diff Python/compile.c @ 83783:3d858f1eef54

hide the __class__ closure from the class body (#12370)
author Benjamin Peterson <benjamin@python.org>
date Wed, 15 May 2013 15:26:42 -0500
parents cf65c7a75f55
children 6db3741e59be
line wrap: on
line diff
--- a/Python/compile.c	Wed May 15 19:43:15 2013 +0200
+++ b/Python/compile.c	Wed May 15 15:26:42 2013 -0500
@@ -535,6 +535,37 @@
         compiler_unit_free(u);
         return 0;
     }
+    if (u->u_ste->ste_needs_class_closure) {
+        /* Cook up a implicit __class__ cell. */
+        _Py_IDENTIFIER(__class__);
+        PyObject *tuple, *name, *zero;
+        int res;
+        assert(u->u_scope_type == COMPILER_SCOPE_CLASS);
+        assert(PyDict_Size(u->u_cellvars) == 0);
+        name = _PyUnicode_FromId(&PyId___class__);
+        if (!name) {
+            compiler_unit_free(u);
+            return 0;
+        }
+        tuple = PyTuple_Pack(2, name, Py_TYPE(name));
+        if (!tuple) {
+            compiler_unit_free(u);
+            return 0;
+        }
+        zero = PyLong_FromLong(0);
+        if (!zero) {
+            Py_DECREF(tuple);
+            compiler_unit_free(u);
+            return 0;
+        }
+        res = PyDict_SetItem(u->u_cellvars, tuple, zero);
+        Py_DECREF(tuple);
+        Py_DECREF(zero);
+        if (res < 0) {
+            compiler_unit_free(u);
+            return 0;
+        }
+    }
 
     u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS,
                                PyDict_Size(u->u_cellvars));
@@ -1331,6 +1362,9 @@
 static int
 get_ref_type(struct compiler *c, PyObject *name)
 {
+    if (c->u->u_scope_type == COMPILER_SCOPE_CLASS &&
+        !PyUnicode_CompareWithASCIIString(name, "__class__"))
+        return CELL;
     int scope = PyST_GetScope(c->u->u_ste, name);
     if (scope == 0) {
         char buf[350];
@@ -1704,23 +1738,23 @@
             compiler_exit_scope(c);
             return 0;
         }
-        /* return the (empty) __class__ cell */
-        str = PyUnicode_InternFromString("__class__");
-        if (str == NULL) {
-            compiler_exit_scope(c);
-            return 0;
-        }
-        i = compiler_lookup_arg(c->u->u_cellvars, str);
-        Py_DECREF(str);
-        if (i == -1) {
-            /* This happens when nobody references the cell */
-            PyErr_Clear();
-            /* Return None */
-            ADDOP_O(c, LOAD_CONST, Py_None, consts);
+        if (c->u->u_ste->ste_needs_class_closure) {
+            /* return the (empty) __class__ cell */
+            str = PyUnicode_InternFromString("__class__");
+            if (str == NULL) {
+                compiler_exit_scope(c);
+                return 0;
+            }
+            i = compiler_lookup_arg(c->u->u_cellvars, str);
+            Py_DECREF(str);
+            assert(i == 0);
+            /* Return the cell where to store __class__ */
+            ADDOP_I(c, LOAD_CLOSURE, i);
         }
         else {
-            /* Return the cell where to store __class__ */
-            ADDOP_I(c, LOAD_CLOSURE, i);
+            assert(PyDict_Size(c->u->u_cellvars) == 0);
+            /* This happens when nobody references the cell. Return None. */
+            ADDOP_O(c, LOAD_CONST, Py_None, consts);
         }
         ADDOP_IN_SCOPE(c, RETURN_VALUE);
         /* create the code object */