Skip to content

Commit e151f83

Browse files
authored
bpo-33672: Fix Task.__repr__ crash with Cython's bogus coroutines (GH-7180)
[3.6 backport of 989b9e0]
1 parent 7593b8a commit e151f83

File tree

4 files changed

+42
-12
lines changed

4 files changed

+42
-12
lines changed

‎Lib/asyncio/coroutines.py‎

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -310,18 +310,25 @@ def _format_coroutine(coro):
310310
if coro_name is None:
311311
coro_name = events._format_callback(func, (), {})
312312

313-
try:
314-
coro_code = coro.gi_code
315-
except AttributeError:
313+
coro_code = None
314+
if hasattr(coro, 'cr_code') and coro.cr_code:
316315
coro_code = coro.cr_code
316+
elif hasattr(coro, 'gi_code') and coro.gi_code:
317+
coro_code = coro.gi_code
317318

318-
try:
319-
coro_frame = coro.gi_frame
320-
except AttributeError:
319+
coro_frame = None
320+
if hasattr(coro, 'cr_frame') and coro.cr_frame:
321321
coro_frame = coro.cr_frame
322+
elif hasattr(coro, 'gi_frame') and coro.gi_frame:
323+
coro_frame = coro.gi_frame
324+
325+
filename = '<empty co_filename>'
326+
if coro_code and coro_code.co_filename:
327+
filename = coro_code.co_filename
322328

323-
filename = coro_code.co_filename
324329
lineno = 0
330+
coro_repr = coro_name
331+
325332
if (isinstance(coro, CoroWrapper) and
326333
not inspect.isgeneratorfunction(coro.func) and
327334
coro.func is not None):
@@ -338,7 +345,7 @@ def _format_coroutine(coro):
338345
lineno = coro_frame.f_lineno
339346
coro_repr = ('%s running at %s:%s'
340347
% (coro_name, filename, lineno))
341-
else:
348+
elif coro_code:
342349
lineno = coro_code.co_firstlineno
343350
coro_repr = ('%s done, defined at %s:%s'
344351
% (coro_name, filename, lineno))

‎Lib/asyncio/events.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ def _format_callback(func, args, kwargs, suffix=''):
5858
suffix = _format_args_and_kwargs(args, kwargs) + suffix
5959
return _format_callback(func.func, func.args, func.keywords, suffix)
6060

61-
if hasattr(func, '__qualname__'):
62-
func_repr = getattr(func, '__qualname__')
63-
elif hasattr(func, '__name__'):
64-
func_repr = getattr(func, '__name__')
61+
if hasattr(func, '__qualname__') and func.__qualname__:
62+
func_repr = func.__qualname__
63+
elif hasattr(func, '__name__') and func.__name__:
64+
func_repr = func.__name__
6565
else:
6666
func_repr = repr(func)
6767

‎Lib/test/test_asyncio/test_events.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,6 +2467,28 @@ def __await__(self):
24672467
# built-in async_gen.asend().
24682468
self.assertEqual(coroutines._format_coroutine(coro), 'Coro()')
24692469

2470+
coro = Coro()
2471+
coro.__qualname__ = 'AAA'
2472+
coro.cr_code = None
2473+
self.assertEqual(coroutines._format_coroutine(coro), 'AAA()')
2474+
2475+
coro = Coro()
2476+
coro.__qualname__ = 'AAA'
2477+
coro.cr_code = None
2478+
coro.cr_frame = None
2479+
self.assertEqual(coroutines._format_coroutine(coro), 'AAA()')
2480+
2481+
coro = Coro()
2482+
coro.__qualname__ = None
2483+
coro.cr_code = None
2484+
coro.cr_frame = None
2485+
self.assertEqual(coroutines._format_coroutine(coro), f'{repr(coro)}()')
2486+
2487+
coro = Coro()
2488+
coro.cr_code = None
2489+
coro.cr_frame = None
2490+
self.assertEqual(coroutines._format_coroutine(coro), f'{repr(coro)}()')
2491+
24702492

24712493
class TimerTests(unittest.TestCase):
24722494

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix Task.__repr__ crash with Cython's bogus coroutines

0 commit comments

Comments
 (0)