@@ -1771,33 +1771,55 @@ def tearDown(self):
1771
1771
def test_simultaneous_asend (self ):
1772
1772
"""
1773
1773
Verify that simultaneous use of generator by different coroutines is not
1774
- permitted
1774
+ permitted. We use Tasks to achieve this, where one task is suspended
1775
+ in a `asyncio.sleep()` call inside the generator (during an `asend()` call),
1776
+ and the other task attempts
1777
+ to do an `asend()`, (or `athrow()`, or `aclose()`) on the generator.
1775
1778
"""
1776
1779
1777
1780
async def run ():
1778
- async def consumer ():
1779
- while True :
1780
- await asyncio .sleep (0 )
1781
- if (yield ) is None :
1782
- break
1783
1781
1784
- # try different combinations of asend, athrow, aclose
1785
- # which are clashing with an asend which is already running
1786
- # (and awaiting sleep(0))
1787
- for op , args in [("asend" , ["A" ]), ("athrow" , [EOFError ]), ("aclose" , [])]:
1782
+ async def run_collision (op , * args ):
1783
+ # Two tasks are created and scheduled. The first will sleep inside the
1784
+ # `asend()` and the other will then attempt a second operation and fail.
1785
+
1786
+ async def consumer ():
1787
+ while True :
1788
+ # task fa will sleep here, and another task will try to iterate
1789
+ # the generator
1790
+ await asyncio .sleep (0 )
1791
+ if (yield ) is None :
1792
+ break
1793
+
1794
+ # create and start the generator
1788
1795
agenerator = consumer ()
1789
- await agenerator .asend (None ) # start it
1790
- # fa will hit sleep and then fb will run
1796
+ await agenerator .asend (None )
1797
+
1798
+ # start the first asend() task
1791
1799
fa = asyncio .create_task (agenerator .asend ("A" ))
1792
- coro = getattr (agenerator , op )(* args )
1793
- fb = asyncio .create_task (coro )
1800
+
1801
+ # start the second task, which should fail (asend, athrow, aclose)
1802
+ method = getattr (agenerator , op )
1803
+ fb = asyncio .create_task (method (* args ))
1804
+
1805
+ # first asend should succeed
1794
1806
await fa
1807
+
1808
+ # second operation should fail
1795
1809
with self .assertRaises (RuntimeError ) as err :
1796
1810
await fb
1797
1811
assert "already running" in str (err .exception )
1812
+
1813
+ # cleanup partially run generator
1798
1814
with self .assertRaises (StopAsyncIteration ):
1799
1815
await agenerator .asend (None ) # close it
1800
1816
1817
+ # try different combinations of asend, athrow, aclose
1818
+ # which are clashing with an asend which is already running
1819
+ # (and awaiting sleep(0))
1820
+ for op , args in [("asend" , ["A" ]), ("athrow" , [EOFError ]), ("aclose" , [])]:
1821
+ await run_collision (op , * args )
1822
+
1801
1823
self .loop .run_until_complete (run ())
1802
1824
1803
1825
def test_ag_running (self ):
0 commit comments