]> granicus.if.org Git - python/commitdiff
use a invalid name for the __class__ closure for super() (closes #12370)
authorBenjamin Peterson <benjamin@python.org>
Mon, 20 Jun 2011 00:42:22 +0000 (19:42 -0500)
committerBenjamin Peterson <benjamin@python.org>
Mon, 20 Jun 2011 00:42:22 +0000 (19:42 -0500)
This prevents the assignment of __class__ in the class body from breaking
super. (Although a determined person could do locals()["@__class__"] = 4)

Lib/test/test_super.py
Misc/NEWS
Objects/typeobject.c
Python/compile.c
Python/symtable.c

index 914216d2dabf5ef6d872bf98507f365dad628ff0..298cae001179497c7547502b7628b9ea157a59b2 100644 (file)
@@ -81,6 +81,16 @@ class TestSuper(unittest.TestCase):
 
         self.assertEqual(E().f(), 'AE')
 
+    def test___class___set(self):
+        # See issue #12370
+        class X(A):
+            def f(self):
+                return super().f()
+            __class__ = 413
+        x = X()
+        self.assertEqual(x.f(), 'A')
+        self.assertEqual(x.__class__, 413)
+
 
 def test_main():
     support.run_unittest(TestSuper)
index 89eab0efe98ed130a699e131cf69111b80a9baae..a793d0878bfec739cd1f6ded6c1024bd9130aef2 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
 Core and Builtins
 -----------------
 
+- Issue #12370: Fix super with not arguments when __class__ is overriden in the
+  class body.
+
 - Issue #12084: os.stat on Windows now works properly with relative symbolic
   links when called from any directory.
 
index 02f86ef22b88b052f411a0f089e9e56ec2158249..5b7ab1edfedf29f9e8c14253f319f7f38d2d5d54 100644 (file)
@@ -6399,7 +6399,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 b655c2523a0a57c62d0adaed9872dfea0b55ffaf..567b2302a9140d623e0585ed591005768a67617c 100644 (file)
@@ -1566,7 +1566,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 e31a2ebb394658114e78f3ec23be7a849edaf0ca..b82d8d5b3145dbcb03a295bd54791e18f062ef9e 100644 (file)
@@ -225,10 +225,17 @@ symtable_new(void)
 struct symtable *
 PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
 {
-    struct symtable *st = symtable_new();
+    struct symtable *st;
     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;
@@ -744,8 +751,6 @@ 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;
@@ -783,7 +788,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,
@@ -1143,8 +1148,7 @@ 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 (!GET_IDENTIFIER(__class__) ||
-            !symtable_add_def(st, __class__, DEF_LOCAL) ||
+        if (!symtable_add_def(st, __class__, DEF_LOCAL) ||
             !GET_IDENTIFIER(__locals__) ||
             !symtable_add_def(st, __locals__, DEF_PARAM)) {
             symtable_exit_block(st, s);
@@ -1417,8 +1421,7 @@ 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 (!GET_IDENTIFIER(__class__) ||
-                !symtable_add_def(st, __class__, USE))
+            if (!symtable_add_def(st, __class__, USE))
                 return 0;
         }
         break;