summaryrefslogtreecommitdiffstats
path: root/Lib/asyncio
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-06-12 16:39:26 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-06-12 16:39:26 (GMT)
commit307bccc6ff6670c58f4c20421a29071ff710e6a3 (patch)
treee165b2e33505bcece03948112ca230af5d2d2688 /Lib/asyncio
parentf54432e2a16d445ed6fa142a9c5d8d23b11780b2 (diff)
downloadcpython-307bccc6ff6670c58f4c20421a29071ff710e6a3.zip
cpython-307bccc6ff6670c58f4c20421a29071ff710e6a3.tar.gz
cpython-307bccc6ff6670c58f4c20421a29071ff710e6a3.tar.bz2
asyncio: Tulip issue 173: Enhance repr(Handle) and repr(Task)
repr(Handle) is shorter for function: "foo" instead of "<function foo at 0x...>". It now also includes the source of the callback, filename and line number where it was defined, if available. repr(Task) now also includes the current position in the code, filename and line number, if available. If the coroutine (generator) is done, the line number is omitted and "done" is added.
Diffstat (limited to 'Lib/asyncio')
-rw-r--r--Lib/asyncio/events.py30
-rw-r--r--Lib/asyncio/tasks.py10
-rw-r--r--Lib/asyncio/test_utils.py7
3 files changed, 45 insertions, 2 deletions
diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py
index 4a9a9a3..de161df 100644
--- a/Lib/asyncio/events.py
+++ b/Lib/asyncio/events.py
@@ -8,9 +8,29 @@ __all__ = ['AbstractEventLoopPolicy',
'get_child_watcher', 'set_child_watcher',
]
+import functools
+import inspect
import subprocess
import threading
import socket
+import sys
+
+
+_PY34 = sys.version_info >= (3, 4)
+
+def _get_function_source(func):
+ if _PY34:
+ func = inspect.unwrap(func)
+ elif hasattr(func, '__wrapped__'):
+ func = func.__wrapped__
+ if inspect.isfunction(func):
+ code = func.__code__
+ return (code.co_filename, code.co_firstlineno)
+ if isinstance(func, functools.partial):
+ return _get_function_source(func.func)
+ if _PY34 and isinstance(func, functools.partialmethod):
+ return _get_function_source(func.func)
+ return None
class Handle:
@@ -26,7 +46,15 @@ class Handle:
self._cancelled = False
def __repr__(self):
- res = 'Handle({}, {})'.format(self._callback, self._args)
+ cb_repr = getattr(self._callback, '__qualname__', None)
+ if not cb_repr:
+ cb_repr = str(self._callback)
+
+ source = _get_function_source(self._callback)
+ if source:
+ cb_repr += ' at %s:%s' % source
+
+ res = 'Handle({}, {})'.format(cb_repr, self._args)
if self._cancelled:
res += '<cancelled>'
return res
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 8b8fb82..e6fd3d3 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -188,7 +188,15 @@ class Task(futures.Future):
i = res.find('<')
if i < 0:
i = len(res)
- res = res[:i] + '(<{}>)'.format(self._coro.__name__) + res[i:]
+ text = self._coro.__name__
+ coro = self._coro
+ if inspect.isgenerator(coro):
+ filename = coro.gi_code.co_filename
+ if coro.gi_frame is not None:
+ text += ' at %s:%s' % (filename, coro.gi_frame.f_lineno)
+ else:
+ text += ' done at %s' % filename
+ res = res[:i] + '(<{}>)'.format(text) + res[i:]
return res
def get_stack(self, *, limit=None):
diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py
index 9c3656a..1062bae 100644
--- a/Lib/asyncio/test_utils.py
+++ b/Lib/asyncio/test_utils.py
@@ -372,3 +372,10 @@ class MockPattern(str):
"""
def __eq__(self, other):
return bool(re.search(str(self), other, re.S))
+
+
+def get_function_source(func):
+ source = events._get_function_source(func)
+ if source is None:
+ raise ValueError("unable to get the source of %r" % (func,))
+ return source