PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/cpyext/eval.py

https://bitbucket.org/pypy/pypy/
Python | 230 lines | 177 code | 16 blank | 37 comment | 13 complexity | 7c11e3abc996b9440b730e709002994b MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from pypy.interpreter.error import oefmt
  2. from pypy.interpreter.astcompiler import consts
  3. from rpython.rtyper.lltypesystem import rffi, lltype
  4. from pypy.module.cpyext.api import (
  5. cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP,
  6. cpython_struct, is_valid_fp)
  7. from pypy.module.cpyext.pyobject import PyObject
  8. from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno
  9. from pypy.module.cpyext.funcobject import PyCodeObject
  10. from pypy.module.__builtin__ import compiling
  11. PyCompilerFlags = cpython_struct(
  12. "PyCompilerFlags", (("cf_flags", rffi.INT),))
  13. PyCompilerFlagsPtr = lltype.Ptr(PyCompilerFlags)
  14. PyCF_MASK = (consts.CO_FUTURE_DIVISION |
  15. consts.CO_FUTURE_ABSOLUTE_IMPORT |
  16. consts.CO_FUTURE_WITH_STATEMENT |
  17. consts.CO_FUTURE_PRINT_FUNCTION |
  18. consts.CO_FUTURE_UNICODE_LITERALS)
  19. @cpython_api([PyObject, PyObject, PyObject], PyObject)
  20. def PyEval_CallObjectWithKeywords(space, w_obj, w_arg, w_kwds):
  21. return space.call(w_obj, w_arg, w_kwds)
  22. @cpython_api([], PyObject, result_borrowed=True)
  23. def PyEval_GetBuiltins(space):
  24. """Return a dictionary of the builtins in the current execution
  25. frame, or the interpreter of the thread state if no frame is
  26. currently executing."""
  27. caller = space.getexecutioncontext().gettopframe_nohidden()
  28. if caller is not None:
  29. w_globals = caller.get_w_globals()
  30. w_builtins = space.getitem(w_globals, space.wrap('__builtins__'))
  31. if not space.isinstance_w(w_builtins, space.w_dict):
  32. w_builtins = w_builtins.getdict(space)
  33. else:
  34. w_builtins = space.builtin.getdict(space)
  35. return w_builtins # borrowed ref in all cases
  36. @cpython_api([], PyObject, error=CANNOT_FAIL, result_borrowed=True)
  37. def PyEval_GetLocals(space):
  38. """Return a dictionary of the local variables in the current execution
  39. frame, or NULL if no frame is currently executing."""
  40. caller = space.getexecutioncontext().gettopframe_nohidden()
  41. if caller is None:
  42. return None
  43. return caller.getdictscope() # borrowed ref
  44. @cpython_api([], PyObject, error=CANNOT_FAIL, result_borrowed=True)
  45. def PyEval_GetGlobals(space):
  46. """Return a dictionary of the global variables in the current execution
  47. frame, or NULL if no frame is currently executing."""
  48. caller = space.getexecutioncontext().gettopframe_nohidden()
  49. if caller is None:
  50. return None
  51. return caller.get_w_globals() # borrowed ref
  52. @cpython_api([PyCodeObject, PyObject, PyObject], PyObject)
  53. def PyEval_EvalCode(space, w_code, w_globals, w_locals):
  54. """This is a simplified interface to PyEval_EvalCodeEx(), with just
  55. the code object, and the dictionaries of global and local variables.
  56. The other arguments are set to NULL."""
  57. if w_globals is None:
  58. w_globals = space.w_None
  59. if w_locals is None:
  60. w_locals = space.w_None
  61. return compiling.eval(space, w_code, w_globals, w_locals)
  62. @cpython_api([PyObject, PyObject], PyObject)
  63. def PyObject_CallObject(space, w_obj, w_arg):
  64. """
  65. Call a callable Python object callable_object, with arguments given by the
  66. tuple args. If no arguments are needed, then args may be NULL. Returns
  67. the result of the call on success, or NULL on failure. This is the equivalent
  68. of the Python expression apply(callable_object, args) or
  69. callable_object(*args)."""
  70. return space.call(w_obj, w_arg)
  71. @cpython_api([PyObject, PyObject, PyObject], PyObject)
  72. def PyObject_Call(space, w_obj, w_args, w_kw):
  73. """
  74. Call a callable Python object, with arguments given by the
  75. tuple args, and named arguments given by the dictionary kw. If no named
  76. arguments are needed, kw may be NULL. args must not be NULL, use an
  77. empty tuple if no arguments are needed. Returns the result of the call on
  78. success, or NULL on failure. This is the equivalent of the Python expression
  79. apply(callable_object, args, kw) or callable_object(*args, **kw)."""
  80. return space.call(w_obj, w_args, w_kw)
  81. # These constants are also defined in include/eval.h
  82. Py_single_input = 256
  83. Py_file_input = 257
  84. Py_eval_input = 258
  85. def compile_string(space, source, filename, start, flags=0):
  86. w_source = space.newbytes(source)
  87. start = rffi.cast(lltype.Signed, start)
  88. if start == Py_file_input:
  89. mode = 'exec'
  90. elif start == Py_eval_input:
  91. mode = 'eval'
  92. elif start == Py_single_input:
  93. mode = 'single'
  94. else:
  95. raise oefmt(space.w_ValueError,
  96. "invalid mode parameter for compilation")
  97. return compiling.compile(space, w_source, filename, mode, flags)
  98. def run_string(space, source, filename, start, w_globals, w_locals):
  99. w_code = compile_string(space, source, filename, start)
  100. return compiling.eval(space, w_code, w_globals, w_locals)
  101. @cpython_api([CONST_STRING], rffi.INT_real, error=-1)
  102. def PyRun_SimpleString(space, command):
  103. """This is a simplified interface to PyRun_SimpleStringFlags() below,
  104. leaving the PyCompilerFlags* argument set to NULL."""
  105. command = rffi.charp2str(command)
  106. run_string(space, command, "<string>", Py_file_input,
  107. space.w_None, space.w_None)
  108. return 0
  109. @cpython_api([CONST_STRING, rffi.INT_real,PyObject, PyObject], PyObject)
  110. def PyRun_String(space, source, start, w_globals, w_locals):
  111. """This is a simplified interface to PyRun_StringFlags() below, leaving
  112. flags set to NULL."""
  113. source = rffi.charp2str(source)
  114. filename = "<string>"
  115. return run_string(space, source, filename, start, w_globals, w_locals)
  116. @cpython_api([CONST_STRING, rffi.INT_real, PyObject, PyObject,
  117. PyCompilerFlagsPtr], PyObject)
  118. def PyRun_StringFlags(space, source, start, w_globals, w_locals, flagsptr):
  119. """Execute Python source code from str in the context specified by the
  120. dictionaries globals and locals with the compiler flags specified by
  121. flags. The parameter start specifies the start token that should be used to
  122. parse the source code.
  123. Returns the result of executing the code as a Python object, or NULL if an
  124. exception was raised."""
  125. source = rffi.charp2str(source)
  126. if flagsptr:
  127. flags = rffi.cast(lltype.Signed, flagsptr.c_cf_flags)
  128. else:
  129. flags = 0
  130. w_code = compile_string(space, source, "<string>", start, flags)
  131. return compiling.eval(space, w_code, w_globals, w_locals)
  132. @cpython_api([FILEP, CONST_STRING, rffi.INT_real, PyObject, PyObject], PyObject)
  133. def PyRun_File(space, fp, filename, start, w_globals, w_locals):
  134. """This is a simplified interface to PyRun_FileExFlags() below, leaving
  135. closeit set to 0 and flags set to NULL."""
  136. BUF_SIZE = 8192
  137. source = ""
  138. filename = rffi.charp2str(filename)
  139. buf = lltype.malloc(rffi.CCHARP.TO, BUF_SIZE, flavor='raw')
  140. if not is_valid_fp(fp):
  141. lltype.free(buf, flavor='raw')
  142. PyErr_SetFromErrno(space, space.w_IOError)
  143. return None
  144. try:
  145. while True:
  146. count = fread(buf, 1, BUF_SIZE, fp)
  147. count = rffi.cast(lltype.Signed, count)
  148. source += rffi.charpsize2str(buf, count)
  149. if count < BUF_SIZE:
  150. if feof(fp):
  151. break
  152. PyErr_SetFromErrno(space, space.w_IOError)
  153. finally:
  154. lltype.free(buf, flavor='raw')
  155. return run_string(space, source, filename, start, w_globals, w_locals)
  156. # Undocumented function!
  157. @cpython_api([PyObject, Py_ssize_tP], rffi.INT_real, error=0)
  158. def _PyEval_SliceIndex(space, w_obj, pi):
  159. """Extract a slice index from a PyInt or PyLong or an object with the
  160. nb_index slot defined, and store in *pi.
  161. Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
  162. and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
  163. Return 0 on error, 1 on success.
  164. Note: If v is NULL, return success without storing into *pi. This
  165. is because_PyEval_SliceIndex() is called by apply_slice(), which can be
  166. called by the SLICE opcode with v and/or w equal to NULL.
  167. """
  168. if w_obj is not None:
  169. pi[0] = space.getindex_w(w_obj, None)
  170. return 1
  171. @cpython_api([CONST_STRING, CONST_STRING, rffi.INT_real, PyCompilerFlagsPtr],
  172. PyObject)
  173. def Py_CompileStringFlags(space, source, filename, start, flagsptr):
  174. """Parse and compile the Python source code in str, returning the
  175. resulting code object. The start token is given by start; this
  176. can be used to constrain the code which can be compiled and should
  177. be Py_eval_input, Py_file_input, or Py_single_input. The filename
  178. specified by filename is used to construct the code object and may
  179. appear in tracebacks or SyntaxError exception messages. This
  180. returns NULL if the code cannot be parsed or compiled."""
  181. source = rffi.charp2str(source)
  182. filename = rffi.charp2str(filename)
  183. if flagsptr:
  184. flags = rffi.cast(lltype.Signed, flagsptr.c_cf_flags)
  185. else:
  186. flags = 0
  187. return compile_string(space, source, filename, start, flags)
  188. @cpython_api([PyCompilerFlagsPtr], rffi.INT_real, error=CANNOT_FAIL)
  189. def PyEval_MergeCompilerFlags(space, cf):
  190. """This function changes the flags of the current evaluation
  191. frame, and returns true on success, false on failure."""
  192. flags = rffi.cast(lltype.Signed, cf.c_cf_flags)
  193. result = flags != 0
  194. current_frame = space.getexecutioncontext().gettopframe_nohidden()
  195. if current_frame:
  196. codeflags = current_frame.pycode.co_flags
  197. compilerflags = codeflags & PyCF_MASK
  198. if compilerflags:
  199. result = 1
  200. flags |= compilerflags
  201. # No future keyword at the moment
  202. # if codeflags & CO_GENERATOR_ALLOWED:
  203. # result = 1
  204. # flags |= CO_GENERATOR_ALLOWED
  205. cf.c_cf_flags = rffi.cast(rffi.INT, flags)
  206. return result