Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f5ff223

Browse files
committed
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)
1 parent 019d0f2 commit f5ff223

5 files changed

Lines changed: 26 additions & 10 deletions

File tree

Lib/test/test_super.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ def nested():
8181

8282
self.assertEqual(E().f(), 'AE')
8383

84+
def test___class___set(self):
85+
# See issue #12370
86+
class X(A):
87+
def f(self):
88+
return super().f()
89+
__class__ = 413
90+
x = X()
91+
self.assertEqual(x.f(), 'A')
92+
self.assertEqual(x.__class__, 413)
93+
8494

8595
def test_main():
8696
support.run_unittest(TestSuper)

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #12370: Fix super with not arguments when __class__ is overriden in the
14+
class body.
15+
1316
- Issue #12084: os.stat on Windows now works properly with relative symbolic
1417
links when called from any directory.
1518

Objects/typeobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6399,7 +6399,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
63996399
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
64006400
assert(PyUnicode_Check(name));
64016401
if (!PyUnicode_CompareWithASCIIString(name,
6402-
"__class__")) {
6402+
"@__class__")) {
64036403
Py_ssize_t index = co->co_nlocals +
64046404
PyTuple_GET_SIZE(co->co_cellvars) + i;
64056405
PyObject *cell = f->f_localsplus[index];

Python/compile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1566,7 +1566,7 @@ compiler_class(struct compiler *c, stmt_ty s)
15661566
return 0;
15671567
}
15681568
/* return the (empty) __class__ cell */
1569-
str = PyUnicode_InternFromString("__class__");
1569+
str = PyUnicode_InternFromString("@__class__");
15701570
if (str == NULL) {
15711571
compiler_exit_scope(c);
15721572
return 0;

Python/symtable.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,17 @@ symtable_new(void)
225225
struct symtable *
226226
PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
227227
{
228-
struct symtable *st = symtable_new();
228+
struct symtable *st;
229229
asdl_seq *seq;
230230
int i;
231231

232+
if (__class__ == NULL) {
233+
__class__ = PyUnicode_InternFromString("@__class__");
234+
if (__class__ == NULL)
235+
return NULL;
236+
}
237+
238+
st = symtable_new();
232239
if (st == NULL)
233240
return st;
234241
st->st_filename = filename;
@@ -744,8 +751,6 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
744751
}
745752
else {
746753
/* Special-case __class__ */
747-
if (!GET_IDENTIFIER(__class__))
748-
goto error;
749754
assert(PySet_Contains(local, __class__) == 1);
750755
if (PySet_Add(newbound, __class__) < 0)
751756
goto error;
@@ -783,7 +788,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
783788
NULL))
784789
goto error;
785790
else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree,
786-
"__class__"))
791+
"@__class__"))
787792
goto error;
788793
/* Records the results of the analysis in the symbol table entry */
789794
if (!update_symbols(ste->ste_symbols, scopes, bound, newfree,
@@ -1143,8 +1148,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
11431148
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
11441149
(void *)s, s->lineno, s->col_offset))
11451150
return 0;
1146-
if (!GET_IDENTIFIER(__class__) ||
1147-
!symtable_add_def(st, __class__, DEF_LOCAL) ||
1151+
if (!symtable_add_def(st, __class__, DEF_LOCAL) ||
11481152
!GET_IDENTIFIER(__locals__) ||
11491153
!symtable_add_def(st, __locals__, DEF_PARAM)) {
11501154
symtable_exit_block(st, s);
@@ -1417,8 +1421,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
14171421
if (e->v.Name.ctx == Load &&
14181422
st->st_cur->ste_type == FunctionBlock &&
14191423
!PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) {
1420-
if (!GET_IDENTIFIER(__class__) ||
1421-
!symtable_add_def(st, __class__, USE))
1424+
if (!symtable_add_def(st, __class__, USE))
14221425
return 0;
14231426
}
14241427
break;

0 commit comments

Comments
 (0)