Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-118894: Make asyncio REPL use pyrepl #119433

Merged
merged 9 commits into from
May 31, 2024
11 changes: 8 additions & 3 deletions Lib/_pyrepl/simple_interact.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def runsource(self, source, filename="<input>", symbol="single"):
the_symbol = symbol if stmt is last_stmt else "exec"
item = wrapper([stmt])
try:
code = compile(item, filename, the_symbol)
code = self.compile.compiler(item, filename, the_symbol)
except (OverflowError, ValueError):
self.showsyntaxerror(filename)
return False
Expand All @@ -108,14 +108,19 @@ def runsource(self, source, filename="<input>", symbol="single"):


def run_multiline_interactive_console(
mainmodule: ModuleType | None= None, future_flags: int = 0
mainmodule: ModuleType | None = None,
future_flags: int = 0,
console: code.InteractiveConsole | None = None,
) -> None:
import __main__
from .readline import _setup
_setup()

mainmodule = mainmodule or __main__
console = InteractiveColoredConsole(mainmodule.__dict__, filename="<stdin>")
if console is None:
console = InteractiveColoredConsole(
mainmodule.__dict__, filename="<stdin>"
)
if future_flags:
console.compile.compiler.flags |= future_flags

Expand Down
37 changes: 29 additions & 8 deletions Lib/asyncio/__main__.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import ast
import asyncio
import code
import concurrent.futures
import inspect
import os
import site
import sys
import threading
import types
import warnings

from _pyrepl.simple_interact import InteractiveColoredConsole, check
from _pyrepl.simple_interact import run_multiline_interactive_console

from . import futures


class AsyncIOInteractiveConsole(code.InteractiveConsole):
class AsyncIOInteractiveConsole(InteractiveColoredConsole):

def __init__(self, locals, loop):
super().__init__(locals)
super().__init__(locals, filename="<stdin>")
self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

self.loop = loop
Expand Down Expand Up @@ -75,12 +78,30 @@ def run(self):
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'
ambv marked this conversation as resolved.
Show resolved Hide resolved
)
exit_message = 'exiting asyncio REPL...'

console.write(banner)
if startup_path := os.getenv("PYTHONSTARTUP"):
import tokenize
with tokenize.open(startup_path) as f:
startup_code = compile(f.read(), startup_path, "exec")
exec(startup_code, console.locals)

console.interact(
banner=banner,
exitmsg='exiting asyncio REPL...')
try:
import errno
if not os.isatty(sys.stdin.fileno()):
raise OSError(errno.ENOTTY, "tty required", "stdin")
if err := check():
raise RuntimeError(err)
except Exception as e:
console.interact(banner="", exitmsg=exit_message)
else:
try:
run_multiline_interactive_console(console=console)
except BaseException:
console.showtraceback()
ambv marked this conversation as resolved.
Show resolved Hide resolved
console.write(exit_message + '\n')
finally:
warnings.filterwarnings(
'ignore',
Expand Down Expand Up @@ -126,7 +147,7 @@ def run(self):
completer = rlcompleter.Completer(console.locals)
readline.set_completer(completer.complete)

repl_thread = REPLThread()
repl_thread = REPLThread(name="Interactive thread")
repl_thread.daemon = True
repl_thread.start()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:mod:`asyncio` REPL now has the same capabilities as PyREPL.
Loading