summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-02-07 17:12:54 (GMT)
committerGitHub <noreply@github.com>2024-02-07 17:12:54 (GMT)
commit967f27d0a18f53670aedab4988da753edaf4312d (patch)
tree4e934b560227542157620d05a44cda91eff27c4f /Python
parenta69e68db6075c6c64d3b97513d9be768037579cb (diff)
downloadcpython-967f27d0a18f53670aedab4988da753edaf4312d.zip
cpython-967f27d0a18f53670aedab4988da753edaf4312d.tar.gz
cpython-967f27d0a18f53670aedab4988da753edaf4312d.tar.bz2
[3.12] gh-114828: Fix __class__ in class-scope inlined comprehensions (GH-115139) (#115140)
gh-114828: Fix __class__ in class-scope inlined comprehensions (GH-115139) (cherry picked from commit fedbf77191ea9d6515b39f958cc9e588d23517c9) Co-authored-by: Carl Meyer <carl@oddbird.net>
Diffstat (limited to 'Python')
-rw-r--r--Python/symtable.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/Python/symtable.c b/Python/symtable.c
index a5c6b46..7972984 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -658,6 +658,8 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
{
PyObject *k, *v;
Py_ssize_t pos = 0;
+ int remove_dunder_class = 0;
+
while (PyDict_Next(comp->ste_symbols, &pos, &k, &v)) {
// skip comprehension parameter
long comp_flags = PyLong_AS_LONG(v);
@@ -679,6 +681,19 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
if (!existing) {
// name does not exist in scope, copy from comprehension
assert(scope != FREE || PySet_Contains(comp_free, k) == 1);
+ if (scope == FREE && ste->ste_type == ClassBlock &&
+ _PyUnicode_EqualToASCIIString(k, "__class__")) {
+ // if __class__ is unbound in the enclosing class scope and free
+ // in the comprehension scope, it needs special handling; just
+ // letting it be marked as free in class scope will break due to
+ // drop_class_free
+ scope = GLOBAL_IMPLICIT;
+ only_flags &= ~DEF_FREE;
+ if (PySet_Discard(comp_free, k) < 0) {
+ return 0;
+ }
+ remove_dunder_class = 1;
+ }
PyObject *v_flags = PyLong_FromLong(only_flags);
if (v_flags == NULL) {
return 0;
@@ -703,6 +718,10 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
}
}
}
+ comp->ste_free = PySet_Size(comp_free) > 0;
+ if (remove_dunder_class && PyDict_DelItemString(comp->ste_symbols, "__class__") < 0) {
+ return 0;
+ }
return 1;
}