11"""
22Test the API of the symtable module.
33"""
4+
5+ import textwrap
46import symtable
57import unittest
68
@@ -354,7 +356,7 @@ def test_name(self):
354356 self .assertEqual (self .spam .lookup ("x" ).get_name (), "x" )
355357 self .assertEqual (self .Mine .get_name (), "Mine" )
356358
357- def test_class_info (self ):
359+ def test_class_get_methods (self ):
358360 self .assertEqual (self .Mine .get_methods (), ('a_method' ,))
359361
360362 top = symtable .symtable (TEST_COMPLEX_CLASS_CODE , "?" , "exec" )
@@ -375,6 +377,58 @@ def test_class_info(self):
375377 'glob_assigned_async_meth' , 'glob_assigned_async_meth_pep_695' ,
376378 ))
377379
380+ # Test generator expressions that are of type TYPE_FUNCTION
381+ # but will not be reported by get_methods() since they are
382+ # not functions per se.
383+ #
384+ # Other kind of comprehensions such as list, set or dict
385+ # expressions do not have the TYPE_FUNCTION type.
386+
387+ def check_body (body , expected_methods ):
388+ indented = textwrap .indent (body , ' ' * 4 )
389+ top = symtable .symtable (f"class A:\n { indented } " , "?" , "exec" )
390+ this = find_block (top , "A" )
391+ self .assertEqual (this .get_methods (), expected_methods )
392+
393+ # statements with 'genexpr' inside it
394+ GENEXPRS = (
395+ 'x = (x for x in [])' ,
396+ 'x = (x async for x in [])' ,
397+ 'type x[genexpr = (x for x in [])] = (x for x in [])' ,
398+ 'type x[genexpr = (x async for x in [])] = (x async for x in [])' ,
399+ 'genexpr = (x for x in [])' ,
400+ 'genexpr = (x async for x in [])' ,
401+ 'type genexpr[genexpr = (x for x in [])] = (x for x in [])' ,
402+ 'type genexpr[genexpr = (x async for x in [])] = (x async for x in [])' ,
403+ )
404+
405+ for gen in GENEXPRS :
406+ # test generator expression
407+ with self .subTest (gen = gen ):
408+ check_body (gen , ())
409+
410+ # test generator expression + variable named 'genexpr'
411+ with self .subTest (gen = gen , isvar = True ):
412+ check_body ('\n ' .join ((gen , 'genexpr = 1' )), ())
413+ check_body ('\n ' .join (('genexpr = 1' , gen )), ())
414+
415+ for paramlist in ('()' , '(x)' , '(x, y)' , '(z: T)' ):
416+ for func in (
417+ f'def genexpr{ paramlist } :pass' ,
418+ f'async def genexpr{ paramlist } :pass' ,
419+ f'def genexpr[T]{ paramlist } :pass' ,
420+ f'async def genexpr[T]{ paramlist } :pass' ,
421+ ):
422+ with self .subTest (func = func ):
423+ # test function named 'genexpr'
424+ check_body (func , ('genexpr' ,))
425+
426+ for gen in GENEXPRS :
427+ with self .subTest (gen = gen , func = func ):
428+ # test generator expression + function named 'genexpr'
429+ check_body ('\n ' .join ((gen , func )), ('genexpr' ,))
430+ check_body ('\n ' .join ((func , gen )), ('genexpr' ,))
431+
378432 def test_filename_correct (self ):
379433 ### Bug tickler: SyntaxError file name correct whether error raised
380434 ### while parsing or building symbol table.
0 commit comments