Skip to content

Commit ef4737c

Browse files
committed
Make simultaneous task test clearer
1 parent 32c5595 commit ef4737c

File tree

1 file changed

+36
-14
lines changed

1 file changed

+36
-14
lines changed

Lib/test/test_asyncgen.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,33 +1771,55 @@ def tearDown(self):
17711771
def test_simultaneous_asend(self):
17721772
"""
17731773
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.
17751778
"""
17761779

17771780
async def run():
1778-
async def consumer():
1779-
while True:
1780-
await asyncio.sleep(0)
1781-
if (yield) is None:
1782-
break
17831781

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
17881795
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
17911799
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
17941806
await fa
1807+
1808+
# second operation should fail
17951809
with self.assertRaises(RuntimeError) as err:
17961810
await fb
17971811
assert "already running" in str(err.exception)
1812+
1813+
# cleanup partially run generator
17981814
with self.assertRaises(StopAsyncIteration):
17991815
await agenerator.asend(None) # close it
18001816

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+
18011823
self.loop.run_until_complete(run())
18021824

18031825
def test_ag_running(self):

0 commit comments

Comments
 (0)