Kaydet (Commit) 3d67615a authored tarafından Yury Selivanov's avatar Yury Selivanov

Issue #26923: Fix asyncio.Gather to refuse being cancelled once all children are done.

Patch by Johannes Ebke.
üst f8c15057
......@@ -592,9 +592,11 @@ class _GatheringFuture(futures.Future):
def cancel(self):
if self.done():
return False
ret = False
for child in self._children:
child.cancel()
return True
if child.cancel():
ret = True
return ret
def gather(*coros_or_futures, loop=None, return_exceptions=False):
......
......@@ -1899,6 +1899,36 @@ class TaskTests(test_utils.TestCase):
def test_cancel_wait_for(self):
self._test_cancel_wait_for(60.0)
def test_cancel_gather(self):
"""Ensure that a gathering future refuses to be cancelled once all
children are done"""
loop = asyncio.new_event_loop()
self.addCleanup(loop.close)
fut = asyncio.Future(loop=loop)
# The indirection fut->child_coro is needed since otherwise the
# gathering task is done at the same time as the child future
def child_coro():
return (yield from fut)
gather_future = asyncio.gather(child_coro(), loop=loop)
gather_task = asyncio.ensure_future(gather_future, loop=loop)
cancel_result = None
def cancelling_callback(_):
nonlocal cancel_result
cancel_result = gather_task.cancel()
fut.add_done_callback(cancelling_callback)
fut.set_result(42) # calls the cancelling_callback after fut is done()
# At this point the task should complete.
loop.run_until_complete(gather_task)
# Python issue #26923: asyncio.gather drops cancellation
self.assertEqual(cancel_result, False)
self.assertFalse(gather_task.cancelled())
self.assertEqual(gather_task.result(), [42])
class GatherTestsBase:
......
......@@ -398,6 +398,10 @@ Library
- Issue #27972: Prohibit Tasks to await on themselves.
- Issue #26923: Fix asyncio.Gather to refuse being cancelled once all
children are done.
Patch by Johannes Ebke.
IDLE
----
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment