[pypy-commit] pypy py3k: kill prepare_exec, most of it was already reimpl. in rpython anyway,
pjenvey
noreply at buildbot.pypy.org
Fri Dec 14 00:36:22 CET 2012
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r59419:114108122293
Date: 2012-12-13 15:12 -0800
http://bitbucket.org/pypy/pypy/changeset/114108122293/
Log: kill prepare_exec, most of it was already reimpl. in rpython anyway,
cleanup/reuse its replacements in compile/eval/exec. support
memoryview source
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -498,23 +498,30 @@
self.w_locals = self.popvalue()
def exec_(self, w_prog, w_globals, w_locals):
- """The ___builtin__.exec function."""
- ec = self.space.getexecutioncontext()
+ """The builtins.exec function."""
+ space = self.space
+ ec = space.getexecutioncontext()
flags = ec.compiler.getcodeflags(self.pycode)
- w_compile_flags = self.space.wrap(flags)
- w_resulttuple = prepare_exec(self.space, self.space.wrap(self), w_prog,
- w_globals, w_locals,
- w_compile_flags,
- self.space.wrap(self.get_builtin()),
- self.space.gettypeobject(PyCode.typedef))
- w_prog, w_globals, w_locals = self.space.fixedview(w_resulttuple, 3)
+
+ if space.isinstance_w(w_prog, space.gettypeobject(PyCode.typedef)):
+ code = space.interp_w(PyCode, w_prog)
+ else:
+ from pypy.interpreter.astcompiler import consts
+ flags |= consts.PyCF_SOURCE_IS_UTF8
+ source, flags = source_as_str(
+ space, w_prog, 'exec', "string, bytes or code", flags)
+ code = ec.compiler.compile(source, "<string>", 'exec', flags)
+
+ w_globals, w_locals = ensure_ns(space, w_globals, w_locals, 'exec',
+ self)
+ space.call_method(w_globals, 'setdefault', space.wrap('__builtins__'),
+ space.wrap(self.get_builtin()))
plain = (self.w_locals is not None and
- self.space.is_w(w_locals, self.w_locals))
+ space.is_w(w_locals, self.w_locals))
if plain:
w_locals = self.getdictscope()
- co = self.space.interp_w(eval.Code, w_prog)
- co.exec_code(self.space, w_globals, w_locals)
+ code.exec_code(space, w_globals, w_locals)
if plain:
self.setdictscope(w_locals)
@@ -1369,6 +1376,58 @@
self.operr = operr
+def source_as_str(space, w_source, funcname, what, flags):
+ """Return an unwrapped string (without NUL bytes) from some kind of
+ wrapped source string and adjusted compiler flags"""
+ from pypy.interpreter.astcompiler import consts
+
+ if space.isinstance_w(w_source, space.w_unicode):
+ source = space.unicode0_w(w_source).encode('utf-8')
+ flags |= consts.PyCF_IGNORE_COOKIE
+ elif space.isinstance_w(w_source, space.w_bytes):
+ source = space.bytes0_w(w_source)
+ else:
+ try:
+ source = space.bufferstr0_new_w(w_source)
+ except OperationError as e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ raise operationerrfmt(space.w_TypeError,
+ "%s() arg 1 must be a %s object",
+ funcname, what)
+ return source, flags
+
+
+def ensure_ns(space, w_globals, w_locals, funcname, caller=None):
+ """Ensure globals/locals exist and are of the correct type"""
+ if (not space.is_none(w_globals) and
+ not space.isinstance_w(w_globals, space.w_dict)):
+ raise operationerrfmt(space.w_TypeError,
+ '%s() arg 2 must be a dict, not %s',
+ funcname, space.type(w_globals).getname(space))
+ if (not space.is_none(w_locals) and
+ space.lookup(w_locals, '__getitem__') is None):
+ raise operationerrfmt(space.w_TypeError,
+ '%s() arg 3 must be a mapping or None, not %s',
+ funcname, space.type(w_locals).getname(space))
+
+ if space.is_none(w_globals):
+ if caller is None:
+ caller = space.getexecutioncontext().gettopframe_nohidden()
+ if caller is None:
+ w_globals = space.newdict()
+ if space.is_none(w_locals):
+ w_locals = w_globals
+ else:
+ w_globals = caller.w_globals
+ if space.is_none(w_locals):
+ w_locals = caller.getdictscope()
+ elif space.is_none(w_locals):
+ w_locals = w_globals
+
+ return w_globals, w_locals
+
+
### helpers written at the application-level ###
# Some of these functions are expected to be generally useful if other
# parts of the code need to do the same thing as a non-trivial opcode,
@@ -1485,43 +1544,3 @@
''', filename=__file__)
import_all_from = app.interphook('import_all_from')
-
-app = gateway.applevel(r'''
- def prepare_exec(f, prog, globals, locals, compile_flags, builtin, codetype):
- """Manipulate parameters to exec statement to (codeobject, dict, dict).
- """
- if (globals is None and locals is None and
- isinstance(prog, tuple) and
- (len(prog) == 2 or len(prog) == 3)):
- globals = prog[1]
- if len(prog) == 3:
- locals = prog[2]
- prog = prog[0]
- if globals is None:
- globals = f.f_globals
- if locals is None:
- locals = f.f_locals
- if locals is None:
- locals = globals
-
- if not isinstance(globals, dict):
- raise TypeError(
- "exec() arg 2 must be a dict or None, not %s" %
- type(globals).__name__)
- globals.setdefault('__builtins__', builtin)
- if not isinstance(locals, dict):
- if not hasattr(locals, '__getitem__'):
- raise TypeError(
- "exec() arg 3 must be a mapping or None, not %s" %
- type(locals).__name__)
-
- if not isinstance(prog, codetype):
- filename = '<string>'
- if not isinstance(prog, (str, bytes)):
- raise TypeError("exec() arg 1 must be a string, bytes, "
- "or code object")
- prog = compile(prog, filename, 'exec', compile_flags, 1)
- return (prog, globals, locals)
-''', filename=__file__)
-
-prepare_exec = app.interphook('prepare_exec')
diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -3,7 +3,7 @@
"""
from pypy.interpreter.pycode import PyCode
-from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.error import OperationError
from pypy.interpreter.astcompiler import consts, ast
from pypy.interpreter.gateway import unwrap_spec
from pypy.interpreter.argument import Arguments
@@ -25,7 +25,7 @@
compile; if absent or zero these statements do influence the compilation,
in addition to any features explicitly specified.
"""
-
+ from pypy.interpreter.pyopcode import source_as_str
ec = space.getexecutioncontext()
if flags & ~(ec.compiler.compiler_flags | consts.PyCF_ONLY_AST |
consts.PyCF_DONT_IMPLY_DEDENT | consts.PyCF_SOURCE_IS_UTF8):
@@ -33,23 +33,13 @@
space.wrap("compile() unrecognized flags"))
flags |= consts.PyCF_SOURCE_IS_UTF8
- ast_node = None
- w_ast_type = space.gettypeobject(ast.AST.typedef)
- source_str = None
- if space.is_true(space.isinstance(w_source, w_ast_type)):
+ ast_node = source = None
+ if space.isinstance_w(w_source, space.gettypeobject(ast.AST.typedef)):
ast_node = space.interp_w(ast.mod, w_source)
ast_node.sync_app_attrs(space)
- elif space.isinstance_w(w_source, space.w_unicode):
- w_utf_8_source = space.call_method(w_source, "encode",
- space.wrap("utf-8"))
- source_str = space.bytes0_w(w_utf_8_source)
- flags |= consts.PyCF_IGNORE_COOKIE
- elif space.isinstance_w(w_source, space.w_bytes):
- source_str = space.bytes0_w(w_source)
else:
- msg = space.wrap(
- "compile() arg 1 must be a string, bytes, AST or code object")
- raise OperationError(space.w_TypeError, msg)
+ source, flags = source_as_str(space, w_source, 'compile',
+ "string, bytes, AST or code", flags)
if not dont_inherit:
caller = ec.gettopframe_nohidden()
@@ -58,16 +48,16 @@
if mode not in ('exec', 'eval', 'single'):
raise OperationError(space.w_ValueError,
- space.wrap("compile() arg 3 must be 'exec' "
- "or 'eval' or 'single'"))
+ space.wrap("compile() arg 3 must be 'exec', "
+ "'eval' or 'single'"))
# XXX optimize is not used
if ast_node is None:
if flags & consts.PyCF_ONLY_AST:
- mod = ec.compiler.compile_to_ast(source_str, filename, mode, flags)
+ mod = ec.compiler.compile_to_ast(source, filename, mode, flags)
return space.wrap(mod)
else:
- code = ec.compiler.compile(source_str, filename, mode, flags)
+ code = ec.compiler.compile(source, filename, mode, flags)
else:
code = ec.compiler.compile_ast(ast_node, filename, mode, flags)
return space.wrap(code)
@@ -80,58 +70,36 @@
are dictionaries, defaulting to the current current globals and locals.
If only globals is given, locals defaults to it.
"""
- w = space.wrap
+ from pypy.interpreter.pyopcode import ensure_ns, source_as_str
+ w_globals, w_locals = ensure_ns(space, w_globals, w_locals, 'eval')
- is_unicode = space.is_true(space.isinstance(w_code, space.w_unicode))
- if (is_unicode or space.is_true(space.isinstance(w_code, space.w_bytes))):
- w_strip = w(u' \t') if is_unicode else space.wrapbytes(' \t')
- # XXX: w_code.lstrip could be overriden
- w_code = compile(space, space.call_method(w_code, 'lstrip', w_strip),
- "<string>", "eval")
+ if space.isinstance_w(w_code, space.gettypeobject(PyCode.typedef)):
+ code = space.interp_w(PyCode, w_code)
+ else:
+ source, flags = source_as_str(space, w_code, 'eval',
+ "string, bytes or code",
+ consts.PyCF_SOURCE_IS_UTF8)
+ # source.lstrip(' \t')
+ i = 0
+ for c in source:
+ if c not in ' \t':
+ if i:
+ source = source[i:]
+ break
+ i += 1
- codeobj = space.interpclass_w(w_code)
- if not isinstance(codeobj, PyCode):
- raise OperationError(space.w_TypeError,
- w('eval() arg 1 must be a string or code object'))
-
- if (not space.is_none(w_globals) and
- not space.isinstance_w(w_globals, space.w_dict)):
- raise operationerrfmt(space.w_TypeError,
- 'eval() arg 2 must be a dict, not %s',
- space.type(w_globals).getname(space))
- if (not space.is_none(w_locals) and
- space.lookup(w_locals, '__getitem__') is None):
- raise operationerrfmt(space.w_TypeError,
- 'eval() arg 3 must be a mapping or None, not %s',
- space.type(w_locals).getname(space))
-
- if space.is_none(w_globals):
- caller = space.getexecutioncontext().gettopframe_nohidden()
- if caller is None:
- w_globals = space.newdict()
- if space.is_none(w_locals):
- w_locals = w_globals
- else:
- w_globals = caller.w_globals
- if space.is_none(w_locals):
- w_locals = caller.getdictscope()
- elif space.is_none(w_locals):
- w_locals = w_globals
+ ec = space.getexecutioncontext()
+ code = ec.compiler.compile(source, "<string>", 'eval', flags)
# xxx removed: adding '__builtins__' to the w_globals dict, if there
# is none. This logic was removed as costly (it requires to get at
# the gettopframe_nohidden()). I bet no test fails, and it's a really
# obscure case.
- return codeobj.exec_code(space, w_globals, w_locals)
+ return code.exec_code(space, w_globals, w_locals)
def exec_(space, w_prog, w_globals=None, w_locals=None):
- if w_globals is None:
- w_globals = space.w_None
- if w_locals is None:
- w_locals = space.w_None
- ec = space.getexecutioncontext()
- frame = ec.gettopframe_nohidden()
+ frame = space.getexecutioncontext().gettopframe_nohidden()
frame.exec_(w_prog, w_globals, w_locals)
def build_class(space, w_func, w_name, __args__):
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -495,6 +495,15 @@
assert ns['foo'] == 'café'
assert eval(b"# coding: latin1\n'caf\xe9'\n") == 'café'
+ def test_memoryview_compile(self):
+ m = memoryview(b'2 + 1')
+ co = compile(m, 'baz', 'eval')
+ assert eval(co) == 3
+ assert eval(m) == 3
+ ns = {}
+ exec(memoryview(b'r = 2 + 1'), ns)
+ assert ns['r'] == 3
+
def test_recompile_ast(self):
import _ast
# raise exception when node type doesn't match with compile mode
More information about the pypy-commit
mailing list