mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	
		
			
	
	
		
			126 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			126 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | 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 |