From 17376ace287d871e3d8bb7ca9dba8b946b381143 Mon Sep 17 00:00:00 2001 From: Shahar Naveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sat, 9 May 2026 18:29:46 +0300 Subject: [PATCH] Update `test_global.py` to 3.14.4 (#7809) --- Lib/test/test_global.py | 225 +++++++++++++++++++++++++++++++++------- 1 file changed, 190 insertions(+), 35 deletions(-) diff --git a/Lib/test/test_global.py b/Lib/test/test_global.py index 4c1bb6c0c..1f55dfbe1 100644 --- a/Lib/test/test_global.py +++ b/Lib/test/test_global.py @@ -1,7 +1,19 @@ -"""Verify that warnings are issued for global statements following use.""" +"""This module includes tests for syntax errors that occur when a name +declared as `global` is used in ways that violate the language +specification, such as after assignment, usage, or annotation. The tests +verify that syntax errors are correctly raised for improper `global` +statements following variable use or assignment within functions. +Additionally, it tests various name-binding scenarios for global +variables to ensure correct behavior. +See `test_scope.py` for additional related behavioral tests covering +variable scoping and usage in different contexts. +""" + +import contextlib from test.support import check_syntax_error from test.support.warnings_helper import check_warnings +from types import SimpleNamespace import unittest import warnings @@ -12,46 +24,189 @@ class GlobalTests(unittest.TestCase): self.enterContext(check_warnings()) warnings.filterwarnings("error", module="") - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test1(self): - prog_text_1 = """\ -def wrong1(): - a = 1 - b = 2 - global a - global b -""" - check_syntax_error(self, prog_text_1, lineno=4, offset=5) + ###################################################### + ### Syntax error cases as covered in Python/symtable.c + ###################################################### - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test2(self): - prog_text_2 = """\ -def wrong2(): - print(x) - global x + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: 12 != 5 + def test_name_param(self): + prog_text = """\ +def fn(name_param): + global name_param """ - check_syntax_error(self, prog_text_2, lineno=3, offset=5) + check_syntax_error(self, prog_text, lineno=2, offset=5) - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test3(self): + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: 12 != 5 + def test_name_after_assign(self): + prog_text = """\ +def fn(): + name_assign = 1 + global name_assign +""" + check_syntax_error(self, prog_text, lineno=3, offset=5) + + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: 12 != 5 + def test_name_after_use(self): + prog_text = """\ +def fn(): + print(name_use) + global name_use +""" + check_syntax_error(self, prog_text, lineno=3, offset=5) + + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: 12 != 5 + def test_name_annot(self): prog_text_3 = """\ -def wrong3(): - print(x) - x = 2 - global x +def fn(): + name_annot: int + global name_annot """ - check_syntax_error(self, prog_text_3, lineno=4, offset=5) + check_syntax_error(self, prog_text_3, lineno=3, offset=5) - def test4(self): - prog_text_4 = """\ -global x -x = 2 -""" - # this should work - compile(prog_text_4, "", "exec") + ############################################################# + ### Tests for global variables across all name binding cases, + ### as described in executionmodel.rst + ############################################################# + + def test_assignment_statement(self): + global name_assignment_statement + value = object() + name_assignment_statement = value + self.assertIs(globals()["name_assignment_statement"], value) + del name_assignment_statement + + def test_unpacking_assignment(self): + global name_unpacking_assignment + value = object() + _, name_unpacking_assignment = [None, value] + self.assertIs(globals()["name_unpacking_assignment"], value) + del name_unpacking_assignment + + def test_assignment_expression(self): + global name_assignment_expression + value = object() + if name_assignment_expression := value: + pass + self.assertIs(globals()["name_assignment_expression"], value) + del name_assignment_expression + + def test_iteration_variable(self): + global name_iteration_variable + value = object() + for name_iteration_variable in [value]: + pass + self.assertIs(globals()["name_iteration_variable"], value) + del name_iteration_variable + + def test_func_def(self): + global name_func_def + + def name_func_def(): + pass + + value = name_func_def + self.assertIs(globals()["name_func_def"], value) + del name_func_def + + def test_class_def(self): + global name_class_def + + class name_class_def: + pass + + value = name_class_def + self.assertIs(globals()["name_class_def"], value) + del name_class_def + + def test_type_alias(self): + global name_type_alias + type name_type_alias = tuple[int, int] + value = name_type_alias + self.assertIs(globals()["name_type_alias"], value) + del name_type_alias + + def test_caught_exception(self): + global name_caught_exc + + try: + 1 / 0 + except ZeroDivisionError as name_caught_exc: + value = name_caught_exc + # `name_caught_exc` is cleared automatically after the except block + self.assertIs(globals()["name_caught_exc"], value) + + def test_caught_exception_group(self): + global name_caught_exc_group + try: + try: + 1 / 0 + except ZeroDivisionError as exc: + raise ExceptionGroup("eg", [exc]) + except* ZeroDivisionError as name_caught_exc_group: + value = name_caught_exc_group + # `name_caught_exc` is cleared automatically after the except block + self.assertIs(globals()["name_caught_exc_group"], value) + + def test_enter_result(self): + global name_enter_result + value = object() + with contextlib.nullcontext(value) as name_enter_result: + pass + self.assertIs(globals()["name_enter_result"], value) + del name_enter_result + + def test_import_result(self): + global name_import_result + value = contextlib + import contextlib as name_import_result + + self.assertIs(globals()["name_import_result"], value) + del name_import_result + + def test_match(self): + global name_match + value = object() + match value: + case name_match: + pass + self.assertIs(globals()["name_match"], value) + del name_match + + def test_match_as(self): + global name_match_as + value = object() + match value: + case _ as name_match_as: + pass + self.assertIs(globals()["name_match_as"], value) + del name_match_as + + def test_match_seq(self): + global name_match_seq + value = object() + match (None, value): + case (_, name_match_seq): + pass + self.assertIs(globals()["name_match_seq"], value) + del name_match_seq + + def test_match_map(self): + global name_match_map + value = object() + match {"key": value}: + case {"key": name_match_map}: + pass + self.assertIs(globals()["name_match_map"], value) + del name_match_map + + def test_match_attr(self): + global name_match_attr + value = object() + match SimpleNamespace(key=value): + case SimpleNamespace(key=name_match_attr): + pass + self.assertIs(globals()["name_match_attr"], value) + del name_match_attr def setUpModule():