[pypy-commit] pypy py3k: Expose the __class__ cell to Python code.

mjacob noreply at buildbot.pypy.org
Fri Jun 5 18:42:46 CEST 2015


Author: Manuel Jacob <me at manueljacob.de>
Branch: py3k
Changeset: r77917:070a2053d3fe
Date: 2015-06-05 18:42 +0200
http://bitbucket.org/pypy/pypy/changeset/070a2053d3fe/

Log:	Expose the __class__ cell to Python code.

	This fixes issue #1930.

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
@@ -1339,10 +1339,10 @@
         # compile the body proper
         self._handle_body(cls.body)
         # return the (empty) __class__ cell
-        scope = self.scope.lookup("@__class__")
+        scope = self.scope.lookup("__class__")
         if scope == symtable.SCOPE_CELL:
             # Return the cell where to store __class__
-            self.emit_op_arg(ops.LOAD_CLOSURE, self.cell_vars["@__class__"])
+            self.emit_op_arg(ops.LOAD_CLOSURE, self.cell_vars["__class__"])
         else:
             # This happens when nobody references the cell
             self.load_const(self.space.w_None)
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
@@ -242,7 +242,7 @@
     def note_symbol(self, identifier, role):
         # Special-case super: it counts as a use of __class__
         if role == SYM_USED and identifier == 'super':
-            self.note_symbol('@__class__', SYM_USED)
+            self.note_symbol('__class__', SYM_USED)
         return Scope.note_symbol(self, identifier, role)
 
     def note_yield(self, yield_node):
@@ -300,12 +300,12 @@
         return misc.mangle(name, self.name)
 
     def _pass_special_names(self, local, new_bound):
-        assert '@__class__' in local
-        new_bound['@__class__'] = None
+        assert '__class__' in local
+        new_bound['__class__'] = None
 
     def _finalize_cells(self, free):
         for name, role in self.symbols.iteritems():
-            if role == SCOPE_LOCAL and name in free and name == '@__class__':
+            if role == SCOPE_LOCAL and name in free and name == '__class__':
                 self.symbols[name] = SCOPE_CELL
                 del free[name]
 
@@ -394,7 +394,7 @@
             clsdef.kwargs.walkabout(self)
         self.visit_sequence(clsdef.decorator_list)
         self.push_scope(ClassScope(clsdef), clsdef)
-        self.note_symbol('@__class__', SYM_ASSIGNED)
+        self.note_symbol('__class__', SYM_ASSIGNED)
         self.note_symbol('__locals__', SYM_PARAM)
         self.visit_sequence(clsdef.body)
         self.pop_scope()
diff --git a/pypy/interpreter/test/test_class.py b/pypy/interpreter/test/test_class.py
--- a/pypy/interpreter/test/test_class.py
+++ b/pypy/interpreter/test/test_class.py
@@ -109,3 +109,9 @@
         c = C()
         assert c.one == "two"
         raises(AttributeError, getattr, c, "two")
+
+    def test___class__(self):
+        class C(object):
+            def get_class(self):
+                return __class__
+        assert C().get_class()
diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py
--- a/pypy/module/__builtin__/descriptor.py
+++ b/pypy/module/__builtin__/descriptor.py
@@ -67,7 +67,7 @@
                     "super(): arg[0] deleted"))
         index = 0
         for name in code.co_freevars:
-            if name == "@__class__":
+            if name == "__class__":
                 break
             index += 1
         else:


More information about the pypy-commit mailing list