@@ -393,6 +393,151 @@ async def gen():
393
393
r'anext\(\): asynchronous generator is already running' ):
394
394
an .__next__ ()
395
395
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
+
396
541
def test_async_gen_3_arg_deprecation_warning (self ):
397
542
async def gen ():
398
543
yield 123
@@ -1571,6 +1716,8 @@ async def main():
1571
1716
self .assertIsInstance (message ['exception' ], ZeroDivisionError )
1572
1717
self .assertIn ('unhandled exception during asyncio.run() shutdown' ,
1573
1718
message ['message' ])
1719
+ del message , messages
1720
+ gc_collect ()
1574
1721
1575
1722
def test_async_gen_expression_01 (self ):
1576
1723
async def arange (n ):
@@ -1624,6 +1771,7 @@ async def main():
1624
1771
asyncio .run (main ())
1625
1772
1626
1773
self .assertEqual ([], messages )
1774
+ gc_collect ()
1627
1775
1628
1776
def test_async_gen_await_same_anext_coro_twice (self ):
1629
1777
async def async_iterate ():
@@ -1809,9 +1957,56 @@ class MyException(Exception):
1809
1957
g = gen ()
1810
1958
with self .assertRaises (MyException ):
1811
1959
g .aclose ().throw (MyException )
1812
- del g
1813
- gc_collect ()
1814
1960
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
1815
2010
1816
2011
if __name__ == "__main__" :
1817
2012
unittest .main ()
0 commit comments