summaryrefslogtreecommitdiff
path: root/tests/test_tasks.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_tasks.py')
-rw-r--r--tests/test_tasks.py430
1 files changed, 209 insertions, 221 deletions
diff --git a/tests/test_tasks.py b/tests/test_tasks.py
index 770f218..e1a8a27 100644
--- a/tests/test_tasks.py
+++ b/tests/test_tasks.py
@@ -6,15 +6,17 @@ import sys
import types
import unittest
import weakref
-from test import support
-from test.script_helper import assert_python_ok
-from unittest import mock
-import asyncio
-from asyncio import coroutines
-from asyncio import test_utils
+import trollius as asyncio
+from trollius import From, Return
+from trollius import coroutines
+from trollius import test_support as support
+from trollius import test_utils
+from trollius.test_support import assert_python_ok
+from trollius.test_utils import mock
+PY33 = (sys.version_info >= (3, 3))
PY34 = (sys.version_info >= (3, 4))
PY35 = (sys.version_info >= (3, 5))
@@ -136,9 +138,14 @@ class TaskTests(test_utils.TestCase):
self.loop.set_debug(False)
@asyncio.coroutine
+ def noop():
+ yield From(None)
+ raise Return('abc')
+
+ @asyncio.coroutine
def notmuch():
- yield from []
- return 'abc'
+ yield From(noop())
+ raise Return('abc')
# test coroutine function
self.assertEqual(notmuch.__name__, 'notmuch')
@@ -152,7 +159,7 @@ class TaskTests(test_utils.TestCase):
# test coroutine object
gen = notmuch()
- if coroutines._DEBUG or PY35:
+ if PY35 or (coroutines._DEBUG and PY33):
coro_qualname = 'TaskTests.test_task_repr.<locals>.notmuch'
else:
coro_qualname = 'notmuch'
@@ -196,7 +203,7 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def notmuch():
- # notmuch() function doesn't use yield from: it will be wrapped by
+ # notmuch() function doesn't use yield: it will be wrapped by
# @coroutine decorator
return 123
@@ -209,12 +216,15 @@ class TaskTests(test_utils.TestCase):
# test coroutine object
gen = notmuch()
- if coroutines._DEBUG or PY35:
+ if PY35 or coroutines._DEBUG:
# On Python >= 3.5, generators now inherit the name of the
# function, as expected, and have a qualified name (__qualname__
# attribute).
coro_name = 'notmuch'
- coro_qualname = 'TaskTests.test_task_repr_coro_decorator.<locals>.notmuch'
+ if PY35 or (coroutines._DEBUG and PY33):
+ coro_qualname = 'TaskTests.test_task_repr_coro_decorator.<locals>.notmuch'
+ else:
+ coro_qualname = 'notmuch'
else:
# On Python < 3.5, generators inherit the name of the code, not of
# the function. See: http://bugs.python.org/issue21205
@@ -261,7 +271,8 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def wait_for(fut):
- return (yield from fut)
+ res = yield From(fut)
+ raise Return(res)
fut = asyncio.Future(loop=self.loop)
task = asyncio.Task(wait_for(fut), loop=self.loop)
@@ -275,9 +286,9 @@ class TaskTests(test_utils.TestCase):
def test_task_basics(self):
@asyncio.coroutine
def outer():
- a = yield from inner1()
- b = yield from inner2()
- return a+b
+ a = yield From(inner1())
+ b = yield From(inner2())
+ raise Return(a+b)
@asyncio.coroutine
def inner1():
@@ -301,10 +312,11 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def task():
- yield from asyncio.sleep(10.0, loop=loop)
- return 12
+ yield From(asyncio.sleep(10.0, loop=loop))
+ raise Return(12)
t = asyncio.Task(task(), loop=loop)
+ test_utils.run_briefly(loop)
loop.call_soon(t.cancel)
with self.assertRaises(asyncio.CancelledError):
loop.run_until_complete(t)
@@ -315,9 +327,9 @@ class TaskTests(test_utils.TestCase):
def test_cancel_yield(self):
@asyncio.coroutine
def task():
- yield
- yield
- return 12
+ yield From(None)
+ yield From(None)
+ raise Return(12)
t = asyncio.Task(task(), loop=self.loop)
test_utils.run_briefly(self.loop) # start coro
@@ -333,8 +345,8 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def task():
- yield from f
- return 12
+ yield From(f)
+ raise Return(12)
t = asyncio.Task(task(), loop=self.loop)
test_utils.run_briefly(self.loop) # start task
@@ -349,8 +361,8 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def task():
- yield from f
- return 12
+ yield From(f)
+ raise Return(12)
t = asyncio.Task(task(), loop=self.loop)
test_utils.run_briefly(self.loop)
@@ -371,11 +383,11 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def task():
- yield from fut1
+ yield From(fut1)
try:
- yield from fut2
+ yield From(fut2)
except asyncio.CancelledError:
- return 42
+ raise Return(42)
t = asyncio.Task(task(), loop=self.loop)
test_utils.run_briefly(self.loop)
@@ -396,13 +408,13 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def task():
- yield from fut1
+ yield From(fut1)
try:
- yield from fut2
+ yield From(fut2)
except asyncio.CancelledError:
pass
- res = yield from fut3
- return res
+ res = yield From(fut3)
+ raise Return(res)
t = asyncio.Task(task(), loop=self.loop)
test_utils.run_briefly(self.loop)
@@ -429,8 +441,8 @@ class TaskTests(test_utils.TestCase):
t.cancel()
self.assertTrue(t._must_cancel) # White-box test.
# The sleep should be cancelled immediately.
- yield from asyncio.sleep(100, loop=loop)
- return 12
+ yield From(asyncio.sleep(100, loop=loop))
+ raise Return(12)
t = asyncio.Task(task(), loop=loop)
self.assertRaises(
@@ -452,17 +464,16 @@ class TaskTests(test_utils.TestCase):
loop = self.new_test_loop(gen)
- x = 0
+ non_local = {'x': 0}
waiters = []
@asyncio.coroutine
def task():
- nonlocal x
- while x < 10:
+ while non_local['x'] < 10:
waiters.append(asyncio.sleep(0.1, loop=loop))
- yield from waiters[-1]
- x += 1
- if x == 2:
+ yield From(waiters[-1])
+ non_local['x'] += 1
+ if non_local['x'] == 3:
loop.stop()
t = asyncio.Task(task(), loop=loop)
@@ -471,7 +482,7 @@ class TaskTests(test_utils.TestCase):
self.assertEqual(str(cm.exception),
'Event loop stopped before Future completed.')
self.assertFalse(t.done())
- self.assertEqual(x, 2)
+ self.assertEqual(non_local['x'], 3)
self.assertAlmostEqual(0.3, loop.time())
# close generators
@@ -482,6 +493,7 @@ class TaskTests(test_utils.TestCase):
def test_wait_for(self):
+ @asyncio.coroutine
def gen():
when = yield
self.assertAlmostEqual(0.2, when)
@@ -491,27 +503,34 @@ class TaskTests(test_utils.TestCase):
loop = self.new_test_loop(gen)
- foo_running = None
+ non_local = {'foo_running': None}
@asyncio.coroutine
def foo():
- nonlocal foo_running
- foo_running = True
+ non_local['foo_running'] = True
try:
- yield from asyncio.sleep(0.2, loop=loop)
+ yield From(asyncio.sleep(0.2, loop=loop))
finally:
- foo_running = False
- return 'done'
+ non_local['foo_running'] = False
+ raise Return('done')
fut = asyncio.Task(foo(), loop=loop)
+ test_utils.run_briefly(loop)
with self.assertRaises(asyncio.TimeoutError):
loop.run_until_complete(asyncio.wait_for(fut, 0.1, loop=loop))
+
+ # Trollius issue #2: need to run the loop briefly to ensure that the
+ # cancellation is propagated to all tasks
+ waiter = asyncio.Future(loop=loop)
+ fut.add_done_callback(lambda f: waiter.set_result(True))
+ loop.run_until_complete(waiter)
+
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)
+ self.assertEqual(non_local['foo_running'], False)
def test_wait_for_blocking(self):
loop = self.new_test_loop()
@@ -538,17 +557,24 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def foo():
- yield from asyncio.sleep(0.2, loop=loop)
- return 'done'
+ yield From(asyncio.sleep(0.2, loop=loop))
+ raise Return('done')
asyncio.set_event_loop(loop)
try:
fut = asyncio.Task(foo(), loop=loop)
+ test_utils.run_briefly(loop)
with self.assertRaises(asyncio.TimeoutError):
loop.run_until_complete(asyncio.wait_for(fut, 0.01))
finally:
asyncio.set_event_loop(None)
+ # Trollius issue #2: need to run the loop briefly to ensure that the
+ # cancellation is propagated to all tasks
+ waiter = asyncio.Future(loop=loop)
+ fut.add_done_callback(lambda f: waiter.set_result(True))
+ loop.run_until_complete(waiter)
+
self.assertAlmostEqual(0.01, loop.time())
self.assertTrue(fut.done())
self.assertTrue(fut.cancelled())
@@ -584,10 +610,10 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def foo():
- done, pending = yield from asyncio.wait([b, a], loop=loop)
+ done, pending = yield From(asyncio.wait([b, a], loop=loop))
self.assertEqual(done, set([a, b]))
self.assertEqual(pending, set())
- return 42
+ raise Return(42)
res = loop.run_until_complete(asyncio.Task(foo(), loop=loop))
self.assertEqual(res, 42)
@@ -614,10 +640,10 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def foo():
- done, pending = yield from asyncio.wait([b, a])
+ done, pending = yield From(asyncio.wait([b, a]))
self.assertEqual(done, set([a, b]))
self.assertEqual(pending, set())
- return 42
+ raise Return(42)
asyncio.set_event_loop(loop)
res = loop.run_until_complete(
@@ -638,7 +664,7 @@ class TaskTests(test_utils.TestCase):
done, pending = self.loop.run_until_complete(task)
self.assertFalse(pending)
- self.assertEqual(set(f.result() for f in done), {'test', 'spam'})
+ self.assertEqual(set(f.result() for f in done), set(('test', 'spam')))
def test_wait_errors(self):
self.assertRaises(
@@ -672,8 +698,8 @@ class TaskTests(test_utils.TestCase):
loop=loop)
done, pending = loop.run_until_complete(task)
- self.assertEqual({b}, done)
- self.assertEqual({a}, pending)
+ self.assertEqual(set((b,)), done)
+ self.assertEqual(set((a,)), pending)
self.assertFalse(a.done())
self.assertTrue(b.done())
self.assertIsNone(b.result())
@@ -689,12 +715,12 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def coro1():
- yield
+ yield From(None)
@asyncio.coroutine
def coro2():
- yield
- yield
+ yield From(None)
+ yield From(None)
a = asyncio.Task(coro1(), loop=self.loop)
b = asyncio.Task(coro2(), loop=self.loop)
@@ -704,7 +730,7 @@ class TaskTests(test_utils.TestCase):
loop=self.loop)
done, pending = self.loop.run_until_complete(task)
- self.assertEqual({a, b}, done)
+ self.assertEqual(set((a, b)), done)
self.assertTrue(a.done())
self.assertIsNone(a.result())
self.assertTrue(b.done())
@@ -733,8 +759,8 @@ class TaskTests(test_utils.TestCase):
loop=loop)
done, pending = loop.run_until_complete(task)
- self.assertEqual({b}, done)
- self.assertEqual({a}, pending)
+ self.assertEqual(set((b,)), done)
+ self.assertEqual(set((a,)), pending)
self.assertAlmostEqual(0, loop.time())
# move forward to close generator
@@ -757,7 +783,7 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def exc():
- yield from asyncio.sleep(0.01, loop=loop)
+ yield From(asyncio.sleep(0.01, loop=loop))
raise ZeroDivisionError('err')
b = asyncio.Task(exc(), loop=loop)
@@ -765,8 +791,8 @@ class TaskTests(test_utils.TestCase):
loop=loop)
done, pending = loop.run_until_complete(task)
- self.assertEqual({b}, done)
- self.assertEqual({a}, pending)
+ self.assertEqual(set((b,)), done)
+ self.assertEqual(set((a,)), pending)
self.assertAlmostEqual(0.01, loop.time())
# move forward to close generator
@@ -788,14 +814,14 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def sleeper():
- yield from asyncio.sleep(0.15, loop=loop)
+ yield From(asyncio.sleep(0.15, loop=loop))
raise ZeroDivisionError('really')
b = asyncio.Task(sleeper(), loop=loop)
@asyncio.coroutine
def foo():
- done, pending = yield from asyncio.wait([b, a], loop=loop)
+ done, pending = yield From(asyncio.wait([b, a], loop=loop))
self.assertEqual(len(done), 2)
self.assertEqual(pending, set())
errors = set(f for f in done if f.exception() is not None)
@@ -825,8 +851,8 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def foo():
- done, pending = yield from asyncio.wait([b, a], timeout=0.11,
- loop=loop)
+ done, pending = yield From(asyncio.wait([b, a], timeout=0.11,
+ loop=loop))
self.assertEqual(done, set([a]))
self.assertEqual(pending, set([b]))
@@ -876,17 +902,16 @@ class TaskTests(test_utils.TestCase):
# disable "slow callback" warning
loop.slow_callback_duration = 1.0
completed = set()
- time_shifted = False
+ non_local = {'time_shifted': False}
@asyncio.coroutine
def sleeper(dt, x):
- nonlocal time_shifted
- yield from asyncio.sleep(dt, loop=loop)
+ yield From(asyncio.sleep(dt, loop=loop))
completed.add(x)
- if not time_shifted and 'a' in completed and 'b' in completed:
- time_shifted = True
+ if not non_local['time_shifted'] and 'a' in completed and 'b' in completed:
+ non_local['time_shifted'] = True
loop.advance_time(0.14)
- return x
+ raise Return(x)
a = sleeper(0.01, 'a')
b = sleeper(0.01, 'b')
@@ -896,8 +921,8 @@ class TaskTests(test_utils.TestCase):
def foo():
values = []
for f in asyncio.as_completed([b, c, a], loop=loop):
- values.append((yield from f))
- return values
+ values.append((yield From(f)))
+ raise Return(values)
res = loop.run_until_complete(asyncio.Task(foo(), loop=loop))
self.assertAlmostEqual(0.15, loop.time())
@@ -929,11 +954,11 @@ class TaskTests(test_utils.TestCase):
if values:
loop.advance_time(0.02)
try:
- v = yield from f
+ v = yield From(f)
values.append((1, v))
except asyncio.TimeoutError as exc:
values.append((2, exc))
- return values
+ raise Return(values)
res = loop.run_until_complete(asyncio.Task(foo(), loop=loop))
self.assertEqual(len(res), 2, res)
@@ -960,7 +985,7 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def foo():
for f in asyncio.as_completed([a], timeout=1, loop=loop):
- v = yield from f
+ v = yield From(f)
self.assertEqual(v, 'a')
loop.run_until_complete(asyncio.Task(foo(), loop=loop))
@@ -976,7 +1001,7 @@ class TaskTests(test_utils.TestCase):
a = asyncio.sleep(0.05, 'a', loop=loop)
b = asyncio.sleep(0.10, 'b', loop=loop)
- fs = {a, b}
+ fs = set((a, b))
futs = list(asyncio.as_completed(fs, loop=loop))
self.assertEqual(len(futs), 2)
@@ -1001,12 +1026,12 @@ class TaskTests(test_utils.TestCase):
a = asyncio.sleep(0.05, 'a', loop=loop)
b = asyncio.sleep(0.05, 'b', loop=loop)
- fs = {a, b}
+ fs = set((a, b))
futs = list(asyncio.as_completed(fs, loop=loop))
self.assertEqual(len(futs), 2)
waiter = asyncio.wait(futs, loop=loop)
done, pending = loop.run_until_complete(waiter)
- self.assertEqual(set(f.result() for f in done), {'a', 'b'})
+ self.assertEqual(set(f.result() for f in done), set(('a', 'b')))
def test_as_completed_duplicate_coroutines(self):
@@ -1020,13 +1045,13 @@ class TaskTests(test_utils.TestCase):
c = coro('ham')
for f in asyncio.as_completed([c, c, coro('spam')],
loop=self.loop):
- result.append((yield from f))
- return result
+ result.append((yield From(f)))
+ raise Return(result)
fut = asyncio.Task(runner(), loop=self.loop)
self.loop.run_until_complete(fut)
result = fut.result()
- self.assertEqual(set(result), {'ham', 'spam'})
+ self.assertEqual(set(result), set(('ham', 'spam')))
self.assertEqual(len(result), 2)
def test_sleep(self):
@@ -1042,9 +1067,9 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def sleeper(dt, arg):
- yield from asyncio.sleep(dt/2, loop=loop)
- res = yield from asyncio.sleep(dt/2, arg, loop=loop)
- return res
+ yield From(asyncio.sleep(dt/2, loop=loop))
+ res = yield From(asyncio.sleep(dt/2, arg, loop=loop))
+ raise Return(res)
t = asyncio.Task(sleeper(0.1, 'yeah'), loop=loop)
loop.run_until_complete(t)
@@ -1064,22 +1089,21 @@ class TaskTests(test_utils.TestCase):
t = asyncio.Task(asyncio.sleep(10.0, 'yeah', loop=loop),
loop=loop)
- handle = None
+ non_local = {'handle': None}
orig_call_later = loop.call_later
def call_later(delay, callback, *args):
- nonlocal handle
- handle = orig_call_later(delay, callback, *args)
- return handle
+ non_local['handle'] = orig_call_later(delay, callback, *args)
+ return non_local['handle']
loop.call_later = call_later
test_utils.run_briefly(loop)
- self.assertFalse(handle._cancelled)
+ self.assertFalse(non_local['handle']._cancelled)
t.cancel()
test_utils.run_briefly(loop)
- self.assertTrue(handle._cancelled)
+ self.assertTrue(non_local['handle']._cancelled)
def test_task_cancel_sleeping_task(self):
@@ -1094,18 +1118,18 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def sleep(dt):
- yield from asyncio.sleep(dt, loop=loop)
+ yield From(asyncio.sleep(dt, loop=loop))
@asyncio.coroutine
def doit():
sleeper = asyncio.Task(sleep(5000), loop=loop)
loop.call_later(0.1, sleeper.cancel)
try:
- yield from sleeper
+ yield From(sleeper)
except asyncio.CancelledError:
- return 'cancelled'
+ raise Return('cancelled')
else:
- return 'slept in'
+ raise Return('slept in')
doer = doit()
self.assertEqual(loop.run_until_complete(doer), 'cancelled')
@@ -1116,7 +1140,7 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def coro():
- yield from fut
+ yield From(fut)
task = asyncio.Task(coro(), loop=self.loop)
test_utils.run_briefly(self.loop)
@@ -1144,9 +1168,9 @@ class TaskTests(test_utils.TestCase):
def test_step_result(self):
@asyncio.coroutine
def notmuch():
- yield None
- yield 1
- return 'ko'
+ yield From(None)
+ yield From(1)
+ raise Return('ko')
self.assertRaises(
RuntimeError, self.loop.run_until_complete, notmuch())
@@ -1157,19 +1181,18 @@ class TaskTests(test_utils.TestCase):
class Fut(asyncio.Future):
def __init__(self, *args, **kwds):
self.cb_added = False
- super().__init__(*args, **kwds)
+ super(Fut, self).__init__(*args, **kwds)
def add_done_callback(self, fn):
self.cb_added = True
- super().add_done_callback(fn)
+ super(Fut, self).add_done_callback(fn)
fut = Fut(loop=self.loop)
- result = None
+ non_local = {'result': None}
@asyncio.coroutine
def wait_for_future():
- nonlocal result
- result = yield from fut
+ non_local['result'] = yield From(fut)
t = asyncio.Task(wait_for_future(), loop=self.loop)
test_utils.run_briefly(self.loop)
@@ -1178,7 +1201,7 @@ class TaskTests(test_utils.TestCase):
res = object()
fut.set_result(res)
test_utils.run_briefly(self.loop)
- self.assertIs(res, result)
+ self.assertIs(res, non_local['result'])
self.assertTrue(t.done())
self.assertIsNone(t.result())
@@ -1204,24 +1227,24 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def sleeper():
- yield from asyncio.sleep(10, loop=loop)
+ yield From(asyncio.sleep(10, loop=loop))
base_exc = BaseException()
@asyncio.coroutine
def notmutch():
try:
- yield from sleeper()
+ yield From(sleeper())
except asyncio.CancelledError:
raise base_exc
task = asyncio.Task(notmutch(), loop=loop)
- test_utils.run_briefly(loop)
+ test_utils.run_briefly(loop, 2)
task.cancel()
self.assertFalse(task.done())
- self.assertRaises(BaseException, test_utils.run_briefly, loop)
+ self.assertRaises(BaseException, test_utils.run_briefly, loop, 2)
self.assertTrue(task.done())
self.assertFalse(task.cancelled())
@@ -1242,37 +1265,6 @@ class TaskTests(test_utils.TestCase):
yield
self.assertTrue(asyncio.iscoroutinefunction(fn2))
- def test_yield_vs_yield_from(self):
- fut = asyncio.Future(loop=self.loop)
-
- @asyncio.coroutine
- def wait_for_future():
- yield fut
-
- task = wait_for_future()
- with self.assertRaises(RuntimeError):
- self.loop.run_until_complete(task)
-
- self.assertFalse(fut.done())
-
- def test_yield_vs_yield_from_generator(self):
- @asyncio.coroutine
- def coro():
- yield
-
- @asyncio.coroutine
- def wait_for_future():
- gen = coro()
- try:
- yield gen
- finally:
- gen.close()
-
- task = wait_for_future()
- self.assertRaises(
- RuntimeError,
- self.loop.run_until_complete, task)
-
def test_coroutine_non_gen_function(self):
@asyncio.coroutine
def func():
@@ -1323,7 +1315,7 @@ class TaskTests(test_utils.TestCase):
@asyncio.coroutine
def coro1(loop):
self.assertTrue(asyncio.Task.current_task(loop=loop) is task1)
- yield from fut1
+ yield From(fut1)
self.assertTrue(asyncio.Task.current_task(loop=loop) is task1)
fut2.set_result(True)
@@ -1331,7 +1323,7 @@ class TaskTests(test_utils.TestCase):
def coro2(loop):
self.assertTrue(asyncio.Task.current_task(loop=loop) is task2)
fut1.set_result(True)
- yield from fut2
+ yield From(fut2)
self.assertTrue(asyncio.Task.current_task(loop=loop) is task2)
task1 = asyncio.Task(coro1(self.loop), loop=self.loop)
@@ -1346,54 +1338,50 @@ class TaskTests(test_utils.TestCase):
def test_yield_future_passes_cancel(self):
# Cancelling outer() cancels inner() cancels waiter.
- proof = 0
+ non_local = {'proof': 0}
waiter = asyncio.Future(loop=self.loop)
@asyncio.coroutine
def inner():
- nonlocal proof
try:
- yield from waiter
+ yield From(waiter)
except asyncio.CancelledError:
- proof += 1
+ non_local['proof'] += 1
raise
else:
self.fail('got past sleep() in inner()')
@asyncio.coroutine
def outer():
- nonlocal proof
try:
- yield from inner()
+ yield From(inner())
except asyncio.CancelledError:
- proof += 100 # Expect this path.
+ non_local['proof'] += 100 # Expect this path.
else:
- proof += 10
+ non_local['proof'] += 10
f = asyncio.async(outer(), loop=self.loop)
test_utils.run_briefly(self.loop)
f.cancel()
self.loop.run_until_complete(f)
- self.assertEqual(proof, 101)
+ self.assertEqual(non_local['proof'], 101)
self.assertTrue(waiter.cancelled())
def test_yield_wait_does_not_shield_cancel(self):
# Cancelling outer() makes wait() return early, leaves inner()
# running.
- proof = 0
+ non_local = {'proof': 0}
waiter = asyncio.Future(loop=self.loop)
@asyncio.coroutine
def inner():
- nonlocal proof
- yield from waiter
- proof += 1
+ yield From(waiter)
+ non_local['proof'] += 1
@asyncio.coroutine
def outer():
- nonlocal proof
- d, p = yield from asyncio.wait([inner()], loop=self.loop)
- proof += 100
+ d, p = yield From(asyncio.wait([inner()], loop=self.loop))
+ non_local['proof'] += 100
f = asyncio.async(outer(), loop=self.loop)
test_utils.run_briefly(self.loop)
@@ -1402,7 +1390,7 @@ class TaskTests(test_utils.TestCase):
asyncio.CancelledError, self.loop.run_until_complete, f)
waiter.set_result(None)
test_utils.run_briefly(self.loop)
- self.assertEqual(proof, 1)
+ self.assertEqual(non_local['proof'], 1)
def test_shield_result(self):
inner = asyncio.Future(loop=self.loop)
@@ -1436,20 +1424,18 @@ class TaskTests(test_utils.TestCase):
def test_shield_effect(self):
# Cancelling outer() does not affect inner().
- proof = 0
+ non_local = {'proof': 0}
waiter = asyncio.Future(loop=self.loop)
@asyncio.coroutine
def inner():
- nonlocal proof
- yield from waiter
- proof += 1
+ yield From(waiter)
+ non_local['proof'] += 1
@asyncio.coroutine
def outer():
- nonlocal proof
- yield from asyncio.shield(inner(), loop=self.loop)
- proof += 100
+ yield From(asyncio.shield(inner(), loop=self.loop))
+ non_local['proof'] += 100
f = asyncio.async(outer(), loop=self.loop)
test_utils.run_briefly(self.loop)
@@ -1458,7 +1444,7 @@ class TaskTests(test_utils.TestCase):
self.loop.run_until_complete(f)
waiter.set_result(None)
test_utils.run_briefly(self.loop)
- self.assertEqual(proof, 1)
+ self.assertEqual(non_local['proof'], 1)
def test_shield_gather(self):
child1 = asyncio.Future(loop=self.loop)
@@ -1527,7 +1513,7 @@ class TaskTests(test_utils.TestCase):
def coro():
# The actual coroutine.
self.assertTrue(gen.gi_running)
- yield from fut
+ yield From(fut)
# A completed Future used to run the coroutine.
fut = asyncio.Future(loop=self.loop)
@@ -1569,13 +1555,15 @@ class TaskTests(test_utils.TestCase):
try:
@asyncio.coroutine
def t1():
- return (yield from t2())
+ res = yield From(t2())
+ raise Return(res)
@asyncio.coroutine
def t2():
f = asyncio.Future(loop=self.loop)
asyncio.Task(t3(f), loop=self.loop)
- return (yield from f)
+ res = yield From(f)
+ raise Return(res)
@asyncio.coroutine
def t3(f):
@@ -1590,7 +1578,7 @@ class TaskTests(test_utils.TestCase):
def test_yield_from_corowrapper_send(self):
def foo():
a = yield
- return a
+ raise Return(a)
def call(arg):
cw = asyncio.coroutines.CoroWrapper(foo(), foo)
@@ -1598,7 +1586,8 @@ class TaskTests(test_utils.TestCase):
try:
cw.send(arg)
except StopIteration as ex:
- return ex.args[0]
+ ex.raised = True
+ return ex.value
else:
raise AssertionError('StopIteration was expected')
@@ -1607,18 +1596,19 @@ class TaskTests(test_utils.TestCase):
def test_corowrapper_weakref(self):
wd = weakref.WeakValueDictionary()
- def foo(): yield from []
+ def foo():
+ yield From(None)
cw = asyncio.coroutines.CoroWrapper(foo(), foo)
wd['cw'] = cw # Would fail without __weakref__ slot.
cw.gen = None # Suppress warning from __del__.
- @unittest.skipUnless(PY34,
- 'need python 3.4 or later')
+ @test_utils.skipUnless(PY34,
+ 'need python 3.4 or later')
def test_log_destroyed_pending_task(self):
@asyncio.coroutine
def kill_me(loop):
future = asyncio.Future(loop=loop)
- yield from future
+ yield From(future)
# at this point, the only reference to kill_me() task is
# the Task._wakeup() method in future._callbacks
raise Exception("code never reached")
@@ -1630,7 +1620,7 @@ class TaskTests(test_utils.TestCase):
# schedule the task
coro = kill_me(self.loop)
task = asyncio.async(coro, loop=self.loop)
- self.assertEqual(asyncio.Task.all_tasks(loop=self.loop), {task})
+ self.assertEqual(asyncio.Task.all_tasks(loop=self.loop), set((task,)))
# execute the task so it waits for future
self.loop._run_once()
@@ -1654,7 +1644,7 @@ class TaskTests(test_utils.TestCase):
})
mock_handler.reset_mock()
- @mock.patch('asyncio.coroutines.logger')
+ @mock.patch('trollius.coroutines.logger')
def test_coroutine_never_yielded(self, m_log):
debug = asyncio.coroutines._DEBUG
try:
@@ -1665,7 +1655,7 @@ class TaskTests(test_utils.TestCase):
finally:
asyncio.coroutines._DEBUG = debug
- tb_filename = __file__
+ tb_filename = sys._getframe().f_code.co_filename
tb_lineno = sys._getframe().f_lineno + 2
# create a coroutine object but don't use it
coro_noop()
@@ -1674,12 +1664,13 @@ class TaskTests(test_utils.TestCase):
self.assertTrue(m_log.error.called)
message = m_log.error.call_args[0][0]
func_filename, func_lineno = test_utils.get_function_source(coro_noop)
+ coro_name = getattr(coro_noop, '__qualname__', coro_noop.__name__)
regex = (r'^<CoroWrapper %s\(\) .* at %s:%s, .*> was never yielded from\n'
r'Coroutine object created at \(most recent call last\):\n'
r'.*\n'
r' File "%s", line %s, in test_coroutine_never_yielded\n'
r' coro_noop\(\)$'
- % (re.escape(coro_noop.__qualname__),
+ % (re.escape(coro_name),
re.escape(func_filename), func_lineno,
re.escape(tb_filename), tb_lineno))
@@ -1689,14 +1680,23 @@ class TaskTests(test_utils.TestCase):
self.loop.set_debug(True)
task = asyncio.Task(coroutine_function(), loop=self.loop)
- lineno = sys._getframe().f_lineno - 1
- self.assertIsInstance(task._source_traceback, list)
- self.assertEqual(task._source_traceback[-1][:3],
- (__file__,
- lineno,
- 'test_task_source_traceback'))
+ self.check_soure_traceback(task._source_traceback, -1)
self.loop.run_until_complete(task)
+ def test_coroutine_class(self):
+ # Trollius issue #9
+ self.loop.set_debug(True)
+
+ class MyClass(object):
+ def __call__(self):
+ return 7
+
+ obj = MyClass()
+ coro_func = asyncio.coroutine(obj)
+ coro_obj = coro_func()
+ res = self.loop.run_until_complete(coro_obj)
+ self.assertEqual(res, 7)
+
class GatherTestsBase:
@@ -1772,30 +1772,19 @@ class GatherTestsBase:
aio_path = os.path.dirname(os.path.dirname(asyncio.__file__))
code = '\n'.join((
- 'import asyncio.coroutines',
- 'print(asyncio.coroutines._DEBUG)'))
-
- # Test with -E to not fail if the unit test was run with
- # PYTHONASYNCIODEBUG set to a non-empty string
- sts, stdout, stderr = assert_python_ok('-E', '-c', code,
- PYTHONPATH=aio_path)
- self.assertEqual(stdout.rstrip(), b'False')
+ 'import trollius.coroutines',
+ 'print(trollius.coroutines._DEBUG)'))
sts, stdout, stderr = assert_python_ok('-c', code,
- PYTHONASYNCIODEBUG='',
+ TROLLIUSDEBUG='',
PYTHONPATH=aio_path)
self.assertEqual(stdout.rstrip(), b'False')
sts, stdout, stderr = assert_python_ok('-c', code,
- PYTHONASYNCIODEBUG='1',
+ TROLLIUSDEBUG='1',
PYTHONPATH=aio_path)
self.assertEqual(stdout.rstrip(), b'True')
- sts, stdout, stderr = assert_python_ok('-E', '-c', code,
- PYTHONASYNCIODEBUG='1',
- PYTHONPATH=aio_path)
- self.assertEqual(stdout.rstrip(), b'False')
-
class FutureGatherTests(GatherTestsBase, test_utils.TestCase):
@@ -1884,7 +1873,7 @@ class FutureGatherTests(GatherTestsBase, test_utils.TestCase):
class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
def setUp(self):
- super().setUp()
+ super(CoroutineGatherTests, self).setUp()
asyncio.set_event_loop(self.one_loop)
def wrap_futures(self, *futures):
@@ -1892,7 +1881,8 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
for fut in futures:
@asyncio.coroutine
def coro(fut=fut):
- return (yield from fut)
+ result = (yield From(fut))
+ raise Return(result)
coros.append(coro())
return coros
@@ -1924,44 +1914,42 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
def test_cancellation_broadcast(self):
# Cancelling outer() cancels all children.
- proof = 0
+ non_local = {'proof': 0}
waiter = asyncio.Future(loop=self.one_loop)
@asyncio.coroutine
def inner():
- nonlocal proof
- yield from waiter
- proof += 1
+ yield From(waiter)
+ non_local['proof'] += 1
child1 = asyncio.async(inner(), loop=self.one_loop)
child2 = asyncio.async(inner(), loop=self.one_loop)
- gatherer = None
+ non_local['gatherer'] = None
@asyncio.coroutine
def outer():
- nonlocal proof, gatherer
- gatherer = asyncio.gather(child1, child2, loop=self.one_loop)
- yield from gatherer
- proof += 100
+ non_local['gatherer'] = asyncio.gather(child1, child2, loop=self.one_loop)
+ yield From(non_local['gatherer'])
+ non_local['proof'] += 100
f = asyncio.async(outer(), loop=self.one_loop)
test_utils.run_briefly(self.one_loop)
self.assertTrue(f.cancel())
with self.assertRaises(asyncio.CancelledError):
self.one_loop.run_until_complete(f)
- self.assertFalse(gatherer.cancel())
+ self.assertFalse(non_local['gatherer'].cancel())
self.assertTrue(waiter.cancelled())
self.assertTrue(child1.cancelled())
self.assertTrue(child2.cancelled())
test_utils.run_briefly(self.one_loop)
- self.assertEqual(proof, 0)
+ self.assertEqual(non_local['proof'], 0)
def test_exception_marking(self):
# Test for the first line marked "Mark exception retrieved."
@asyncio.coroutine
def inner(f):
- yield from f
+ yield From(f)
raise RuntimeError('should not be ignored')
a = asyncio.Future(loop=self.one_loop)
@@ -1969,7 +1957,7 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
@asyncio.coroutine
def outer():
- yield from asyncio.gather(inner(a), inner(b), loop=self.one_loop)
+ yield From(asyncio.gather(inner(a), inner(b), loop=self.one_loop))
f = asyncio.async(outer(), loop=self.one_loop)
test_utils.run_briefly(self.one_loop)