| 
									
										
										
										
											2017-12-14 09:42:21 -05:00
										 |  |  | __all__ = 'run', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from . import coroutines | 
					
						
							|  |  |  | from . import events | 
					
						
							| 
									
										
										
										
											2018-01-21 14:56:59 -05:00
										 |  |  | from . import tasks | 
					
						
							| 
									
										
										
										
											2017-12-14 09:42:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-03 13:54:09 -07:00
										 |  |  | def run(main, *, debug=None): | 
					
						
							| 
									
										
										
										
											2019-09-30 20:12:21 -04:00
										 |  |  |     """Execute the coroutine and return the result.
 | 
					
						
							| 
									
										
										
										
											2017-12-14 09:42:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     This function runs the passed coroutine, taking care of | 
					
						
							|  |  |  |     managing the asyncio event loop and finalizing asynchronous | 
					
						
							|  |  |  |     generators. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This function cannot be called when another asyncio event loop is | 
					
						
							|  |  |  |     running in the same thread. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If debug is True, the event loop will be run in debug mode. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This function always creates a new event loop and closes it at the end. | 
					
						
							|  |  |  |     It should be used as a main entry point for asyncio programs, and should | 
					
						
							|  |  |  |     ideally only be called once. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def main(): | 
					
						
							|  |  |  |             await asyncio.sleep(1) | 
					
						
							|  |  |  |             print('hello') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         asyncio.run(main()) | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if events._get_running_loop() is not None: | 
					
						
							|  |  |  |         raise RuntimeError( | 
					
						
							|  |  |  |             "asyncio.run() cannot be called from a running event loop") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not coroutines.iscoroutine(main): | 
					
						
							|  |  |  |         raise ValueError("a coroutine was expected, got {!r}".format(main)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     loop = events.new_event_loop() | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         events.set_event_loop(loop) | 
					
						
							| 
									
										
										
										
											2020-09-03 13:54:09 -07:00
										 |  |  |         if debug is not None: | 
					
						
							|  |  |  |             loop.set_debug(debug) | 
					
						
							| 
									
										
										
										
											2017-12-14 09:42:21 -05:00
										 |  |  |         return loop.run_until_complete(main) | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2018-01-21 14:56:59 -05:00
										 |  |  |             _cancel_all_tasks(loop) | 
					
						
							| 
									
										
										
										
											2017-12-14 09:42:21 -05:00
										 |  |  |             loop.run_until_complete(loop.shutdown_asyncgens()) | 
					
						
							| 
									
										
										
										
											2019-09-19 08:47:22 -04:00
										 |  |  |             loop.run_until_complete(loop.shutdown_default_executor()) | 
					
						
							| 
									
										
										
										
											2017-12-14 09:42:21 -05:00
										 |  |  |         finally: | 
					
						
							|  |  |  |             events.set_event_loop(None) | 
					
						
							|  |  |  |             loop.close() | 
					
						
							| 
									
										
										
										
											2018-01-21 14:56:59 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _cancel_all_tasks(loop): | 
					
						
							| 
									
										
										
										
											2018-05-28 17:54:02 -04:00
										 |  |  |     to_cancel = tasks.all_tasks(loop) | 
					
						
							| 
									
										
										
										
											2018-01-21 14:56:59 -05:00
										 |  |  |     if not to_cancel: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for task in to_cancel: | 
					
						
							|  |  |  |         task.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     loop.run_until_complete( | 
					
						
							| 
									
										
										
										
											2021-09-04 20:54:50 +03:00
										 |  |  |         tasks._gather(*to_cancel, loop=loop, return_exceptions=True)) | 
					
						
							| 
									
										
										
										
											2018-01-21 14:56:59 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for task in to_cancel: | 
					
						
							|  |  |  |         if task.cancelled(): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if task.exception() is not None: | 
					
						
							|  |  |  |             loop.call_exception_handler({ | 
					
						
							|  |  |  |                 'message': 'unhandled exception during asyncio.run() shutdown', | 
					
						
							|  |  |  |                 'exception': task.exception(), | 
					
						
							|  |  |  |                 'task': task, | 
					
						
							|  |  |  |             }) |