[pypy-commit] pypy py3.3: Really implement __qualname__ for nested blocks.
amauryfa
noreply at buildbot.pypy.org
Thu Dec 18 22:38:43 CET 2014
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.3
Changeset: r75022:9ebba4eb7768
Date: 2014-12-18 22:36 +0100
http://bitbucket.org/pypy/pypy/changeset/9ebba4eb7768/
Log: Really implement __qualname__ for nested blocks.
diff --git a/lib-python/3/importlib/_bootstrap.py b/lib-python/3/importlib/_bootstrap.py
--- a/lib-python/3/importlib/_bootstrap.py
+++ b/lib-python/3/importlib/_bootstrap.py
@@ -405,8 +405,10 @@
due to the addition of new opcodes).
"""
-_RAW_MAGIC_NUMBER = 3230 | ord('\r') << 16 | ord('\n') << 24
-_MAGIC_BYTES = bytes(_RAW_MAGIC_NUMBER >> n & 0xff for n in range(0, 25, 8))
+
+# PyPy change
+import _imp
+_MAGIC_BYTES = _imp.get_magic()
_PYCACHE = '__pycache__'
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -157,6 +157,7 @@
def __init__(self, space, name, first_lineno, scope, compile_info):
self.space = space
self.name = name
+ self.qualname = name
self.first_lineno = first_lineno
self.compile_info = compile_info
self.first_block = self.new_block()
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -205,7 +205,8 @@
"""Convenience function for compiling a sub scope."""
generator = kind(self.space, name, node, lineno, self.symbols,
self.compile_info)
- return generator.assemble()
+ generator.qualname = '%s.%s' % (self.qualname, name)
+ return generator.assemble(), generator.qualname
def push_frame_block(self, kind, block):
self.frame_blocks.append((kind, block))
@@ -282,9 +283,11 @@
self.add_none_to_final_return = False
mod.body.walkabout(self)
- def _make_function(self, code, num_defaults=0):
+ def _make_function(self, code, num_defaults=0, qualname=None):
"""Emit the opcodes to turn a code object into a function."""
code_index = self.add_const(code)
+ w_qualname = self.space.wrap(qualname or code.co_name)
+ qualname_index = self.add_const(w_qualname)
if code.co_freevars:
# Load cell and free vars to pass on.
for free in code.co_freevars:
@@ -296,9 +299,11 @@
self.emit_op_arg(ops.LOAD_CLOSURE, index)
self.emit_op_arg(ops.BUILD_TUPLE, len(code.co_freevars))
self.emit_op_arg(ops.LOAD_CONST, code_index)
+ self.emit_op_arg(ops.LOAD_CONST, qualname_index)
self.emit_op_arg(ops.MAKE_CLOSURE, num_defaults)
else:
self.emit_op_arg(ops.LOAD_CONST, code_index)
+ self.emit_op_arg(ops.LOAD_CONST, qualname_index)
self.emit_op_arg(ops.MAKE_FUNCTION, num_defaults)
def _visit_kwonlydefaults(self, args):
@@ -359,9 +364,9 @@
oparg = num_defaults
oparg |= kw_default_count << 8
oparg |= num_annotations << 16
- code = self.sub_scope(FunctionCodeGenerator, func.name, func,
- func.lineno)
- self._make_function(code, oparg)
+ code, qualname = self.sub_scope(FunctionCodeGenerator, func.name, func,
+ func.lineno)
+ self._make_function(code, oparg, qualname=qualname)
# Apply decorators.
if func.decorator_list:
for i in range(len(func.decorator_list)):
@@ -377,20 +382,22 @@
kw_default_count = self._visit_kwonlydefaults(args)
self.visit_sequence(args.defaults)
default_count = len(args.defaults) if args.defaults is not None else 0
- code = self.sub_scope(LambdaCodeGenerator, "<lambda>", lam, lam.lineno)
+ code, qualname = self.sub_scope(
+ LambdaCodeGenerator, "<lambda>", lam, lam.lineno)
oparg = default_count
oparg |= kw_default_count << 8
- self._make_function(code, oparg)
+ self._make_function(code, oparg, qualname=qualname)
def visit_ClassDef(self, cls):
self.update_position(cls.lineno, True)
self.visit_sequence(cls.decorator_list)
# 1. compile the class body into a code object
- code = self.sub_scope(ClassCodeGenerator, cls.name, cls, cls.lineno)
+ code, qualname = self.sub_scope(
+ ClassCodeGenerator, cls.name, cls, cls.lineno)
# 2. load the 'build_class' function
self.emit_op(ops.LOAD_BUILD_CLASS)
# 3. load a function (or closure) made from the code object
- self._make_function(code, 0)
+ self._make_function(code, qualname=qualname)
# 4. load class name
self.load_const(self.space.wrap(cls.name.decode('utf-8')))
# 5. generate the rest of the code for the call
@@ -1140,9 +1147,9 @@
self.use_next_block(anchor)
def _compile_comprehension(self, node, name, sub_scope):
- code = self.sub_scope(sub_scope, name, node, node.lineno)
+ code, qualname = self.sub_scope(sub_scope, name, node, node.lineno)
self.update_position(node.lineno)
- self._make_function(code)
+ self._make_function(code, qualname=qualname)
first_comp = node.get_generators()[0]
assert isinstance(first_comp, ast.comprehension)
first_comp.iter.walkabout(self)
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -36,10 +36,10 @@
'w_kw_defs?']
def __init__(self, space, code, w_globals=None, defs_w=[], w_kw_defs=None,
- closure=None, w_ann=None, forcename=None):
+ closure=None, w_ann=None, forcename=None, qualname=None):
self.space = space
self.name = forcename or code.co_name
- self.qualname = self.name.decode('utf-8') # So far
+ self.qualname = qualname or self.name.decode('utf-8')
self.w_doc = None # lazily read from code.getdocstring()
self.code = code # Code instance
self.w_func_globals = w_globals # the globals dictionary
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -36,7 +36,7 @@
# different value for the highest 16 bits. Bump pypy_incremental_magic every
# time you make pyc files incompatible
-pypy_incremental_magic = 48 # bump it by 16
+pypy_incremental_magic = 64 # bump it by 16
assert pypy_incremental_magic % 16 == 0
assert pypy_incremental_magic < 3000 # the magic number of Python 3. There are
# no known magic numbers below this value
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1215,6 +1215,8 @@
@jit.unroll_safe
def _make_function(self, oparg, freevars=None):
space = self.space
+ w_qualname = self.popvalue()
+ qualname = self.space.unicode_w(w_qualname)
w_codeobj = self.popvalue()
codeobj = self.space.interp_w(PyCode, w_codeobj)
if freevars is not None:
@@ -1238,7 +1240,7 @@
w_def = self.popvalue()
space.setitem(w_kw_defs, w_def, w_name)
fn = function.Function(space, codeobj, self.w_globals, defaultarguments,
- w_kw_defs, freevars, w_ann)
+ w_kw_defs, freevars, w_ann, qualname=qualname)
self.pushvalue(space.wrap(fn))
def MAKE_FUNCTION(self, oparg, next_instr):
@@ -1246,7 +1248,7 @@
@jit.unroll_safe
def MAKE_CLOSURE(self, oparg, next_instr):
- w_freevarstuple = self.peekvalue(1)
+ w_freevarstuple = self.peekvalue(2)
freevars = [self.space.interp_w(Cell, cell)
for cell in self.space.fixedview(w_freevarstuple)]
self._make_function(oparg, freevars)
diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -23,7 +23,7 @@
def test_qualname(self):
def f(): pass
- assert f.__qualname__ == 'f'
+ assert f.__qualname__ == 'test_qualname.f'
f.__qualname__ = 'qualname'
assert f.__qualname__ == 'qualname'
raises(TypeError, "f.__qualname__ = b'name'")
More information about the pypy-commit
mailing list