mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									cf7d5ef49b
								
							
						
					
					
						commit
						2a37f8f55b
					
				
					 3 changed files with 39 additions and 3 deletions
				
			
		
							
								
								
									
										18
									
								
								Lib/pydoc.py
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								Lib/pydoc.py
									
										
									
									
									
								
							|  | @ -951,6 +951,12 @@ def docroutine(self, object, name=None, mod=None, | ||||||
|                 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 @@ def docroutine(self, object, name=None, mod=None, | ||||||
|         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 @@ def docroutine(self, object, name=None, mod=None, cl=None): | ||||||
|                 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 @@ def docroutine(self, object, name=None, mod=None, cl=None): | ||||||
|                     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 @@ class X: | ||||||
|     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""" | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | builtins.help() now prefixes `async` for async functions | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Rose
						Dan Rose