Kaydet (Commit) 421e49b5 authored tarafından Victor Stinner's avatar Victor Stinner

asyncio: wait_for() now cancels the future on timeout. Patch written by Gustavo

Carneiro.
üst 183e3477
...@@ -382,8 +382,9 @@ def wait_for(fut, timeout, *, loop=None): ...@@ -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): ...@@ -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): ...@@ -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():
yield from tasks.sleep(0.2, loop=loop) nonlocal foo_running
foo_running = True
try:
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): ...@@ -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):
......
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