summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-01-22 23:00:47 +0100
committerVictor Stinner <victor.stinner@gmail.com>2014-01-22 23:00:47 +0100
commit7d7cd62df6ed616494e66dee1b53cbcf2107bf1d (patch)
tree1d749933df159b7a774222ddb0e7540f0b813d7b
parent55fd28c121eae34e7a1f03ddbb9fa880a826a3fd (diff)
downloadtrollius-7d7cd62df6ed616494e66dee1b53cbcf2107bf1d.tar.gz
wait_for() now cancels the future on timeout. Patch written by Gustavo
Carneiro.
-rw-r--r--AUTHORS1
-rw-r--r--asyncio/tasks.py6
-rw-r--r--tests/test_tasks.py29
3 files changed, 19 insertions, 17 deletions
diff --git a/AUTHORS b/AUTHORS
index c6f0b8b..263e8dc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -17,6 +17,7 @@ Contributors:
- Eli Bendersky <eliben AT gmail.com>
- Geert Jansen <geertj AT gmail.com>
- Giampaolo Rodola' <g.rodola AT gmail.com>
+- Gustavo Carneiro <gjcarneiro AT gmail.com>
- Jeff Quast
- Jonathan Slenders
- Nikolay Kim <fafhrd91 AT gmail.com>
diff --git a/asyncio/tasks.py b/asyncio/tasks.py
index 42413dc..b52933f 100644
--- a/asyncio/tasks.py
+++ b/asyncio/tasks.py
@@ -382,8 +382,9 @@ def wait_for(fut, timeout, *, loop=None):
Coroutine will be wrapped in Task.
- Returns result of the Future or coroutine. Raises TimeoutError when
- timeout occurs.
+ Returns result of the Future or coroutine. When a timeout occurs,
+ it cancels the task and raises TimeoutError. To avoid the task
+ cancellation, wrap it in shield().
Usage:
@@ -405,6 +406,7 @@ def wait_for(fut, timeout, *, loop=None):
return fut.result()
else:
fut.remove_done_callback(cb)
+ fut.cancel()
raise futures.TimeoutError()
finally:
timeout_handle.cancel()
diff --git a/tests/test_tasks.py b/tests/test_tasks.py
index 79a25d2..3d08ad8 100644
--- a/tests/test_tasks.py
+++ b/tests/test_tasks.py
@@ -355,30 +355,32 @@ class TaskTests(unittest.TestCase):
when = yield 0
self.assertAlmostEqual(0.1, when)
when = yield 0.1
- self.assertAlmostEqual(0.4, when)
- yield 0.1
loop = test_utils.TestLoop(gen)
self.addCleanup(loop.close)
+ foo_running = None
+
@tasks.coroutine
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'
fut = tasks.Task(foo(), loop=loop)
with self.assertRaises(futures.TimeoutError):
loop.run_until_complete(tasks.wait_for(fut, 0.1, loop=loop))
-
- self.assertFalse(fut.done())
+ self.assertTrue(fut.done())
+ # it should have been cancelled due to the timeout
+ self.assertTrue(fut.cancelled())
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):
@@ -406,11 +408,8 @@ class TaskTests(unittest.TestCase):
events.set_event_loop(None)
self.assertAlmostEqual(0.01, loop.time())
- self.assertFalse(fut.done())
-
- # move forward to close generator
- loop.advance_time(10)
- loop.run_until_complete(fut)
+ self.assertTrue(fut.done())
+ self.assertTrue(fut.cancelled())
def test_wait(self):