summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2011-06-20 00:42:22 (GMT)
committerBenjamin Peterson <benjamin@python.org>2011-06-20 00:42:22 (GMT)
commitf5ff22329b3a4838054dfadfad74fc5a0519cbb2 (patch)
treecbf644106089a69d028c954e246dab129b3d02cd
parent019d0f27a3fc8d4daa7caea8c041cd26d5873950 (diff)
downloadcpython-f5ff22329b3a4838054dfadfad74fc5a0519cbb2.zip
cpython-f5ff22329b3a4838054dfadfad74fc5a0519cbb2.tar.gz
cpython-f5ff22329b3a4838054dfadfad74fc5a0519cbb2.tar.bz2
use a invalid name for the __class__ closure for super() (closes #12370)
This prevents the assignment of __class__ in the class body from breaking super. (Although a determined person could do locals()["@__class__"] = 4)
-rw-r--r--Lib/test/test_super.py10
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/typeobject.c2
-rw-r--r--Python/compile.c2
-rw-r--r--Python/symtable.c19
5 files changed, 26 insertions, 10 deletions
diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py
index 914216d..298cae0 100644
--- a/Lib/test/test_super.py
+++ b/Lib/test/test_super.py
@@ -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)
diff --git a/Misc/NEWS b/Misc/NEWS
index 89eab0e..a793d08 100644
--- 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.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 02f86ef..5b7ab1e 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -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];
diff --git a/Python/compile.c b/Python/compile.c
index b655c25..567b230 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -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;
diff --git a/Python/symtable.c b/Python/symtable.c
index e31a2eb..b82d8d5 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -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;