diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2014-06-25 19:41:58 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2014-06-25 19:41:58 (GMT) |
commit | 975735f729df6b7767556d2d389b560dbc7500ac (patch) | |
tree | 8579740ca947c8323088a452d659e4c0cb130a2e /Lib/test/test_asyncio/test_tasks.py | |
parent | 65c623de74cba3eff6d8f5f4c37cfec89c0fde43 (diff) | |
download | cpython-975735f729df6b7767556d2d389b560dbc7500ac.zip cpython-975735f729df6b7767556d2d389b560dbc7500ac.tar.gz cpython-975735f729df6b7767556d2d389b560dbc7500ac.tar.bz2 |
asyncio, Tulip issue 177: Rewite repr() of Future, Task, Handle and TimerHandle
- Uniformize repr() output to format "<Class ...>"
- On Python 3.5+, repr(Task) uses the qualified name instead of the short name
of the coroutine
Diffstat (limited to 'Lib/test/test_asyncio/test_tasks.py')
-rw-r--r-- | Lib/test/test_asyncio/test_tasks.py | 78 |
1 files changed, 47 insertions, 31 deletions
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 3037f60..7851745 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -26,7 +26,7 @@ def coroutine_function(): class Dummy: def __repr__(self): - return 'Dummy()' + return '<Dummy>' def __call__(self, *args): pass @@ -122,6 +122,7 @@ class TaskTests(test_utils.TestCase): yield from [] return 'abc' + # test coroutine function self.assertEqual(notmuch.__name__, 'notmuch') if PY35: self.assertEqual(notmuch.__qualname__, @@ -131,72 +132,87 @@ class TaskTests(test_utils.TestCase): filename, lineno = test_utils.get_function_source(notmuch) src = "%s:%s" % (filename, lineno) + # test coroutine object gen = notmuch() + if PY35: + coro_qualname = 'TaskTests.test_task_repr.<locals>.notmuch' + else: + coro_qualname = 'notmuch' self.assertEqual(gen.__name__, 'notmuch') if PY35: self.assertEqual(gen.__qualname__, - 'TaskTests.test_task_repr.<locals>.notmuch') + coro_qualname) + # test pending Task t = asyncio.Task(gen, loop=self.loop) t.add_done_callback(Dummy()) + coro = '%s() at %s' % (coro_qualname, src) self.assertEqual(repr(t), - 'Task(<notmuch at %s>)<PENDING, [Dummy()]>' % src) + '<Task pending %s cb=[<Dummy>()]>' % coro) + # test cancelling Task t.cancel() # Does not take immediate effect! self.assertEqual(repr(t), - 'Task(<notmuch at %s>)<CANCELLING, [Dummy()]>' % src) + '<Task cancelling %s cb=[<Dummy>()]>' % coro) + + # test cancelled Task self.assertRaises(asyncio.CancelledError, self.loop.run_until_complete, t) + coro = '%s() done at %s' % (coro_qualname, src) self.assertEqual(repr(t), - 'Task(<notmuch done at %s:%s>)<CANCELLED>' - % (filename, lineno)) + '<Task cancelled %s>' % coro) + # test finished Task t = asyncio.Task(notmuch(), loop=self.loop) self.loop.run_until_complete(t) self.assertEqual(repr(t), - "Task(<notmuch done at %s:%s>)<result='abc'>" - % (filename, lineno)) + "<Task finished %s result='abc'>" % coro) - def test_task_repr_custom(self): + def test_task_repr_coro_decorator(self): @asyncio.coroutine def notmuch(): - pass + # notmuch() function doesn't use yield from: it will be wrapped by + # @coroutine decorator + return 123 + # test coroutine function self.assertEqual(notmuch.__name__, 'notmuch') - self.assertEqual(notmuch.__module__, __name__) if PY35: self.assertEqual(notmuch.__qualname__, - 'TaskTests.test_task_repr_custom.<locals>.notmuch') - - class T(asyncio.Future): - def __repr__(self): - return 'T[]' - - class MyTask(asyncio.Task, T): - def __repr__(self): - return super().__repr__() + 'TaskTests.test_task_repr_coro_decorator.<locals>.notmuch') + self.assertEqual(notmuch.__module__, __name__) + # test coroutine object gen = notmuch() - if PY35 or tasks._DEBUG: + if PY35: # On Python >= 3.5, generators now inherit the name of the # function, as expected, and have a qualified name (__qualname__ - # attribute). In debug mode, @coroutine decorator uses CoroWrapper - # which gets its name (__name__ attribute) from the wrapped - # coroutine function. + # attribute). coro_name = 'notmuch' + coro_qualname = 'TaskTests.test_task_repr_coro_decorator.<locals>.notmuch' + elif tasks._DEBUG: + # In debug mode, @coroutine decorator uses CoroWrapper which gets + # its name (__name__ attribute) from the wrapped coroutine + # function. + coro_name = 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 - coro_name = 'coro' + coro_name = coro_qualname = 'coro' self.assertEqual(gen.__name__, coro_name) if PY35: - self.assertEqual(gen.__qualname__, - 'TaskTests.test_task_repr_custom.<locals>.notmuch') + self.assertEqual(gen.__qualname__, coro_qualname) + + # format the coroutine object + code = gen.gi_code + coro = ('%s() at %s:%s' + % (coro_qualname, code.co_filename, code.co_firstlineno)) - t = MyTask(gen, loop=self.loop) - filename = gen.gi_code.co_filename - lineno = gen.gi_frame.f_lineno - self.assertEqual(repr(t), 'T[](<%s at %s:%s>)' % (coro_name, filename, lineno)) + # test pending Task + t = asyncio.Task(gen, loop=self.loop) + t.add_done_callback(Dummy()) + self.assertEqual(repr(t), + '<Task pending %s cb=[<Dummy>()]>' % coro) def test_task_basics(self): @asyncio.coroutine |