[Python-checkins] cpython (3.4): asyncio: sync with Tulip

victor.stinner python-checkins at python.org
Fri Jul 11 00:25:51 CEST 2014


http://hg.python.org/cpython/rev/2bbfefe414ab
changeset:   91629:2bbfefe414ab
branch:      3.4
parent:      91627:f13cde63ca73
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Fri Jul 11 00:21:27 2014 +0200
summary:
  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().

files:
  Lib/asyncio/base_events.py          |   5 +-
  Lib/asyncio/coroutines.py           |  24 ++++++--
  Lib/asyncio/tasks.py                |   7 ++-
  Lib/test/test_asyncio/test_tasks.py |  49 ++++++++++++++--
  4 files changed, 70 insertions(+), 15 deletions(-)


diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -155,7 +155,10 @@
         """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
--- a/Lib/asyncio/coroutines.py
+++ b/Lib/asyncio/coroutines.py
@@ -57,7 +57,7 @@
 
 
 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 @@
         # 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 @@
         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
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -101,7 +101,12 @@
         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
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -24,6 +24,19 @@
     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 @@
         # 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 @@
         # 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 @@
         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)

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list