[pypy-commit] pypy py3.5: More hacks to make the cell '__class__' in class bodies work
arigo
pypy.commits at gmail.com
Wed Dec 7 08:44:46 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r88937:061607b3f6ed
Date: 2016-12-07 14:44 +0100
http://bitbucket.org/pypy/pypy/changeset/061607b3f6ed/
Log: More hacks to make the cell '__class__' in class bodies work
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
@@ -137,11 +137,11 @@
return ''.join(code)
-def _make_index_dict_filter(syms, flag):
+def _make_index_dict_filter(syms, flag1, flag2):
i = 0
result = {}
for name, scope in syms.iteritems():
- if scope == flag:
+ if scope in (flag1, flag2):
result[name] = i
i += 1
return result
@@ -170,7 +170,8 @@
self.names = {}
self.var_names = _iter_to_dict(scope.varnames)
self.cell_vars = _make_index_dict_filter(scope.symbols,
- symtable.SCOPE_CELL)
+ symtable.SCOPE_CELL,
+ symtable.SCOPE_CELL_CLASS)
self.free_vars = _iter_to_dict(scope.free_vars, len(self.cell_vars))
self.w_consts = space.newdict()
self.argcount = 0
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
@@ -317,7 +317,8 @@
# Load cell and free vars to pass on.
for free in code.co_freevars:
free_scope = self.scope.lookup(free)
- if free_scope == symtable.SCOPE_CELL:
+ if free_scope in (symtable.SCOPE_CELL,
+ symtable.SCOPE_CELL_CLASS):
index = self.cell_vars[free]
else:
index = self.free_vars[free]
@@ -1626,7 +1627,7 @@
self._handle_body(cls.body)
# return the (empty) __class__ cell
scope = self.scope.lookup("__class__")
- if scope == symtable.SCOPE_CELL:
+ if scope == symtable.SCOPE_CELL_CLASS:
# Return the cell where to store __class__
self.emit_op_arg(ops.LOAD_CLOSURE, self.cell_vars["__class__"])
else:
diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py
--- a/pypy/interpreter/astcompiler/symtable.py
+++ b/pypy/interpreter/astcompiler/symtable.py
@@ -21,6 +21,7 @@
SCOPE_LOCAL = 3
SCOPE_FREE = 4
SCOPE_CELL = 5
+SCOPE_CELL_CLASS = 6 # for "__class__" inside class bodies only
class Scope(object):
@@ -336,7 +337,7 @@
def _finalize_cells(self, free):
for name, role in self.symbols.iteritems():
if role == SCOPE_LOCAL and name in free and name == '__class__':
- self.symbols[name] = SCOPE_CELL
+ self.symbols[name] = SCOPE_CELL_CLASS
del free[name]
diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -398,6 +398,13 @@
# in CPython 3.5.2. Looks like a bug to me
def testing():
return 42
+''', '''
+class Y:
+ def f():
+ __class__
+ __class__ = 42
+def testing():
+ return Y.__dict__['__class__']
'''
]:
space.call_args(w_filterwarnings, filter_arg)
More information about the pypy-commit
mailing list