1+ import ast
12import contextlib
23import copy
34import inspect
@@ -418,17 +419,26 @@ def test_async_comprehension_scope(self):
418419 "async def f():\n {x async for x in y}" ,
419420 "async def f():\n {k: x async for k, x in y}" ,
420421 "async def f():\n [[await x for x in y] for y in z]" ,
422+ # Defaults and bases are evaluated in the enclosing scope.
423+ "async def outer():\n async def f(x=[await y for y in z]): pass" ,
424+ "async def f():\n class C([await x for x in y]): pass" ,
421425 ]
422426 for code in allowed :
423427 with self .subTest (code = code ):
424428 compile (code , "<test>" , "exec" )
425429
426430 # Generator expressions with await are async genexps and may appear
427- # outside async functions.
431+ # outside async functions. A listcomp nested in a genexp is also
432+ # allowed (the genexp becomes an async generator).
428433 for code in [
429434 "(await x for x in y)" ,
430435 "def f():\n (await x for x in y)" ,
431436 "class C:\n (await x for x in y)" ,
437+ "lambda: (await x for x in y)" ,
438+ "([await x for x in y] for y in z)" ,
439+ "def f():\n ([await x for x in y] for y in z)" ,
440+ "class C:\n ([await x for x in y] for y in z)" ,
441+ "async def f():\n ([await x for x in y] for y in z)" ,
432442 ]:
433443 with self .subTest (code = code ):
434444 compile (code , "<test>" , "exec" )
@@ -453,6 +463,22 @@ def test_async_comprehension_scope(self):
453463 "class C:\n [[await x for x in y] for y in z]" ,
454464 "async def f():\n class C:\n x = [await y for y in z]" ,
455465 "async def f():\n class C:\n x = [y async for y in z]" ,
466+ # Lambdas are never async, even inside async def.
467+ "lambda: [await x for x in y]" ,
468+ "async def f():\n lambda: [await x for x in y]" ,
469+ "class C:\n f = lambda: [await x for x in y]" ,
470+ # Defaults and bases run in the enclosing scope.
471+ "async def f(x=[await y for y in z]): pass" ,
472+ "def f(x=[await y for y in z]): pass" ,
473+ "class C:\n def f(self, x=[await y for y in z]): pass" ,
474+ "class C([await x for x in y]): pass" ,
475+ # Type aliases and type-parameter scopes.
476+ "type T = [await x for x in y]" ,
477+ "type T = [x async for x in y]" ,
478+ "def f[T=[await x for x in y]](): pass" ,
479+ "def f[T: [await x for x in y]](): pass" ,
480+ "async def f[T=[await x for x in y]](): pass" ,
481+ "async def f(x: [await y for y in z]): pass" ,
456482 ]
457483 for code in invalid :
458484 with self .subTest (code = code ):
@@ -465,6 +491,26 @@ def test_async_comprehension_scope(self):
465491 support .check_syntax_error (
466492 self , "def f():\n await x" , "'await' outside async function" )
467493
494+ flags = ast .PyCF_ALLOW_TOP_LEVEL_AWAIT
495+ for code in [
496+ "[await x for x in y]" ,
497+ "async def f(x=[await y for y in z]): pass" ,
498+ "class C([await x for x in y]): pass" ,
499+ "f'{[await x for x in y]}'" ,
500+ ]:
501+ with self .subTest (code = code , tla = True ):
502+ compile (code , "<test>" , "exec" , flags = flags )
503+ still_invalid = [
504+ "lambda: [await x for x in y]" ,
505+ "class C:\n def f(self, x=[await y for y in z]): pass" ,
506+ "type T = [await x for x in y]" ,
507+ "async def f[T=[await x for x in y]](): pass" ,
508+ ]
509+ for code in still_invalid :
510+ with self .subTest (code = code , tla = True ):
511+ with self .assertRaisesRegex (SyntaxError , err ):
512+ compile (code , "<test>" , "exec" , flags = flags )
513+
468514 def test_badsyntax_2 (self ):
469515 samples = [
470516 """def foo():
0 commit comments