1313
1414glob = 42
1515some_var = 12
16- some_non_assigned_global_var = 11
16+ some_non_assigned_global_var: int
1717some_assigned_global_var = 11
1818
1919class Mine:
@@ -53,6 +53,120 @@ class GenericMine[T: int, U: (int, str) = int]:
5353 pass
5454"""
5555
56+ TEST_COMPLEX_CLASS_CODE = """
57+ # The following symbols are defined in ComplexClass
58+ # without being introduced by a 'global' statement.
59+ glob_unassigned_meth: Any
60+ glob_unassigned_meth_pep_695: Any
61+
62+ glob_unassigned_async_meth: Any
63+ glob_unassigned_async_meth_pep_695: Any
64+
65+ def glob_assigned_meth(): pass
66+ def glob_assigned_meth_pep_695[T](): pass
67+
68+ async def glob_assigned_async_meth(): pass
69+ async def glob_assigned_async_meth_pep_695[T](): pass
70+
71+ # The following symbols are defined in ComplexClass after
72+ # being introduced by a 'global' statement (and therefore
73+ # are not considered as local symbols of ComplexClass).
74+ glob_unassigned_meth_ignore: Any
75+ glob_unassigned_meth_pep_695_ignore: Any
76+
77+ glob_unassigned_async_meth_ignore: Any
78+ glob_unassigned_async_meth_pep_695_ignore: Any
79+
80+ def glob_assigned_meth_ignore(): pass
81+ def glob_assigned_meth_pep_695_ignore[T](): pass
82+
83+ async def glob_assigned_async_meth_ignore(): pass
84+ async def glob_assigned_async_meth_pep_695_ignore[T](): pass
85+
86+ class ComplexClass:
87+ a_var = 1234
88+ a_genexpr = (x for x in [])
89+ a_lambda = lambda x: x
90+
91+ type a_type_alias = int
92+ type a_type_alias_pep_695[T] = list[T]
93+
94+ class a_class: pass
95+ class a_class_pep_695[T]: pass
96+
97+ def a_method(self): pass
98+ def a_method_pep_695[T](self): pass
99+
100+ async def an_async_method(self): pass
101+ async def an_async_method_pep_695[T](self): pass
102+
103+ @classmethod
104+ def a_classmethod(cls): pass
105+ @classmethod
106+ def a_classmethod_pep_695[T](self): pass
107+
108+ @classmethod
109+ async def an_async_classmethod(cls): pass
110+ @classmethod
111+ async def an_async_classmethod_pep_695[T](self): pass
112+
113+ @staticmethod
114+ def a_staticmethod(): pass
115+ @staticmethod
116+ def a_staticmethod_pep_695[T](self): pass
117+
118+ @staticmethod
119+ async def an_async_staticmethod(): pass
120+ @staticmethod
121+ async def an_async_staticmethod_pep_695[T](self): pass
122+
123+ # These ones will be considered as methods because of the 'def' although
124+ # they are *not* valid methods at runtime since they are not decorated
125+ # with @staticmethod.
126+ def a_fakemethod(): pass
127+ def a_fakemethod_pep_695[T](): pass
128+
129+ async def an_async_fakemethod(): pass
130+ async def an_async_fakemethod_pep_695[T](): pass
131+
132+ # Check that those are still considered as methods
133+ # since they are not using the 'global' keyword.
134+ def glob_unassigned_meth(): pass
135+ def glob_unassigned_meth_pep_695[T](): pass
136+
137+ async def glob_unassigned_async_meth(): pass
138+ async def glob_unassigned_async_meth_pep_695[T](): pass
139+
140+ def glob_assigned_meth(): pass
141+ def glob_assigned_meth_pep_695[T](): pass
142+
143+ async def glob_assigned_async_meth(): pass
144+ async def glob_assigned_async_meth_pep_695[T](): pass
145+
146+ # The following are not picked as local symbols because they are not
147+ # visible by the class at runtime (this is equivalent to having the
148+ # definitions outside of the class).
149+ global glob_unassigned_meth_ignore
150+ def glob_unassigned_meth_ignore(): pass
151+ global glob_unassigned_meth_pep_695_ignore
152+ def glob_unassigned_meth_pep_695_ignore[T](): pass
153+
154+ global glob_unassigned_async_meth_ignore
155+ async def glob_unassigned_async_meth_ignore(): pass
156+ global glob_unassigned_async_meth_pep_695_ignore
157+ async def glob_unassigned_async_meth_pep_695_ignore[T](): pass
158+
159+ global glob_assigned_meth_ignore
160+ def glob_assigned_meth_ignore(): pass
161+ global glob_assigned_meth_pep_695_ignore
162+ def glob_assigned_meth_pep_695_ignore[T](): pass
163+
164+ global glob_assigned_async_meth_ignore
165+ async def glob_assigned_async_meth_ignore(): pass
166+ global glob_assigned_async_meth_pep_695_ignore
167+ async def glob_assigned_async_meth_pep_695_ignore[T](): pass
168+ """
169+
56170
57171def find_block (block , name ):
58172 for ch in block .get_children ():
@@ -65,6 +179,7 @@ class SymtableTest(unittest.TestCase):
65179 top = symtable .symtable (TEST_CODE , "?" , "exec" )
66180 # These correspond to scopes in TEST_CODE
67181 Mine = find_block (top , "Mine" )
182+
68183 a_method = find_block (Mine , "a_method" )
69184 spam = find_block (top , "spam" )
70185 internal = find_block (spam , "internal" )
@@ -242,6 +357,24 @@ def test_name(self):
242357 def test_class_info (self ):
243358 self .assertEqual (self .Mine .get_methods (), ('a_method' ,))
244359
360+ top = symtable .symtable (TEST_COMPLEX_CLASS_CODE , "?" , "exec" )
361+ this = find_block (top , "ComplexClass" )
362+
363+ self .assertEqual (this .get_methods (), (
364+ 'a_method' , 'a_method_pep_695' ,
365+ 'an_async_method' , 'an_async_method_pep_695' ,
366+ 'a_classmethod' , 'a_classmethod_pep_695' ,
367+ 'an_async_classmethod' , 'an_async_classmethod_pep_695' ,
368+ 'a_staticmethod' , 'a_staticmethod_pep_695' ,
369+ 'an_async_staticmethod' , 'an_async_staticmethod_pep_695' ,
370+ 'a_fakemethod' , 'a_fakemethod_pep_695' ,
371+ 'an_async_fakemethod' , 'an_async_fakemethod_pep_695' ,
372+ 'glob_unassigned_meth' , 'glob_unassigned_meth_pep_695' ,
373+ 'glob_unassigned_async_meth' , 'glob_unassigned_async_meth_pep_695' ,
374+ 'glob_assigned_meth' , 'glob_assigned_meth_pep_695' ,
375+ 'glob_assigned_async_meth' , 'glob_assigned_async_meth_pep_695' ,
376+ ))
377+
245378 def test_filename_correct (self ):
246379 ### Bug tickler: SyntaxError file name correct whether error raised
247380 ### while parsing or building symbol table.
0 commit comments