@@ -393,6 +393,151 @@ async def gen():
393393 r'anext\(\): asynchronous generator is already running' ):
394394 an .__next__ ()
395395
396+ with self .assertRaisesRegex (RuntimeError ,
397+ r"cannot reuse already awaited __anext__\(\)/asend\(\)" ):
398+ an .send (None )
399+
400+ def test_async_gen_asend_throw_concurrent_with_send (self ):
401+ import types
402+
403+ @types .coroutine
404+ def _async_yield (v ):
405+ return (yield v )
406+
407+ class MyExc (Exception ):
408+ pass
409+
410+ async def agenfn ():
411+ while True :
412+ try :
413+ await _async_yield (None )
414+ except MyExc :
415+ pass
416+ return
417+ yield
418+
419+
420+ agen = agenfn ()
421+ gen = agen .asend (None )
422+ gen .send (None )
423+ gen2 = agen .asend (None )
424+
425+ with self .assertRaisesRegex (RuntimeError ,
426+ r'anext\(\): asynchronous generator is already running' ):
427+ gen2 .throw (MyExc )
428+
429+ with self .assertRaisesRegex (RuntimeError ,
430+ r"cannot reuse already awaited __anext__\(\)/asend\(\)" ):
431+ gen2 .send (None )
432+
433+ def test_async_gen_athrow_throw_concurrent_with_send (self ):
434+ import types
435+
436+ @types .coroutine
437+ def _async_yield (v ):
438+ return (yield v )
439+
440+ class MyExc (Exception ):
441+ pass
442+
443+ async def agenfn ():
444+ while True :
445+ try :
446+ await _async_yield (None )
447+ except MyExc :
448+ pass
449+ return
450+ yield
451+
452+
453+ agen = agenfn ()
454+ gen = agen .asend (None )
455+ gen .send (None )
456+ gen2 = agen .athrow (MyExc )
457+
458+ with self .assertRaisesRegex (RuntimeError ,
459+ r'athrow\(\): asynchronous generator is already running' ):
460+ gen2 .throw (MyExc )
461+
462+ with self .assertRaisesRegex (RuntimeError ,
463+ r"cannot reuse already awaited aclose\(\)/athrow\(\)" ):
464+ gen2 .send (None )
465+
466+ def test_async_gen_asend_throw_concurrent_with_throw (self ):
467+ import types
468+
469+ @types .coroutine
470+ def _async_yield (v ):
471+ return (yield v )
472+
473+ class MyExc (Exception ):
474+ pass
475+
476+ async def agenfn ():
477+ try :
478+ yield
479+ except MyExc :
480+ pass
481+ while True :
482+ try :
483+ await _async_yield (None )
484+ except MyExc :
485+ pass
486+
487+
488+ agen = agenfn ()
489+ with self .assertRaises (StopIteration ):
490+ agen .asend (None ).send (None )
491+
492+ gen = agen .athrow (MyExc )
493+ gen .throw (MyExc )
494+ gen2 = agen .asend (MyExc )
495+
496+ with self .assertRaisesRegex (RuntimeError ,
497+ r'anext\(\): asynchronous generator is already running' ):
498+ gen2 .throw (MyExc )
499+
500+ with self .assertRaisesRegex (RuntimeError ,
501+ r"cannot reuse already awaited __anext__\(\)/asend\(\)" ):
502+ gen2 .send (None )
503+
504+ def test_async_gen_athrow_throw_concurrent_with_throw (self ):
505+ import types
506+
507+ @types .coroutine
508+ def _async_yield (v ):
509+ return (yield v )
510+
511+ class MyExc (Exception ):
512+ pass
513+
514+ async def agenfn ():
515+ try :
516+ yield
517+ except MyExc :
518+ pass
519+ while True :
520+ try :
521+ await _async_yield (None )
522+ except MyExc :
523+ pass
524+
525+ agen = agenfn ()
526+ with self .assertRaises (StopIteration ):
527+ agen .asend (None ).send (None )
528+
529+ gen = agen .athrow (MyExc )
530+ gen .throw (MyExc )
531+ gen2 = agen .athrow (None )
532+
533+ with self .assertRaisesRegex (RuntimeError ,
534+ r'athrow\(\): asynchronous generator is already running' ):
535+ gen2 .throw (MyExc )
536+
537+ with self .assertRaisesRegex (RuntimeError ,
538+ r"cannot reuse already awaited aclose\(\)/athrow\(\)" ):
539+ gen2 .send (None )
540+
396541 def test_async_gen_3_arg_deprecation_warning (self ):
397542 async def gen ():
398543 yield 123
@@ -1571,6 +1716,8 @@ async def main():
15711716 self .assertIsInstance (message ['exception' ], ZeroDivisionError )
15721717 self .assertIn ('unhandled exception during asyncio.run() shutdown' ,
15731718 message ['message' ])
1719+ del message , messages
1720+ gc_collect ()
15741721
15751722 def test_async_gen_expression_01 (self ):
15761723 async def arange (n ):
@@ -1624,6 +1771,7 @@ async def main():
16241771 asyncio .run (main ())
16251772
16261773 self .assertEqual ([], messages )
1774+ gc_collect ()
16271775
16281776 def test_async_gen_await_same_anext_coro_twice (self ):
16291777 async def async_iterate ():
@@ -1809,9 +1957,56 @@ class MyException(Exception):
18091957 g = gen ()
18101958 with self .assertRaises (MyException ):
18111959 g .aclose ().throw (MyException )
1812- del g
1813- gc_collect ()
18141960
1961+ del g
1962+ gc_collect () # does not warn unawaited
1963+
1964+ def test_asend_send_already_running (self ):
1965+ @types .coroutine
1966+ def _async_yield (v ):
1967+ return (yield v )
1968+
1969+ async def agenfn ():
1970+ while True :
1971+ await _async_yield (1 )
1972+ return
1973+ yield
1974+
1975+ agen = agenfn ()
1976+ gen = agen .asend (None )
1977+ gen .send (None )
1978+ gen2 = agen .asend (None )
1979+
1980+ with self .assertRaisesRegex (RuntimeError ,
1981+ r'anext\(\): asynchronous generator is already running' ):
1982+ gen2 .send (None )
1983+
1984+ del gen2
1985+ gc_collect () # does not warn unawaited
1986+
1987+
1988+ def test_athrow_send_already_running (self ):
1989+ @types .coroutine
1990+ def _async_yield (v ):
1991+ return (yield v )
1992+
1993+ async def agenfn ():
1994+ while True :
1995+ await _async_yield (1 )
1996+ return
1997+ yield
1998+
1999+ agen = agenfn ()
2000+ gen = agen .asend (None )
2001+ gen .send (None )
2002+ gen2 = agen .athrow (Exception )
2003+
2004+ with self .assertRaisesRegex (RuntimeError ,
2005+ r'athrow\(\): asynchronous generator is already running' ):
2006+ gen2 .send (None )
2007+
2008+ del gen2
2009+ gc_collect () # does not warn unawaited
18152010
18162011if __name__ == "__main__" :
18172012 unittest .main ()
0 commit comments