Commit 2a37f8f5 authored by Dan Rose's avatar Dan Rose Committed by Miss Islington (bot)

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
parent cf7d5ef4
...@@ -951,6 +951,12 @@ class HTMLDoc(Doc): ...@@ -951,6 +951,12 @@ class HTMLDoc(Doc):
else: else:
note = ' unbound %s method' % self.classlink(imclass,mod) note = ' unbound %s method' % self.classlink(imclass,mod)
if (inspect.iscoroutinefunction(object) or
inspect.isasyncgenfunction(object)):
asyncqualifier = 'async '
else:
asyncqualifier = ''
if name == realname: if name == realname:
title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname) title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
else: else:
...@@ -979,8 +985,8 @@ class HTMLDoc(Doc): ...@@ -979,8 +985,8 @@ class HTMLDoc(Doc):
if not argspec: if not argspec:
argspec = '(...)' argspec = '(...)'
decl = title + self.escape(argspec) + (note and self.grey( decl = asyncqualifier + title + self.escape(argspec) + (note and
'<font face="helvetica, arial">%s</font>' % note)) self.grey('<font face="helvetica, arial">%s</font>' % note))
if skipdocs: if skipdocs:
return '<dl><dt>%s</dt></dl>\n' % decl return '<dl><dt>%s</dt></dl>\n' % decl
...@@ -1382,6 +1388,12 @@ location listed above. ...@@ -1382,6 +1388,12 @@ location listed above.
else: else:
note = ' unbound %s method' % classname(imclass,mod) note = ' unbound %s method' % classname(imclass,mod)
if (inspect.iscoroutinefunction(object) or
inspect.isasyncgenfunction(object)):
asyncqualifier = 'async '
else:
asyncqualifier = ''
if name == realname: if name == realname:
title = self.bold(realname) title = self.bold(realname)
else: else:
...@@ -1405,7 +1417,7 @@ location listed above. ...@@ -1405,7 +1417,7 @@ location listed above.
argspec = argspec[1:-1] # remove parentheses argspec = argspec[1:-1] # remove parentheses
if not argspec: if not argspec:
argspec = '(...)' argspec = '(...)'
decl = title + argspec + note decl = asyncqualifier + title + argspec + note
if skipdocs: if skipdocs:
return decl + '\n' return decl + '\n'
......
...@@ -1288,6 +1288,29 @@ foo ...@@ -1288,6 +1288,29 @@ foo
Custom descriptor Custom descriptor
""") """)
def test_async_annotation(self):
async def coro_function(ign) -> int:
return 1
text = pydoc.plain(pydoc.plaintext.document(coro_function))
self.assertIn('async coro_function', text)
html = pydoc.HTMLDoc().document(coro_function)
self.assertIn(
'async <a name="-coro_function"><strong>coro_function',
html)
def test_async_generator_annotation(self):
async def an_async_generator():
yield 1
text = pydoc.plain(pydoc.plaintext.document(an_async_generator))
self.assertIn('async an_async_generator', text)
html = pydoc.HTMLDoc().document(an_async_generator)
self.assertIn(
'async <a name="-an_async_generator"><strong>an_async_generator',
html)
class PydocServerTest(unittest.TestCase): class PydocServerTest(unittest.TestCase):
"""Tests for pydoc._start_server""" """Tests for pydoc._start_server"""
......
builtins.help() now prefixes `async` for async functions
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment