mirror of
https://github.com/python/cpython.git
synced 2025-09-13 12:17:24 +00:00
asyncio: wait_for() now cancels the future on timeout. Patch written by Gustavo
Carneiro.
This commit is contained in:
parent
183e347796
commit
421e49b5c1
2 changed files with 18 additions and 17 deletions
|
@ -382,8 +382,9 @@ def wait_for(fut, timeout, *, loop=None):
|
||||||
|
|
||||||
Coroutine will be wrapped in Task.
|
Coroutine will be wrapped in Task.
|
||||||
|
|
||||||
Returns result of the Future or coroutine. Raises TimeoutError when
|
Returns result of the Future or coroutine. When a timeout occurs,
|
||||||
timeout occurs.
|
it cancels the task and raises TimeoutError. To avoid the task
|
||||||
|
cancellation, wrap it in shield().
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
|
@ -405,6 +406,7 @@ def wait_for(fut, timeout, *, loop=None):
|
||||||
return fut.result()
|
return fut.result()
|
||||||
else:
|
else:
|
||||||
fut.remove_done_callback(cb)
|
fut.remove_done_callback(cb)
|
||||||
|
fut.cancel()
|
||||||
raise futures.TimeoutError()
|
raise futures.TimeoutError()
|
||||||
finally:
|
finally:
|
||||||
timeout_handle.cancel()
|
timeout_handle.cancel()
|
||||||
|
|
|
@ -355,30 +355,32 @@ class TaskTests(unittest.TestCase):
|
||||||
when = yield 0
|
when = yield 0
|
||||||
self.assertAlmostEqual(0.1, when)
|
self.assertAlmostEqual(0.1, when)
|
||||||
when = yield 0.1
|
when = yield 0.1
|
||||||
self.assertAlmostEqual(0.4, when)
|
|
||||||
yield 0.1
|
|
||||||
|
|
||||||
loop = test_utils.TestLoop(gen)
|
loop = test_utils.TestLoop(gen)
|
||||||
self.addCleanup(loop.close)
|
self.addCleanup(loop.close)
|
||||||
|
|
||||||
|
foo_running = None
|
||||||
|
|
||||||
@tasks.coroutine
|
@tasks.coroutine
|
||||||
def foo():
|
def foo():
|
||||||
|
nonlocal foo_running
|
||||||
|
foo_running = True
|
||||||
|
try:
|
||||||
yield from tasks.sleep(0.2, loop=loop)
|
yield from tasks.sleep(0.2, loop=loop)
|
||||||
|
finally:
|
||||||
|
foo_running = False
|
||||||
return 'done'
|
return 'done'
|
||||||
|
|
||||||
fut = tasks.Task(foo(), loop=loop)
|
fut = tasks.Task(foo(), loop=loop)
|
||||||
|
|
||||||
with self.assertRaises(futures.TimeoutError):
|
with self.assertRaises(futures.TimeoutError):
|
||||||
loop.run_until_complete(tasks.wait_for(fut, 0.1, loop=loop))
|
loop.run_until_complete(tasks.wait_for(fut, 0.1, loop=loop))
|
||||||
|
self.assertTrue(fut.done())
|
||||||
self.assertFalse(fut.done())
|
# it should have been cancelled due to the timeout
|
||||||
|
self.assertTrue(fut.cancelled())
|
||||||
self.assertAlmostEqual(0.1, loop.time())
|
self.assertAlmostEqual(0.1, loop.time())
|
||||||
|
self.assertEqual(foo_running, False)
|
||||||
|
|
||||||
# wait for result
|
|
||||||
res = loop.run_until_complete(
|
|
||||||
tasks.wait_for(fut, 0.3, loop=loop))
|
|
||||||
self.assertEqual(res, 'done')
|
|
||||||
self.assertAlmostEqual(0.2, loop.time())
|
|
||||||
|
|
||||||
def test_wait_for_with_global_loop(self):
|
def test_wait_for_with_global_loop(self):
|
||||||
|
|
||||||
|
@ -406,11 +408,8 @@ class TaskTests(unittest.TestCase):
|
||||||
events.set_event_loop(None)
|
events.set_event_loop(None)
|
||||||
|
|
||||||
self.assertAlmostEqual(0.01, loop.time())
|
self.assertAlmostEqual(0.01, loop.time())
|
||||||
self.assertFalse(fut.done())
|
self.assertTrue(fut.done())
|
||||||
|
self.assertTrue(fut.cancelled())
|
||||||
# move forward to close generator
|
|
||||||
loop.advance_time(10)
|
|
||||||
loop.run_until_complete(fut)
|
|
||||||
|
|
||||||
def test_wait(self):
|
def test_wait(self):
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue