https://github.com/python/cpython/commit/664965a1c141e8af5eb465d29099781a6a2fc3f3
commit: 664965a1c141e8af5eb465d29099781a6a2fc3f3
branch: main
author: wookie184 <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-02-17T12:06:31Z
summary:
gh-96497: Mangle name before symtable lookup in
'symtable_extend_namedexpr_scope' (GH-96561)
files:
A Misc/NEWS.d/next/Core and
Builtins/2022-09-04-16-51-56.gh-issue-96497.HTBuIL.rst
M Lib/test/test_named_expressions.py
M Python/symtable.c
diff --git a/Lib/test/test_named_expressions.py
b/Lib/test/test_named_expressions.py
index 7b2fa844827ae9..f2017bdffcf968 100644
--- a/Lib/test/test_named_expressions.py
+++ b/Lib/test/test_named_expressions.py
@@ -298,6 +298,16 @@ def
test_named_expression_invalid_set_comprehension_iterable_expression(self):
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
+ def test_named_expression_invalid_mangled_class_variables(self):
+ code = """class Foo:
+ def bar(self):
+ [[(__x:=2) for _ in range(2)] for __x in range(2)]
+ """
+
+ with self.assertRaisesRegex(SyntaxError,
+ "assignment expression cannot rebind comprehension iteration
variable '__x'"):
+ exec(code, {}, {})
+
class NamedExpressionAssignmentTest(unittest.TestCase):
@@ -674,6 +684,18 @@ def test_named_expression_scope_in_genexp(self):
for idx, elem in enumerate(genexp):
self.assertEqual(elem, b[idx] + a)
+ def test_named_expression_scope_mangled_names(self):
+ class Foo:
+ def f(self_):
+ global __x1
+ __x1 = 0
+ [_Foo__x1 := 1 for a in [2]]
+ self.assertEqual(__x1, 1)
+ [__x1 := 2 for a in [3]]
+ self.assertEqual(__x1, 2)
+
+ Foo().f()
+ self.assertEqual(_Foo__x1, 2)
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/Core and
Builtins/2022-09-04-16-51-56.gh-issue-96497.HTBuIL.rst b/Misc/NEWS.d/next/Core
and Builtins/2022-09-04-16-51-56.gh-issue-96497.HTBuIL.rst
new file mode 100644
index 00000000000000..6881dde2e6cf44
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and
Builtins/2022-09-04-16-51-56.gh-issue-96497.HTBuIL.rst
@@ -0,0 +1,2 @@
+Fix incorrect resolution of mangled class variables used in assignment
+expressions in comprehensions.
diff --git a/Python/symtable.c b/Python/symtable.c
index d69516351efba2..b69452bf77c517 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -1359,16 +1359,22 @@ symtable_enter_block(struct symtable *st, identifier
name, _Py_block_ty block,
}
static long
-symtable_lookup(struct symtable *st, PyObject *name)
+symtable_lookup_entry(struct symtable *st, PySTEntryObject *ste, PyObject
*name)
{
PyObject *mangled = _Py_Mangle(st->st_private, name);
if (!mangled)
return 0;
- long ret = _PyST_GetSymbol(st->st_cur, mangled);
+ long ret = _PyST_GetSymbol(ste, mangled);
Py_DECREF(mangled);
return ret;
}
+static long
+symtable_lookup(struct symtable *st, PyObject *name)
+{
+ return symtable_lookup_entry(st, st->st_cur, name);
+}
+
static int
symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct
_symtable_entry *ste,
int lineno, int col_offset, int end_lineno, int
end_col_offset)
@@ -2009,7 +2015,7 @@ symtable_extend_namedexpr_scope(struct symtable *st,
expr_ty e)
* binding conflict with iteration variables, otherwise skip it
*/
if (ste->ste_comprehension) {
- long target_in_scope = _PyST_GetSymbol(ste, target_name);
+ long target_in_scope = symtable_lookup_entry(st, ste, target_name);
if ((target_in_scope & DEF_COMP_ITER) &&
(target_in_scope & DEF_LOCAL)) {
PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_CONFLICT,
target_name);
@@ -2025,7 +2031,7 @@ symtable_extend_namedexpr_scope(struct symtable *st,
expr_ty e)
/* If we find a FunctionBlock entry, add as GLOBAL/LOCAL or
NONLOCAL/LOCAL */
if (ste->ste_type == FunctionBlock) {
- long target_in_scope = _PyST_GetSymbol(ste, target_name);
+ long target_in_scope = symtable_lookup_entry(st, ste, target_name);
if (target_in_scope & DEF_GLOBAL) {
if (!symtable_add_def(st, target_name, DEF_GLOBAL,
LOCATION(e)))
VISIT_QUIT(st, 0);
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]