10000 gh-58749: Removes the erroneous explanation regarding the restrictions of the global statement by bombs-kim · Pull Request #126523 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-58749: Removes the erroneous explanation regarding the restrictions of the global statement #126523

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 12, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Change test module description to reflect the new tests
Refer to test_scope.py in the description for additional behavioural tests
Verify that syntax errors are correctly raised for improper `global`
statements
Test various name-binding scenarios for global
variables to ensure correct behavior
  • Loading branch information
bombs-kim committed Nov 11, 2024
commit f37b6d946abeba6a6439720181f8a18f36945629
213 changes: 185 additions & 28 deletions Lib/test/test_global.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -12,40 +24,185 @@ def setUp(self):
self.enterContext(check_warnings())
warnings.filterwarnings("error", module="<test string>")

def test1(self):
prog_text_1 = """\
def wrong1():
a = 1
b = 2
global a
global b
######################################################
### Syntax error cases as covered in Python/symtable.c
######################################################

def test_name_param(self):
prog_text = """\
def fn(name_param):
global name_param
"""
check_syntax_error(self, prog_text_1, lineno=4, offset=5)
check_syntax_error(self, prog_text, lineno=2, offset=5)

def test2(self):
prog_text_2 = """\
def wrong2():
print(x)
global x
def test_name_after_assign(self):
prog_text = """\
def fn():
name_assign = 1
global name_assign
"""
check_syntax_error(self, prog_text_2, lineno=3, offset=5)
check_syntax_error(self, prog_text, lineno=3, offset=5)

def test3(self):
prog_text_3 = """\
def wrong3():
print(x)
x = 2
global x
def test_name_after_use(self):
prog_text = """\
def fn():
print(name_use)
global name_use
"""
check_syntax_error(self, prog_text_3, lineno=4, offset=5)
check_syntax_error(self, prog_text, lineno=3, offset=5)

def test4(self):
prog_text_4 = """\
global x
x = 2
def test_name_annot(self):
prog_text_3 = """\
def fn():
name_annot: int
global name_annot
"""
# this should work
compile(prog_text_4, "<test string>", "exec")
check_syntax_error(self, prog_text_3, lineno=3, offset=5)

#############################################################
### 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

10000 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():
Expand Down
0