--- /dev/null
+import ast
+import asyncio
+import code
+import concurrent.futures
+import inspect
+import sys
+import threading
+import types
+import warnings
+
+from . import futures
+
+
+class AsyncIOInteractiveConsole(code.InteractiveConsole):
+
+ def __init__(self, locals, loop):
+ super().__init__(locals)
+ self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
+
+ self.loop = loop
+
+ def runcode(self, code):
+ future = concurrent.futures.Future()
+
+ def callback():
+ global repl_future
+ global repl_future_interrupted
+
+ repl_future = None
+ repl_future_interrupted = False
+
+ func = types.FunctionType(code, self.locals)
+ try:
+ coro = func()
+ except SystemExit:
+ raise
+ except KeyboardInterrupt as ex:
+ repl_future_interrupted = True
+ future.set_exception(ex)
+ return
+ except BaseException as ex:
+ future.set_exception(ex)
+ return
+
+ if not inspect.iscoroutine(coro):
+ future.set_result(coro)
+ return
+
+ try:
+ repl_future = self.loop.create_task(coro)
+ futures._chain_future(repl_future, future)
+ except BaseException as exc:
+ future.set_exception(exc)
+
+ loop.call_soon_threadsafe(callback)
+
+ try:
+ return future.result()
+ except SystemExit:
+ raise
+ except BaseException:
+ if repl_future_interrupted:
+ self.write("\nKeyboardInterrupt\n")
+ else:
+ self.showtraceback()
+
+
+class REPLThread(threading.Thread):
+
+ def run(self):
+ try:
+ banner = (
+ f'asyncio REPL {sys.version} on {sys.platform}\n'
+ f'Use "await" directly instead of "asyncio.run()".\n'
+ f'Type "help", "copyright", "credits" or "license" '
+ f'for more information.\n'
+ f'{getattr(sys, "ps1", ">>> ")}import asyncio'
+ )
+
+ console.interact(
+ banner=banner,
+ exitmsg='exiting asyncio REPL...')
+ finally:
+ warnings.filterwarnings(
+ 'ignore',
+ message=r'^coroutine .* was never awaited$',
+ category=RuntimeWarning)
+
+ loop.call_soon_threadsafe(loop.stop)
+
+
+if __name__ == '__main__':
+ loop = asyncio.new_event_loop()
+ asyncio.set_event_loop(loop)
+
+ repl_locals = {'asyncio': asyncio}
+ for key in {'__name__', '__package__',
+ '__loader__', '__spec__',
+ '__builtins__', '__file__'}:
+ repl_locals[key] = locals()[key]
+
+ console = AsyncIOInteractiveConsole(repl_locals, loop)
+
+ repl_future = None
+ repl_future_interrupted = False
+
+ try:
+ import readline # NoQA
+ except ImportError:
+ pass
+
+ repl_thread = REPLThread()
+ repl_thread.daemon = True
+ repl_thread.start()
+
+ while True:
+ try:
+ loop.run_forever()
+ except KeyboardInterrupt:
+ if repl_future and not repl_future.done():
+ repl_future.cancel()
+ repl_future_interrupted = True
+ continue
+ else:
+ break