]> granicus.if.org Git - python/commitdiff
bpo-33672: Fix Task.__repr__ crash with Cython's bogus coroutines (GH-7180)
authorYury Selivanov <yury@magic.io>
Tue, 29 May 2018 04:55:27 +0000 (00:55 -0400)
committerGitHub <noreply@github.com>
Tue, 29 May 2018 04:55:27 +0000 (00:55 -0400)
[3.6 backport of 989b9e0]

Lib/asyncio/coroutines.py
Lib/asyncio/events.py
Lib/test/test_asyncio/test_events.py
Misc/NEWS.d/next/Library/2018-05-28-17-45-06.bpo-33672.GM_Xm_.rst [new file with mode: 0644]

index 520a309f846049e9b9bb719037e0a54f34798ace..a9022f92a52a1a982b9a63a9ecd10981c391d531 100644 (file)
@@ -310,18 +310,25 @@ def _format_coroutine(coro):
     if coro_name is None:
         coro_name = events._format_callback(func, (), {})
 
-    try:
-        coro_code = coro.gi_code
-    except AttributeError:
+    coro_code = None
+    if hasattr(coro, 'cr_code') and coro.cr_code:
         coro_code = coro.cr_code
+    elif hasattr(coro, 'gi_code') and coro.gi_code:
+        coro_code = coro.gi_code
 
-    try:
-        coro_frame = coro.gi_frame
-    except AttributeError:
+    coro_frame = None
+    if hasattr(coro, 'cr_frame') and coro.cr_frame:
         coro_frame = coro.cr_frame
+    elif hasattr(coro, 'gi_frame') and coro.gi_frame:
+        coro_frame = coro.gi_frame
+
+    filename = '<empty co_filename>'
+    if coro_code and coro_code.co_filename:
+        filename = coro_code.co_filename
 
-    filename = coro_code.co_filename
     lineno = 0
+    coro_repr = coro_name
+
     if (isinstance(coro, CoroWrapper) and
             not inspect.isgeneratorfunction(coro.func) and
             coro.func is not None):
@@ -338,7 +345,7 @@ def _format_coroutine(coro):
         lineno = coro_frame.f_lineno
         coro_repr = ('%s running at %s:%s'
                      % (coro_name, filename, lineno))
-    else:
+    elif coro_code:
         lineno = coro_code.co_firstlineno
         coro_repr = ('%s done, defined at %s:%s'
                      % (coro_name, filename, lineno))
index 05dc8969f44a6a9b526117f82b1a42458f78e8c2..e654efc5526a47602b84675e266eb506b3f919da 100644 (file)
@@ -58,10 +58,10 @@ def _format_callback(func, args, kwargs, suffix=''):
         suffix = _format_args_and_kwargs(args, kwargs) + suffix
         return _format_callback(func.func, func.args, func.keywords, suffix)
 
-    if hasattr(func, '__qualname__'):
-        func_repr = getattr(func, '__qualname__')
-    elif hasattr(func, '__name__'):
-        func_repr = getattr(func, '__name__')
+    if hasattr(func, '__qualname__') and func.__qualname__:
+        func_repr = func.__qualname__
+    elif hasattr(func, '__name__') and func.__name__:
+        func_repr = func.__name__
     else:
         func_repr = repr(func)
 
index 1ecc89f2e758f8f22d31e6a592782860d88a14a4..548a4610f7729e8c303d95b3589275e3f77f6670 100644 (file)
@@ -2467,6 +2467,28 @@ class HandleTests(test_utils.TestCase):
         # built-in async_gen.asend().
         self.assertEqual(coroutines._format_coroutine(coro), 'Coro()')
 
+        coro = Coro()
+        coro.__qualname__ = 'AAA'
+        coro.cr_code = None
+        self.assertEqual(coroutines._format_coroutine(coro), 'AAA()')
+
+        coro = Coro()
+        coro.__qualname__ = 'AAA'
+        coro.cr_code = None
+        coro.cr_frame = None
+        self.assertEqual(coroutines._format_coroutine(coro), 'AAA()')
+
+        coro = Coro()
+        coro.__qualname__ = None
+        coro.cr_code = None
+        coro.cr_frame = None
+        self.assertEqual(coroutines._format_coroutine(coro), f'{repr(coro)}()')
+
+        coro = Coro()
+        coro.cr_code = None
+        coro.cr_frame = None
+        self.assertEqual(coroutines._format_coroutine(coro), f'{repr(coro)}()')
+
 
 class TimerTests(unittest.TestCase):
 
diff --git a/Misc/NEWS.d/next/Library/2018-05-28-17-45-06.bpo-33672.GM_Xm_.rst b/Misc/NEWS.d/next/Library/2018-05-28-17-45-06.bpo-33672.GM_Xm_.rst
new file mode 100644 (file)
index 0000000..36373c0
--- /dev/null
@@ -0,0 +1 @@
+Fix Task.__repr__ crash with Cython's bogus coroutines