mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 18:07:37 +00:00 
			
		
		
		
	 494360afd0
			
		
	
	
		494360afd0
		
			
		
	
	
	
	
		
			
			* Removes erroneous explanation of the `global` statement restrictions; a name declared as global can be subsequently bound using any kind of name binding operation. * Updates `test_global.py` to also test various name-binding scenarios for global variables to ensure correct behavior
		
			
				
	
	
		
			214 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """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
 | |
| 
 | |
| 
 | |
| class GlobalTests(unittest.TestCase):
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.enterContext(check_warnings())
 | |
|         warnings.filterwarnings("error", module="<test string>")
 | |
| 
 | |
|     ######################################################
 | |
|     ### 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, lineno=2, offset=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)
 | |
| 
 | |
|     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)
 | |
| 
 | |
|     def test_name_annot(self):
 | |
|         prog_text_3 = """\
 | |
| def fn():
 | |
|     name_annot: int
 | |
|     global name_annot
 | |
| """
 | |
|         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
 | |
| 
 | |
|     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():
 | |
|     unittest.enterModuleContext(warnings.catch_warnings())
 | |
|     warnings.filterwarnings("error", module="<test string>")
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     unittest.main()
 |