22
33__all__ = ['run' , 'forever' ]
44
5+ import inspect
56import threading
67
78from . import coroutines
89from . import events
910
1011
12+ def _isasyncgen (obj ):
13+ if hasattr (inspect , 'isasyncgen' ):
14+ return inspect .isasyncgen (obj )
15+ return False
16+
17+
1118@coroutines .coroutine
1219def forever ():
1320 """Wait until the current event loop stops running.
@@ -67,8 +74,10 @@ async def main():
6774 if not isinstance (threading .current_thread (), threading ._MainThread ):
6875 raise RuntimeError (
6976 "asyncio.run() must be called from the main thread" )
70- if not coroutines .iscoroutine (coro ):
71- raise ValueError ("a coroutine was expected, got {!r}" .format (coro ))
77+ if not coroutines .iscoroutine (coro ) and not _isasyncgen (coro ):
78+ raise ValueError (
79+ "a coroutine or an asynchronous generator was expected, "
80+ "got {!r}" .format (coro ))
7281
7382 loop = events .new_event_loop ()
7483 try :
@@ -77,15 +86,26 @@ async def main():
7786 if debug :
7887 loop .set_debug (True )
7988
80- task = loop .create_task (coro )
81- task .add_done_callback (lambda task : loop .stop ())
89+ if _isasyncgen (coro ):
90+ result = None
91+ loop .run_until_complete (coro .asend (None ))
92+ try :
93+ loop .run_forever ()
94+ except BaseException as ex :
95+ try :
96+ loop .run_until_complete (coro .athrow (ex ))
97+ except StopAsyncIteration as ex :
98+ if ex .args :
99+ result = ex .args [0 ]
100+ else :
101+ try :
102+ loop .run_until_complete (coro .asend (None ))
103+ except StopAsyncIteration as ex :
104+ if ex .args :
105+ result = ex .args [0 ]
82106
83- try :
84- loop .run_forever ()
85- except BaseException as ex :
86- result = loop .run_until_complete (task )
87107 else :
88- result = task . result ( )
108+ result = loop . run_until_complete ( coro )
89109
90110 try :
91111 # `shutdown_asyncgens` was added in Python 3.6; not all
0 commit comments