@@ -624,13 +624,13 @@ async def test___del__(capfd):
624
624
625
625
@async_generator
626
626
async def awaits_when_unwinding ():
627
- await yield_ (1 )
627
+ await yield_ (0 )
628
628
try :
629
- await yield_ (2 )
629
+ await yield_ (1 )
630
630
finally :
631
631
await mock_sleep ()
632
632
try :
633
- await yield_ (3 )
633
+ await yield_ (2 )
634
634
finally :
635
635
nonlocal completions
636
636
completions += 1
@@ -640,21 +640,21 @@ async def awaits_when_unwinding():
640
640
gen .__del__ ()
641
641
642
642
gen = awaits_when_unwinding ()
643
- assert await collect (gen ) == [1 , 2 , 3 ]
643
+ assert await collect (gen ) == [0 , 1 , 2 ]
644
644
# Exhausted, so no problem
645
645
gen .__del__ ()
646
646
647
- for turns in (1 , 2 , 3 ):
647
+ for stop_after_turn in (1 , 2 , 3 ):
648
648
gen = awaits_when_unwinding ()
649
- for turn in range (1 , turns + 1 ):
649
+ for turn in range (stop_after_turn ):
650
650
assert await gen .__anext__ () == turn
651
651
await gen .aclose ()
652
652
# Closed, so no problem
653
653
gen .__del__ ()
654
654
655
- for turns in (1 , 2 , 3 ):
655
+ for stop_after_turn in (1 , 2 , 3 ):
656
656
gen = awaits_when_unwinding ()
657
- for turn in range (1 , turns + 1 ):
657
+ for turn in range (stop_after_turn ):
658
658
assert await gen .__anext__ () == turn
659
659
660
660
if sys .implementation .name == "pypy" :
@@ -665,14 +665,14 @@ async def awaits_when_unwinding():
665
665
with pytest .raises (RuntimeError ) as info :
666
666
gen .__del__ ()
667
667
assert "partially-exhausted async_generator" in str (info .value )
668
- if turns == 3 :
668
+ if stop_after_turn == 3 :
669
669
# We didn't increment completions, because we didn't finalize
670
670
# the generator. Increment it now so the check below (which is
671
671
# calibrated for the correct/CPython behavior) doesn't fire;
672
672
# we know about the pypy bug.
673
673
completions += 1
674
674
675
- elif turns == 2 :
675
+ elif stop_after_turn == 2 :
676
676
# Stopped in the middle of a try/finally that awaits in the finally,
677
677
# so __del__ can't cleanup.
678
678
with pytest .raises (RuntimeError ) as info :
@@ -892,7 +892,7 @@ def two(agen): # pragma: no cover
892
892
with pytest .raises (TypeError ):
893
893
set_asyncgen_hooks (finalizer = False )
894
894
895
- def in_thread (results = [] ):
895
+ def in_thread (results ):
896
896
results .append (get_asyncgen_hooks ())
897
897
set_asyncgen_hooks (two , one )
898
898
results .append (get_asyncgen_hooks ())
@@ -964,6 +964,18 @@ async def anext_verbosely(iter, ident):
964
964
]
965
965
del events [:]
966
966
967
+ # Ensure that firstiter is only called once, even if we create
968
+ # two asend() coroutines before iterating either of them.
969
+ iterX = agen ("X" )
970
+ sender1 = iterX .asend (None )
971
+ sender2 = iterX .asend (None )
972
+ events .append ("before close" )
973
+ sender1 .close ()
974
+ sender2 .close ()
975
+ await iterX .aclose ()
976
+ assert events == ["firstiter X" , "before close" ]
977
+ del events [:]
978
+
967
979
if sys .implementation .name == "pypy" :
968
980
# pypy segfaults if an async generator's __del__ is called (even if it resurrects!)
969
981
# and then the underlying coroutine encounters another await:
0 commit comments