| 
									
										
										
										
											2021-07-01 16:13:59 +03:00
										 |  |  | __all__ = 'iscoroutinefunction', 'iscoroutine' | 
					
						
							| 
									
										
										
										
											2014-06-29 00:46:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-19 07:18:45 -05:00
										 |  |  | import collections.abc | 
					
						
							| 
									
										
										
										
											2014-06-29 00:46:45 +02:00
										 |  |  | import inspect | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											2014-06-30 14:39:11 +02:00
										 |  |  | import types | 
					
						
							| 
									
										
										
										
											2014-06-29 00:46:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-30 14:39:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 07:14:07 -08:00
										 |  |  | def _is_debug_mode(): | 
					
						
							| 
									
										
										
										
											2021-07-01 16:13:59 +03:00
										 |  |  |     # See: https://docs.python.org/3/library/asyncio-dev.html#asyncio-debug-mode. | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |     return sys.flags.dev_mode or (not sys.flags.ignore_environment and | 
					
						
							|  |  |  |                                   bool(os.environ.get('PYTHONASYNCIODEBUG'))) | 
					
						
							| 
									
										
										
										
											2017-11-20 07:14:07 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 15:20:34 -05:00
										 |  |  | # A marker for iscoroutinefunction. | 
					
						
							|  |  |  | _is_coroutine = object() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-29 00:46:45 +02:00
										 |  |  | def iscoroutinefunction(func): | 
					
						
							|  |  |  |     """Return True if func is a decorated coroutine function.""" | 
					
						
							| 
									
										
										
										
											2017-11-29 18:23:43 +02:00
										 |  |  |     return (inspect.iscoroutinefunction(func) or | 
					
						
							|  |  |  |             getattr(func, '_is_coroutine', None) is _is_coroutine) | 
					
						
							| 
									
										
										
										
											2014-06-29 00:46:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-29 18:23:43 +02:00
										 |  |  | # Prioritize native coroutine check to speed-up | 
					
						
							|  |  |  | # asyncio.iscoroutine. | 
					
						
							|  |  |  | _COROUTINE_TYPES = (types.CoroutineType, types.GeneratorType, | 
					
						
							| 
									
										
										
										
											2021-07-01 16:13:59 +03:00
										 |  |  |                     collections.abc.Coroutine) | 
					
						
							| 
									
										
										
										
											2017-12-19 07:18:45 -05:00
										 |  |  | _iscoroutine_typecache = set() | 
					
						
							| 
									
										
										
										
											2015-05-13 15:21:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-30 14:39:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-29 00:46:45 +02:00
										 |  |  | def iscoroutine(obj): | 
					
						
							|  |  |  |     """Return True if obj is a coroutine object.""" | 
					
						
							| 
									
										
										
										
											2017-12-19 07:18:45 -05:00
										 |  |  |     if type(obj) in _iscoroutine_typecache: | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if isinstance(obj, _COROUTINE_TYPES): | 
					
						
							|  |  |  |         # Just in case we don't want to cache more than 100 | 
					
						
							|  |  |  |         # positive types.  That shouldn't ever happen, unless | 
					
						
							|  |  |  |         # someone stressing the system on purpose. | 
					
						
							|  |  |  |         if len(_iscoroutine_typecache) < 100: | 
					
						
							|  |  |  |             _iscoroutine_typecache.add(type(obj)) | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2014-06-29 00:46:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _format_coroutine(coro): | 
					
						
							|  |  |  |     assert iscoroutine(coro) | 
					
						
							| 
									
										
										
										
											2015-05-02 18:38:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |     def get_name(coro): | 
					
						
							|  |  |  |         # Coroutines compiled with Cython sometimes don't have | 
					
						
							|  |  |  |         # proper __qualname__ or __name__.  While that is a bug | 
					
						
							|  |  |  |         # in Cython, asyncio shouldn't crash with an AttributeError | 
					
						
							|  |  |  |         # in its __repr__ functions. | 
					
						
							|  |  |  |         if hasattr(coro, '__qualname__') and coro.__qualname__: | 
					
						
							|  |  |  |             coro_name = coro.__qualname__ | 
					
						
							|  |  |  |         elif hasattr(coro, '__name__') and coro.__name__: | 
					
						
							|  |  |  |             coro_name = coro.__name__ | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             # Stop masking Cython bugs, expose them in a friendly way. | 
					
						
							|  |  |  |             coro_name = f'<{type(coro).__name__} without __name__>' | 
					
						
							|  |  |  |         return f'{coro_name}()' | 
					
						
							| 
									
										
										
										
											2016-10-05 19:32:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |     def is_running(coro): | 
					
						
							| 
									
										
										
										
											2016-10-05 19:32:49 -04:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |             return coro.cr_running | 
					
						
							| 
									
										
										
										
											2016-10-05 19:32:49 -04:00
										 |  |  |         except AttributeError: | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |                 return coro.gi_running | 
					
						
							| 
									
										
										
										
											2016-10-05 19:32:49 -04:00
										 |  |  |             except AttributeError: | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |                 return False | 
					
						
							| 
									
										
										
										
											2016-10-05 19:32:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |     coro_code = None | 
					
						
							|  |  |  |     if hasattr(coro, 'cr_code') and coro.cr_code: | 
					
						
							|  |  |  |         coro_code = coro.cr_code | 
					
						
							|  |  |  |     elif hasattr(coro, 'gi_code') and coro.gi_code: | 
					
						
							|  |  |  |         coro_code = coro.gi_code | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     coro_name = get_name(coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not coro_code: | 
					
						
							|  |  |  |         # Built-in types might not have __qualname__ or __name__. | 
					
						
							|  |  |  |         if is_running(coro): | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |             return f'{coro_name} running' | 
					
						
							| 
									
										
										
										
											2016-10-05 19:32:49 -04:00
										 |  |  |         else: | 
					
						
							|  |  |  |             return coro_name | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |     coro_frame = None | 
					
						
							|  |  |  |     if hasattr(coro, 'gi_frame') and coro.gi_frame: | 
					
						
							| 
									
										
										
										
											2015-06-24 10:30:14 -04:00
										 |  |  |         coro_frame = coro.gi_frame | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |     elif hasattr(coro, 'cr_frame') and coro.cr_frame: | 
					
						
							| 
									
										
										
										
											2015-06-24 10:30:14 -04:00
										 |  |  |         coro_frame = coro.cr_frame | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  |     # If Cython's coroutine has a fake code object without proper | 
					
						
							|  |  |  |     # co_filename -- expose that. | 
					
						
							|  |  |  |     filename = coro_code.co_filename or '<empty co_filename>' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-11 08:42:49 +02:00
										 |  |  |     lineno = 0 | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-01 16:13:59 +03:00
										 |  |  |     if coro_frame is not None: | 
					
						
							| 
									
										
										
										
											2015-06-24 10:30:14 -04:00
										 |  |  |         lineno = coro_frame.f_lineno | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |         coro_repr = f'{coro_name} running at {filename}:{lineno}' | 
					
						
							| 
									
										
										
										
											2018-05-28 16:27:34 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-29 00:46:45 +02:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2015-06-24 10:30:14 -04:00
										 |  |  |         lineno = coro_code.co_firstlineno | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |         coro_repr = f'{coro_name} done, defined at {filename}:{lineno}' | 
					
						
							| 
									
										
										
										
											2014-07-11 00:21:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return coro_repr |