summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-07-10 22:21:27 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-07-10 22:21:27 (GMT)
commitc39ba7d611fe556314acc8c11cd9f805512db663 (patch)
tree21dc6e07bea4dae7705aa9ccd26326d05303f6aa
parentf68bd88aa61ae6214d3dc5552a7e3f9cf1401507 (diff)
downloadcpython-c39ba7d611fe556314acc8c11cd9f805512db663.zip
cpython-c39ba7d611fe556314acc8c11cd9f805512db663.tar.gz
cpython-c39ba7d611fe556314acc8c11cd9f805512db663.tar.bz2
asyncio: sync with Tulip
- repr(Task) and repr(CoroWrapper) now also includes where these objects were created. If the coroutine is not a generator (don't use "yield from"), use the location of the function, not the location of the coro() wrapper. - Fix create_task(): truncate the traceback to hide the call to create_task().
-rw-r--r--Lib/asyncio/base_events.py5
-rw-r--r--Lib/asyncio/coroutines.py24
-rw-r--r--Lib/asyncio/tasks.py7
-rw-r--r--Lib/test/test_asyncio/test_tasks.py49
4 files changed, 70 insertions, 15 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 833f81d..f6d7a58 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -155,7 +155,10 @@ class BaseEventLoop(events.AbstractEventLoop):
"""Schedule a coroutine object.
Return a task object."""
- return tasks.Task(coro, loop=self)
+ task = tasks.Task(coro, loop=self)
+ if task._source_traceback:
+ del task._source_traceback[-1]
+ return task
def _make_socket_transport(self, sock, protocol, waiter=None, *,
extra=None, server=None):
diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py
index 48730c2..4cbfa85 100644
--- a/Lib/asyncio/coroutines.py
+++ b/Lib/asyncio/coroutines.py
@@ -57,7 +57,7 @@ del has_yield_from_bug
class CoroWrapper:
- # Wrapper for coroutine in _DEBUG mode.
+ # Wrapper for coroutine object in _DEBUG mode.
def __init__(self, gen, func):
assert inspect.isgenerator(gen), gen
@@ -68,8 +68,11 @@ class CoroWrapper:
# decorator
def __repr__(self):
- return ('<%s %s>'
- % (self.__class__.__name__, _format_coroutine(self)))
+ coro_repr = _format_coroutine(self)
+ if self._source_traceback:
+ frame = self._source_traceback[-1]
+ coro_repr += ', created at %s:%s' % (frame[0], frame[1])
+ return '<%s %s>' % (self.__class__.__name__, coro_repr)
def __iter__(self):
return self
@@ -181,9 +184,18 @@ def _format_coroutine(coro):
coro_name = coro.__name__
filename = coro.gi_code.co_filename
- if coro.gi_frame is not None:
+ if (isinstance(coro, CoroWrapper)
+ and not inspect.isgeneratorfunction(coro.func)):
+ filename, lineno = events._get_function_source(coro.func)
+ if coro.gi_frame is None:
+ coro_repr = '%s() done, defined at %s:%s' % (coro_name, filename, lineno)
+ else:
+ coro_repr = '%s() running, defined at %s:%s' % (coro_name, filename, lineno)
+ elif coro.gi_frame is not None:
lineno = coro.gi_frame.f_lineno
- return '%s() at %s:%s' % (coro_name, filename, lineno)
+ coro_repr = '%s() running at %s:%s' % (coro_name, filename, lineno)
else:
lineno = coro.gi_code.co_firstlineno
- return '%s() done at %s:%s' % (coro_name, filename, lineno)
+ coro_repr = '%s() done, defined at %s:%s' % (coro_name, filename, lineno)
+
+ return coro_repr
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index befc296..61f4822 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -101,7 +101,12 @@ class Task(futures.Future):
else:
info.append(self._state.lower())
- info.append(coroutines._format_coroutine(self._coro))
+ coro = coroutines._format_coroutine(self._coro)
+ info.append('coro=<%s>' % coro)
+
+ if self._source_traceback:
+ frame = self._source_traceback[-1]
+ info.append('created at %s:%s' % (frame[0], frame[1]))
if self._state == futures._FINISHED:
info.append(self._format_result())
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py
index afadc7c..b13818f 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -24,6 +24,19 @@ def coroutine_function():
pass
+def format_coroutine(qualname, state, src, source_traceback, generator=False):
+ if generator:
+ state = '%s' % state
+ else:
+ state = '%s, defined' % state
+ if source_traceback is not None:
+ frame = source_traceback[-1]
+ return ('coro=<%s() %s at %s> created at %s:%s'
+ % (qualname, state, src, frame[0], frame[1]))
+ else:
+ return 'coro=<%s() %s at %s>' % (qualname, state, src)
+
+
class Dummy:
def __repr__(self):
@@ -149,7 +162,9 @@ class TaskTests(test_utils.TestCase):
# test pending Task
t = asyncio.Task(gen, loop=self.loop)
t.add_done_callback(Dummy())
- coro = '%s() at %s' % (coro_qualname, src)
+
+ coro = format_coroutine(coro_qualname, 'running', src,
+ t._source_traceback, generator=True)
self.assertEqual(repr(t),
'<Task pending %s cb=[<Dummy>()]>' % coro)
@@ -161,13 +176,16 @@ class TaskTests(test_utils.TestCase):
# test cancelled Task
self.assertRaises(asyncio.CancelledError,
self.loop.run_until_complete, t)
- coro = '%s() done at %s' % (coro_qualname, src)
+ coro = format_coroutine(coro_qualname, 'done', src,
+ t._source_traceback)
self.assertEqual(repr(t),
'<Task cancelled %s>' % coro)
# test finished Task
t = asyncio.Task(notmuch(), loop=self.loop)
self.loop.run_until_complete(t)
+ coro = format_coroutine(coro_qualname, 'done', src,
+ t._source_traceback)
self.assertEqual(repr(t),
"<Task finished %s result='abc'>" % coro)
@@ -206,18 +224,35 @@ class TaskTests(test_utils.TestCase):
if PY35:
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))
-
# test repr(CoroWrapper)
if coroutines._DEBUG:
+ # format the coroutine object
+ if coroutines._DEBUG:
+ filename, lineno = test_utils.get_function_source(notmuch)
+ frame = gen._source_traceback[-1]
+ coro = ('%s() running, defined at %s:%s, created at %s:%s'
+ % (coro_qualname, filename, lineno,
+ frame[0], frame[1]))
+ else:
+ code = gen.gi_code
+ coro = ('%s() running at %s:%s'
+ % (coro_qualname, code.co_filename, code.co_firstlineno))
+
self.assertEqual(repr(gen), '<CoroWrapper %s>' % coro)
# test pending Task
t = asyncio.Task(gen, loop=self.loop)
t.add_done_callback(Dummy())
+
+ # format the coroutine object
+ if coroutines._DEBUG:
+ src = '%s:%s' % test_utils.get_function_source(notmuch)
+ else:
+ code = gen.gi_code
+ src = '%s:%s' % (code.co_filename, code.co_firstlineno)
+ coro = format_coroutine(coro_qualname, 'running', src,
+ t._source_traceback,
+ generator=not coroutines._DEBUG)
self.assertEqual(repr(t),
'<Task pending %s cb=[<Dummy>()]>' % coro)
self.loop.run_until_complete(t)