Skip to content

Commit 2a37f8f

Browse files
rotumiss-islington
authored andcommitted
bpo-36045: builtins.help() now prefixes async for async functions (GH-12010)
Previously, it was hard to tell whether a function should be awaited. It was also incorrect (per PEP 484) to put this in the type hint for coroutine functions. Added this info to the output of builtins.help and pydoc. https://bugs.python.org/issue36045
1 parent cf7d5ef commit 2a37f8f

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

Lib/pydoc.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,12 @@ def docroutine(self, object, name=None, mod=None,
951951
else:
952952
note = ' unbound %s method' % self.classlink(imclass,mod)
953953

954+
if (inspect.iscoroutinefunction(object) or
955+
inspect.isasyncgenfunction(object)):
956+
asyncqualifier = 'async '
957+
else:
958+
asyncqualifier = ''
959+
954960
if name == realname:
955961
title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
956962
else:
@@ -979,8 +985,8 @@ def docroutine(self, object, name=None, mod=None,
979985
if not argspec:
980986
argspec = '(...)'
981987

982-
decl = title + self.escape(argspec) + (note and self.grey(
983-
'<font face="helvetica, arial">%s</font>' % note))
988+
decl = asyncqualifier + title + self.escape(argspec) + (note and
989+
self.grey('<font face="helvetica, arial">%s</font>' % note))
984990

985991
if skipdocs:
986992
return '<dl><dt>%s</dt></dl>\n' % decl
@@ -1382,6 +1388,12 @@ def docroutine(self, object, name=None, mod=None, cl=None):
13821388
else:
13831389
note = ' unbound %s method' % classname(imclass,mod)
13841390

1391+
if (inspect.iscoroutinefunction(object) or
1392+
inspect.isasyncgenfunction(object)):
1393+
asyncqualifier = 'async '
1394+
else:
1395+
asyncqualifier = ''
1396+
13851397
if name == realname:
13861398
title = self.bold(realname)
13871399
else:
@@ -1405,7 +1417,7 @@ def docroutine(self, object, name=None, mod=None, cl=None):
14051417
argspec = argspec[1:-1] # remove parentheses
14061418
if not argspec:
14071419
argspec = '(...)'
1408-
decl = title + argspec + note
1420+
decl = asyncqualifier + title + argspec + note
14091421

14101422
if skipdocs:
14111423
return decl + '\n'

Lib/test/test_pydoc.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,29 @@ class X:
12881288
Custom descriptor
12891289
""")
12901290

1291+
def test_async_annotation(self):
1292+
async def coro_function(ign) -> int:
1293+
return 1
1294+
1295+
text = pydoc.plain(pydoc.plaintext.document(coro_function))
1296+
self.assertIn('async coro_function', text)
1297+
1298+
html = pydoc.HTMLDoc().document(coro_function)
1299+
self.assertIn(
1300+
'async <a name="-coro_function"><strong>coro_function',
1301+
html)
1302+
1303+
def test_async_generator_annotation(self):
1304+
async def an_async_generator():
1305+
yield 1
1306+
1307+
text = pydoc.plain(pydoc.plaintext.document(an_async_generator))
1308+
self.assertIn('async an_async_generator', text)
1309+
1310+
html = pydoc.HTMLDoc().document(an_async_generator)
1311+
self.assertIn(
1312+
'async <a name="-an_async_generator"><strong>an_async_generator',
1313+
html)
12911314

12921315
class PydocServerTest(unittest.TestCase):
12931316
"""Tests for pydoc._start_server"""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
builtins.help() now prefixes `async` for async functions

0 commit comments

Comments
 (0)