summaryrefslogtreecommitdiffstats
path: root/Lib/asyncio/tasks.py
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-06-27 11:52:20 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-06-27 11:52:20 (GMT)
commit80f53aa9a0b2af28c9d8052c46b452cccb8e0b41 (patch)
tree2f1714ab75a7d22f9c719a5890459278d4d581fa /Lib/asyncio/tasks.py
parentbbd96c6f47046e11f47de06550dcd1c816aad71c (diff)
downloadcpython-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.py14
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')