Skip to content

Commit 8dc3e43

Browse files
author
Yury Selivanov
committed
Issue #28372: Fix asyncio to support formatting of non-python coroutines
1 parent 0de3de6 commit 8dc3e43

3 files changed

Lines changed: 55 additions & 0 deletions

File tree

Lib/asyncio/coroutines.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,25 @@ def iscoroutine(obj):
261261
def _format_coroutine(coro):
262262
assert iscoroutine(coro)
263263

264+
if not hasattr(coro, 'cr_code') and not hasattr(coro, 'gi_code'):
265+
# Most likely a Cython coroutine.
266+
coro_name = getattr(coro, '__qualname__', coro.__name__)
267+
coro_name = '{}()'.format(coro_name)
268+
269+
running = False
270+
try:
271+
running = coro.cr_running
272+
except AttributeError:
273+
try:
274+
running = coro.gi_running
275+
except AttributeError:
276+
pass
277+
278+
if running:
279+
return '{} running'.format(coro_name)
280+
else:
281+
return coro_name
282+
264283
coro_name = None
265284
if isinstance(coro, CoroWrapper):
266285
func = coro.func

Lib/test/test_asyncio/test_events.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Tests for events.py."""
22

3+
import collections.abc
34
import functools
45
import gc
56
import io
@@ -25,6 +26,7 @@
2526
import tty
2627

2728
import asyncio
29+
from asyncio import coroutines
2830
from asyncio import proactor_events
2931
from asyncio import selector_events
3032
from asyncio import sslproto
@@ -2380,6 +2382,38 @@ def check_source_traceback(h):
23802382
h = loop.call_later(0, noop)
23812383
check_source_traceback(h)
23822384

2385+
@unittest.skipUnless(hasattr(collections.abc, 'Coroutine'),
2386+
'No collections.abc.Coroutine')
2387+
def test_coroutine_like_object_debug_formatting(self):
2388+
# Test that asyncio can format coroutines that are instances of
2389+
# collections.abc.Coroutine, but lack cr_core or gi_code attributes
2390+
# (such as ones compiled with Cython).
2391+
2392+
class Coro:
2393+
__name__ = 'AAA'
2394+
2395+
def send(self, v):
2396+
pass
2397+
2398+
def throw(self, *exc):
2399+
pass
2400+
2401+
def close(self):
2402+
pass
2403+
2404+
def __await__(self):
2405+
pass
2406+
2407+
coro = Coro()
2408+
self.assertTrue(asyncio.iscoroutine(coro))
2409+
self.assertEqual(coroutines._format_coroutine(coro), 'AAA()')
2410+
2411+
coro.__qualname__ = 'BBB'
2412+
self.assertEqual(coroutines._format_coroutine(coro), 'BBB()')
2413+
2414+
coro.cr_running = True
2415+
self.assertEqual(coroutines._format_coroutine(coro), 'BBB() running')
2416+
23832417

23842418
class TimerTests(unittest.TestCase):
23852419

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,8 @@ Library
358358

359359
- Issue #28371: Deprecate passing asyncio.Handles to run_in_executor.
360360

361+
- Issue #28372: Fix asyncio to support formatting of non-python coroutines.
362+
361363
IDLE
362364
----
363365

0 commit comments

Comments
 (0)