diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2014-06-27 11:52:20 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2014-06-27 11:52:20 (GMT) |
commit | 80f53aa9a0b2af28c9d8052c46b452cccb8e0b41 (patch) | |
tree | 2f1714ab75a7d22f9c719a5890459278d4d581fa /Lib/asyncio/tasks.py | |
parent | bbd96c6f47046e11f47de06550dcd1c816aad71c (diff) | |
download | cpython-80f53aa9a0b2af28c9d8052c46b452cccb8e0b41.zip cpython-80f53aa9a0b2af28c9d8052c46b452cccb8e0b41.tar.gz cpython-80f53aa9a0b2af28c9d8052c46b452cccb8e0b41.tar.bz2 |
asyncio, Tulip issue 137: In debug mode, save traceback where Future, Task and
Handle objects are created. Pass the traceback to call_exception_handler() in
the 'source_traceback' key.
The traceback is truncated to hide internal calls in asyncio, show only the
traceback from user code.
Add tests for the new source_traceback, and a test for the 'Future/Task
exception was never retrieved' log.
Diffstat (limited to 'Lib/asyncio/tasks.py')
-rw-r--r-- | Lib/asyncio/tasks.py | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 89ec3a4..db0bbf3 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -195,6 +195,8 @@ class Task(futures.Future): def __init__(self, coro, *, loop=None): assert iscoroutine(coro), repr(coro) # Not a coroutine function! super().__init__(loop=loop) + if self._source_traceback: + del self._source_traceback[-1] self._coro = iter(coro) # Use the iterator just in case. self._fut_waiter = None self._must_cancel = False @@ -207,10 +209,13 @@ class Task(futures.Future): if _PY34: def __del__(self): if self._state == futures._PENDING: - self._loop.call_exception_handler({ + context = { 'task': self, 'message': 'Task was destroyed but it is pending!', - }) + } + if self._source_traceback: + context['source_traceback'] = self._source_traceback + self._loop.call_exception_handler(context) futures.Future.__del__(self) def __repr__(self): @@ -620,7 +625,10 @@ def async(coro_or_future, *, loop=None): raise ValueError('loop argument must agree with Future') return coro_or_future elif iscoroutine(coro_or_future): - return Task(coro_or_future, loop=loop) + task = Task(coro_or_future, loop=loop) + if task._source_traceback: + del task._source_traceback[-1] + return task else: raise TypeError('A Future or coroutine is required') |