[Python-checkins] (no subject)

Łukasz Langa webhook-mailer at python.org
Mon Oct 14 07:40:19 EDT 2019




To: python-checkins at python.org
Subject: bpo-38469: Handle named expression scope with global/nonlocal
 keywords (GH-16755) (#16760)
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0

https://github.com/python/cpython/commit/927f07c816aad9f8ed961d7ace6a367837f7=
fa8f
commit: 927f07c816aad9f8ed961d7ace6a367837f7fa8f
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.co=
m>
committer: =C5=81ukasz Langa <lukasz at langa.pl>
date: 2019-10-14T13:40:15+02:00
summary:

bpo-38469: Handle named expression scope with global/nonlocal keywords (GH-16=
755) (#16760)

The symbol table handing of PEP572's assignment expressions is not resolving =
correctly the scope of some variables in presence of global/nonlocal keywords=
 in conjunction with comprehensions.
(cherry picked from commit fd5c414880b2e05720b9cf14ab0b0d7ae2b7d925)

Co-authored-by: Pablo Galindo <Pablogsal at gmail.com>

files:
A Misc/NEWS.d/next/Core and Builtins/2019-10-13-23-41-38.bpo-38469.9kmuQj.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_express=
ions.py
index b1027ce78006d..01e26c8dfaf25 100644
--- a/Lib/test/test_named_expressions.py
+++ b/Lib/test/test_named_expressions.py
@@ -1,6 +1,7 @@
 import os
 import unittest
=20
+GLOBAL_VAR =3D None
=20
 class NamedExpressionInvalidTest(unittest.TestCase):
=20
@@ -470,5 +471,49 @@ def test_named_expression_variable_reuse_in_comprehensio=
ns(self):
                 self.assertEqual(ns["x"], 2)
                 self.assertEqual(ns["result"], [0, 1, 2])
=20
+    def test_named_expression_global_scope(self):
+        sentinel =3D object()
+        global GLOBAL_VAR
+        def f():
+            global GLOBAL_VAR
+            [GLOBAL_VAR :=3D sentinel for _ in range(1)]
+            self.assertEqual(GLOBAL_VAR, sentinel)
+        try:
+            f()
+            self.assertEqual(GLOBAL_VAR, sentinel)
+        finally:
+            GLOBAL_VAR =3D None
+
+    def test_named_expression_global_scope_no_global_keyword(self):
+        sentinel =3D object()
+        def f():
+            GLOBAL_VAR =3D None
+            [GLOBAL_VAR :=3D sentinel for _ in range(1)]
+            self.assertEqual(GLOBAL_VAR, sentinel)
+        f()
+        self.assertEqual(GLOBAL_VAR, None)
+
+    def test_named_expression_nonlocal_scope(self):
+        sentinel =3D object()
+        def f():
+            nonlocal_var =3D None
+            def g():
+                nonlocal nonlocal_var
+                [nonlocal_var :=3D sentinel for _ in range(1)]
+            g()
+            self.assertEqual(nonlocal_var, sentinel)
+        f()
+
+    def test_named_expression_nonlocal_scope_no_nonlocal_keyword(self):
+        sentinel =3D object()
+        def f():
+            nonlocal_var =3D None
+            def g():
+                [nonlocal_var :=3D sentinel for _ in range(1)]
+            g()
+            self.assertEqual(nonlocal_var, None)
+        f()
+
+
 if __name__ =3D=3D "__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-3846=
9.9kmuQj.rst
new file mode 100644
index 0000000000000..328a1b70825af
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-10-13-23-41-38.bpo-38469.9kmuQj=
.rst=09
@@ -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 f2453db69dd7d..b8713588b9a91 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -1467,10 +1467,16 @@ symtable_extend_namedexpr_scope(struct symtable *st, =
expr_ty e)
             continue;
         }
=20
-        /* 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 =3D=3D FunctionBlock) {
-            if (!symtable_add_def(st, target_name, DEF_NONLOCAL))
-                VISIT_QUIT(st, 0);
+            long target_in_scope =3D _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->co=
l_offset))
                 VISIT_QUIT(st, 0);
=20



More information about the Python-checkins mailing list