]> granicus.if.org Git - python/commitdiff
Close #14857: fix regression in references to PEP 3135 implicit __class__ closure...
authorNick Coghlan <ncoghlan@gmail.com>
Sun, 27 May 2012 08:17:07 +0000 (18:17 +1000)
committerNick Coghlan <ncoghlan@gmail.com>
Sun, 27 May 2012 08:17:07 +0000 (18:17 +1000)
Lib/test/test_super.py
Lib/unittest/mock.py
Misc/NEWS
Objects/typeobject.c
Python/compile.c
Python/import.c
Python/symtable.c

index 298cae001179497c7547502b7628b9ea157a59b2..32eb1c090917cdbafea5c0d1b55c34c3f9114623 100644 (file)
@@ -81,6 +81,7 @@ class TestSuper(unittest.TestCase):
 
         self.assertEqual(E().f(), 'AE')
 
+    @unittest.expectedFailure
     def test___class___set(self):
         # See issue #12370
         class X(A):
@@ -91,6 +92,29 @@ class TestSuper(unittest.TestCase):
         self.assertEqual(x.f(), 'A')
         self.assertEqual(x.__class__, 413)
 
+    def test___class___instancemethod(self):
+        # See issue #14857
+        class X:
+            def f(self):
+                return __class__
+        self.assertIs(X().f(), X)
+
+    def test___class___classmethod(self):
+        # See issue #14857
+        class X:
+            @classmethod
+            def f(cls):
+                return __class__
+        self.assertIs(X.f(), X)
+
+    def test___class___staticmethod(self):
+        # See issue #14857
+        class X:
+            @staticmethod
+            def f():
+                return __class__
+        self.assertIs(X.f(), X)
+
 
 def test_main():
     support.run_unittest(TestSuper)
index a94acd638e3e65ac6a9e746e974c31bc7c8835c7..36be0fd0381e3aeb3de0a88ea6a392ef04952c33 100644 (file)
@@ -39,6 +39,9 @@ if 'java' in sys.platform:
 
 FILTER_DIR = True
 
+# Workaround for issue #12370
+# Without this, the __class__ properties wouldn't be set correctly
+_safe_super = super
 
 def _is_instance_mock(obj):
     # can't use isinstance on Mock objects because they override __class__
@@ -397,7 +400,7 @@ class NonCallableMock(Base):
         if kwargs:
             self.configure_mock(**kwargs)
 
-        super(NonCallableMock, self).__init__(
+        _safe_super(NonCallableMock, self).__init__(
             spec, wraps, name, spec_set, parent,
             _spec_state
         )
@@ -820,7 +823,7 @@ class CallableMixin(Base):
                  _spec_state=None, _new_name='', _new_parent=None, **kwargs):
         self.__dict__['_mock_return_value'] = return_value
 
-        super(CallableMixin, self).__init__(
+        _safe_super(CallableMixin, self).__init__(
             spec, wraps, name, spec_set, parent,
             _spec_state, _new_name, _new_parent, **kwargs
         )
@@ -1690,7 +1693,7 @@ def _set_return_value(mock, method, name):
 
 class MagicMixin(object):
     def __init__(self, *args, **kw):
-        super(MagicMixin, self).__init__(*args, **kw)
+        _safe_super(MagicMixin, self).__init__(*args, **kw)
         self._mock_set_magics()
 
 
index 57272018d37de2198e9018a2ced66b749e188a3f..512783a0c65043e869d67829aedef2a553b52b15 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.3.0 Alpha 4?
 Core and Builtins
 -----------------
 
+- Issue #14857: fix regression in references to PEP 3135 implicit __class__
+  closure variable (Reopens issue #12370)
+
 - Issue #14712 (PEP 405): Virtual environments. Implemented by Vinay Sajip.
 
 - Issue #14660 (PEP 420): Namespace packages. Implemented by Eric Smith.
index cb4b99b4936a3f2776ecda7fab670c8fe4ebd269..872ed99568e9a9bfdae93c3f15dd4c9bf034b30f 100644 (file)
@@ -6436,7 +6436,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
             PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
             assert(PyUnicode_Check(name));
             if (!PyUnicode_CompareWithASCIIString(name,
-                                                  "@__class__")) {
+                                                  "__class__")) {
                 Py_ssize_t index = co->co_nlocals +
                     PyTuple_GET_SIZE(co->co_cellvars) + i;
                 PyObject *cell = f->f_localsplus[index];
index 10e9ad27f56f5d9ff2cba806b024706d1b40380d..2a1b7546355d78dff1fe47c070c8813cf1f067c4 100644 (file)
@@ -1676,7 +1676,7 @@ compiler_class(struct compiler *c, stmt_ty s)
             return 0;
         }
         /* return the (empty) __class__ cell */
-        str = PyUnicode_InternFromString("@__class__");
+        str = PyUnicode_InternFromString("__class__");
         if (str == NULL) {
             compiler_exit_scope(c);
             return 0;
index ab6ff864a5b4e9f05ed32f264268adc24ff7ace5..98d9dc5d7036b663452f2bc1340421f4db130fb3 100644 (file)
@@ -106,6 +106,7 @@ typedef unsigned short mode_t;
        Python 3.3a0  3200 (__qualname__ added)
                      3210 (added size modulo 2**32 to the pyc header)
        Python 3.3a1  3220 (changed PEP 380 implementation)
+       Python 3.3a4  3230 (revert changes to implicit __class__ closure)
 */
 
 /* MAGIC must change whenever the bytecode emitted by the compiler may no
@@ -118,7 +119,7 @@ typedef unsigned short mode_t;
 #define STRIFY(name) QUOTE(name)
 #define MAJOR STRIFY(PY_MAJOR_VERSION)
 #define MINOR STRIFY(PY_MINOR_VERSION)
-#define MAGIC (3220 | ((long)'\r'<<16) | ((long)'\n'<<24))
+#define MAGIC (3230 | ((long)'\r'<<16) | ((long)'\n'<<24))
 #define TAG "cpython-" MAJOR MINOR;
 #define CACHEDIR "__pycache__"
 /* Current magic word and string tag as globals. */
index b6228356bf093c7225f478f82fc21e6c2fbb5d3d..a0b786b3d7a5fd627256b8af584a4e64d2a647e7 100644 (file)
@@ -221,17 +221,10 @@ symtable_new(void)
 struct symtable *
 PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
 {
-    struct symtable *st;
+    struct symtable *st = symtable_new();
     asdl_seq *seq;
     int i;
 
-    if (__class__ == NULL) {
-        __class__ = PyUnicode_InternFromString("@__class__");
-        if (__class__ == NULL)
-            return NULL;
-    }
-
-    st = symtable_new();
     if (st == NULL)
         return st;
     st->st_filename = filename;
@@ -747,6 +740,8 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
     }
     else {
         /* Special-case __class__ */
+        if (!GET_IDENTIFIER(__class__))
+            goto error;
         assert(PySet_Contains(local, __class__) == 1);
         if (PySet_Add(newbound, __class__) < 0)
             goto error;
@@ -784,7 +779,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
                                                          NULL))
         goto error;
     else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree,
-                                                           "@__class__"))
+                                                           "__class__"))
         goto error;
     /* Records the results of the analysis in the symbol table entry */
     if (!update_symbols(ste->ste_symbols, scopes, bound, newfree,
@@ -1111,7 +1106,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
         if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
                                   (void *)s, s->lineno, s->col_offset))
             return 0;
-        if (!symtable_add_def(st, __class__, DEF_LOCAL) ||
+        if (!GET_IDENTIFIER(__class__) ||
+            !symtable_add_def(st, __class__, DEF_LOCAL) ||
             !GET_IDENTIFIER(__locals__) ||
             !symtable_add_def(st, __locals__, DEF_PARAM)) {
             symtable_exit_block(st, s);
@@ -1376,7 +1372,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
         if (e->v.Name.ctx == Load &&
             st->st_cur->ste_type == FunctionBlock &&
             !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) {
-            if (!symtable_add_def(st, __class__, USE))
+            if (!GET_IDENTIFIER(__class__) ||
+                !symtable_add_def(st, __class__, USE))
                 return 0;
         }
         break;