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