diff --git a/Lib/test/test_named_expressions.py b/Lib/test/test_named_expressions.py index b1027ce7800..01e26c8dfaf 100644 --- a/Lib/test/test_named_expressions.py +++ b/Lib/test/test_named_expressions.py @@ -1,6 +1,7 @@ import os import unittest +GLOBAL_VAR = None class NamedExpressionInvalidTest(unittest.TestCase): @@ -470,5 +471,49 @@ spam()""" self.assertEqual(ns["x"], 2) self.assertEqual(ns["result"], [0, 1, 2]) + def test_named_expression_global_scope(self): + sentinel = object() + global GLOBAL_VAR + def f(): + global GLOBAL_VAR + [GLOBAL_VAR := sentinel for _ in range(1)] + self.assertEqual(GLOBAL_VAR, sentinel) + try: + f() + self.assertEqual(GLOBAL_VAR, sentinel) + finally: + GLOBAL_VAR = None + + def test_named_expression_global_scope_no_global_keyword(self): + sentinel = object() + def f(): + GLOBAL_VAR = None + [GLOBAL_VAR := sentinel for _ in range(1)] + self.assertEqual(GLOBAL_VAR, sentinel) + f() + self.assertEqual(GLOBAL_VAR, None) + + def test_named_expression_nonlocal_scope(self): + sentinel = object() + def f(): + nonlocal_var = None + def g(): + nonlocal nonlocal_var + [nonlocal_var := sentinel for _ in range(1)] + g() + self.assertEqual(nonlocal_var, sentinel) + f() + + def test_named_expression_nonlocal_scope_no_nonlocal_keyword(self): + sentinel = object() + def f(): + nonlocal_var = None + def g(): + [nonlocal_var := sentinel for _ in range(1)] + g() + self.assertEqual(nonlocal_var, None) + f() + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-10-13-23-41-38.bpo-38469.9kmuQj.rst b/Misc/NEWS.d/next/Core and Builtins/2019-10-13-23-41-38.bpo-38469.9kmuQj.rst new file mode 100644 index 00000000000..328a1b70825 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-10-13-23-41-38.bpo-38469.9kmuQj.rst @@ -0,0 +1,2 @@ +Fixed a bug where the scope of named expressions was not being resolved +correctly in the presence of the *global* keyword. Patch by Pablo Galindo. diff --git a/Python/symtable.c b/Python/symtable.c index f2453db69dd..b8713588b9a 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1467,10 +1467,16 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) continue; } - /* If we find a FunctionBlock entry, add as NONLOCAL/LOCAL */ + /* If we find a FunctionBlock entry, add as GLOBAL/LOCAL or NONLOCAL/LOCAL */ if (ste->ste_type == FunctionBlock) { - if (!symtable_add_def(st, target_name, DEF_NONLOCAL)) - VISIT_QUIT(st, 0); + long target_in_scope = _PyST_GetSymbol(ste, target_name); + if (target_in_scope & DEF_GLOBAL) { + if (!symtable_add_def(st, target_name, DEF_GLOBAL)) + VISIT_QUIT(st, 0); + } else { + if (!symtable_add_def(st, target_name, DEF_NONLOCAL)) + VISIT_QUIT(st, 0); + } if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset)) VISIT_QUIT(st, 0);