mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
Merge 8e258ef1e9 into 7099af8f5e
This commit is contained in:
commit
0f1460b374
2 changed files with 65 additions and 124 deletions
|
|
@ -2,21 +2,17 @@
|
||||||
import ast
|
import ast
|
||||||
import asyncio
|
import asyncio
|
||||||
import asyncio.tools
|
import asyncio.tools
|
||||||
import concurrent.futures
|
|
||||||
import contextvars
|
import contextvars
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
import site
|
import site
|
||||||
import sys
|
import sys
|
||||||
import threading
|
|
||||||
import types
|
import types
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from _colorize import get_theme
|
from _colorize import get_theme
|
||||||
from _pyrepl.console import InteractiveColoredConsole
|
from _pyrepl.console import InteractiveColoredConsole
|
||||||
|
|
||||||
from . import futures
|
|
||||||
|
|
||||||
|
|
||||||
class AsyncIOInteractiveConsole(InteractiveColoredConsole):
|
class AsyncIOInteractiveConsole(InteractiveColoredConsole):
|
||||||
|
|
||||||
|
|
@ -29,60 +25,27 @@ def __init__(self, locals, loop):
|
||||||
|
|
||||||
def runcode(self, code):
|
def runcode(self, code):
|
||||||
global return_code
|
global return_code
|
||||||
future = concurrent.futures.Future()
|
|
||||||
|
|
||||||
def callback():
|
|
||||||
global return_code
|
|
||||||
global repl_future
|
|
||||||
global keyboard_interrupted
|
|
||||||
|
|
||||||
repl_future = None
|
|
||||||
keyboard_interrupted = False
|
|
||||||
|
|
||||||
|
async def callback():
|
||||||
func = types.FunctionType(code, self.locals)
|
func = types.FunctionType(code, self.locals)
|
||||||
try:
|
|
||||||
coro = func()
|
coro = func()
|
||||||
except SystemExit as se:
|
|
||||||
return_code = se.code
|
|
||||||
self.loop.stop()
|
|
||||||
return
|
|
||||||
except KeyboardInterrupt as ex:
|
|
||||||
keyboard_interrupted = True
|
|
||||||
future.set_exception(ex)
|
|
||||||
return
|
|
||||||
except BaseException as ex:
|
|
||||||
future.set_exception(ex)
|
|
||||||
return
|
|
||||||
|
|
||||||
if not inspect.iscoroutine(coro):
|
if not inspect.iscoroutine(coro):
|
||||||
future.set_result(coro)
|
return coro
|
||||||
return
|
return await coro
|
||||||
|
|
||||||
|
|
||||||
|
task = self.loop.create_task(callback(), context=self.context)
|
||||||
try:
|
try:
|
||||||
repl_future = self.loop.create_task(coro, context=self.context)
|
return self.loop.run_until_complete(task)
|
||||||
futures._chain_future(repl_future, future)
|
except SystemExit:
|
||||||
except BaseException as exc:
|
raise
|
||||||
future.set_exception(exc)
|
|
||||||
|
|
||||||
self.loop.call_soon_threadsafe(callback, context=self.context)
|
|
||||||
|
|
||||||
try:
|
|
||||||
return future.result()
|
|
||||||
except SystemExit as se:
|
|
||||||
return_code = se.code
|
|
||||||
self.loop.stop()
|
|
||||||
return
|
|
||||||
except BaseException:
|
except BaseException:
|
||||||
if keyboard_interrupted:
|
|
||||||
if not CAN_USE_PYREPL:
|
|
||||||
self.write("\nKeyboardInterrupt\n")
|
|
||||||
else:
|
|
||||||
self.showtraceback()
|
self.showtraceback()
|
||||||
return self.STATEMENT_FAILED
|
return self.STATEMENT_FAILED
|
||||||
|
|
||||||
class REPLThread(threading.Thread):
|
|
||||||
|
|
||||||
def run(self):
|
def interact():
|
||||||
global return_code
|
global return_code
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -119,16 +82,19 @@ def run(self):
|
||||||
try:
|
try:
|
||||||
sys.ps1 = ps1
|
sys.ps1 = ps1
|
||||||
run_multiline_interactive_console(console)
|
run_multiline_interactive_console(console)
|
||||||
except SystemExit:
|
except SystemExit as se:
|
||||||
# expected via the `exit` and `quit` commands
|
# expected via the `exit` and `quit` commands
|
||||||
pass
|
return_code = se.code
|
||||||
except BaseException:
|
except BaseException:
|
||||||
# unexpected issue
|
# unexpected issue
|
||||||
console.showtraceback()
|
console.showtraceback()
|
||||||
console.write("Internal error, ")
|
console.write("Internal error, ")
|
||||||
return_code = 1
|
return_code = 1
|
||||||
else:
|
else:
|
||||||
|
try:
|
||||||
console.interact(banner="", exitmsg="")
|
console.interact(banner="", exitmsg="")
|
||||||
|
except SystemExit as se:
|
||||||
|
return_code = se.code
|
||||||
finally:
|
finally:
|
||||||
warnings.filterwarnings(
|
warnings.filterwarnings(
|
||||||
'ignore',
|
'ignore',
|
||||||
|
|
@ -137,15 +103,6 @@ def run(self):
|
||||||
|
|
||||||
loop.call_soon_threadsafe(loop.stop)
|
loop.call_soon_threadsafe(loop.stop)
|
||||||
|
|
||||||
def interrupt(self) -> None:
|
|
||||||
if not CAN_USE_PYREPL:
|
|
||||||
return
|
|
||||||
|
|
||||||
from _pyrepl.simple_interact import _get_reader
|
|
||||||
r = _get_reader()
|
|
||||||
if r.threading_hook is not None:
|
|
||||||
r.threading_hook.add("") # type: ignore
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
|
|
@ -198,9 +155,6 @@ def interrupt(self) -> None:
|
||||||
|
|
||||||
console = AsyncIOInteractiveConsole(repl_locals, loop)
|
console = AsyncIOInteractiveConsole(repl_locals, loop)
|
||||||
|
|
||||||
repl_future = None
|
|
||||||
keyboard_interrupted = False
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import readline # NoQA
|
import readline # NoQA
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
@ -223,21 +177,6 @@ def interrupt(self) -> None:
|
||||||
completer = rlcompleter.Completer(console.locals)
|
completer = rlcompleter.Completer(console.locals)
|
||||||
readline.set_completer(completer.complete)
|
readline.set_completer(completer.complete)
|
||||||
|
|
||||||
repl_thread = REPLThread(name="Interactive thread")
|
interact()
|
||||||
repl_thread.daemon = True
|
|
||||||
repl_thread.start()
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
loop.run_forever()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
keyboard_interrupted = True
|
|
||||||
if repl_future and not repl_future.done():
|
|
||||||
repl_future.cancel()
|
|
||||||
repl_thread.interrupt()
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
console.write('exiting asyncio REPL...\n')
|
console.write('exiting asyncio REPL...\n')
|
||||||
sys.exit(return_code)
|
sys.exit(return_code)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Refactor and simplify the asyncio REPL by removing the threading and future handling.
|
||||||
|
This fixes an issue on MacOS that the readline module will be broken after pressing Ctrl+C.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue