From 2a37f8f55b543589cc77a67b5cd17cbd9d0311c9 Mon Sep 17 00:00:00 2001 From: Dan Rose Date: Fri, 24 May 2019 06:38:01 -0500 Subject: [PATCH] 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 --- Lib/pydoc.py | 18 ++++++++++++--- Lib/test/test_pydoc.py | 23 +++++++++++++++++++ .../2019-02-24-12-44-46.bpo-36045.RO20OV.rst | 1 + 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-02-24-12-44-46.bpo-36045.RO20OV.rst diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 679a596821f..9a22e56686f 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -951,6 +951,12 @@ class HTMLDoc(Doc): else: note = ' unbound %s method' % self.classlink(imclass,mod) + if (inspect.iscoroutinefunction(object) or + inspect.isasyncgenfunction(object)): + asyncqualifier = 'async ' + else: + asyncqualifier = '' + if name == realname: title = '%s' % (anchor, realname) else: @@ -979,8 +985,8 @@ class HTMLDoc(Doc): if not argspec: argspec = '(...)' - decl = title + self.escape(argspec) + (note and self.grey( - '%s' % note)) + decl = asyncqualifier + title + self.escape(argspec) + (note and + self.grey('%s' % note)) if skipdocs: return '
%s
\n' % decl @@ -1382,6 +1388,12 @@ location listed above. else: note = ' unbound %s method' % classname(imclass,mod) + if (inspect.iscoroutinefunction(object) or + inspect.isasyncgenfunction(object)): + asyncqualifier = 'async ' + else: + asyncqualifier = '' + if name == realname: title = self.bold(realname) else: @@ -1405,7 +1417,7 @@ location listed above. argspec = argspec[1:-1] # remove parentheses if not argspec: argspec = '(...)' - decl = title + argspec + note + decl = asyncqualifier + title + argspec + note if skipdocs: return decl + '\n' diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 67c6c5d42d4..6efdeb047c2 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -1288,6 +1288,29 @@ foo 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 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 an_async_generator', + html) class PydocServerTest(unittest.TestCase): """Tests for pydoc._start_server""" diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-02-24-12-44-46.bpo-36045.RO20OV.rst b/Misc/NEWS.d/next/Core and Builtins/2019-02-24-12-44-46.bpo-36045.RO20OV.rst new file mode 100644 index 00000000000..7cab3ea8409 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-02-24-12-44-46.bpo-36045.RO20OV.rst @@ -0,0 +1 @@ +builtins.help() now prefixes `async` for async functions