Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions Lib/asyncio/coroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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))
Expand Down
8 changes: 4 additions & 4 deletions Lib/asyncio/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
22 changes: 22 additions & 0 deletions Lib/test/test_asyncio/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -2449,6 +2449,28 @@ def __await__(self):
# 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):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix Task.__repr__ crash with Cython's bogus coroutines