From edd1f3c32d0c14674cba1d39ba268daecf218c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Wed, 26 Jun 2024 17:40:35 +0200 Subject: [PATCH] gh-118908: Use __main__ for the default PyREPL namespace This allows for PYTHONSTARTUP to execute in the right namespace. --- Lib/_pyrepl/__main__.py | 52 ++------------------------------ Lib/_pyrepl/main.py | 55 ++++++++++++++++++++++++++++++++++ Lib/_pyrepl/simple_interact.py | 12 +------- 3 files changed, 58 insertions(+), 61 deletions(-) create mode 100644 Lib/_pyrepl/main.py diff --git a/Lib/_pyrepl/__main__.py b/Lib/_pyrepl/__main__.py index dae4ba6e178b9a6..efb6d343cc9a7ca 100644 --- a/Lib/_pyrepl/__main__.py +++ b/Lib/_pyrepl/__main__.py @@ -1,51 +1,3 @@ -import os -import sys - -CAN_USE_PYREPL: bool -if sys.platform != "win32": - CAN_USE_PYREPL = True -else: - CAN_USE_PYREPL = sys.getwindowsversion().build >= 10586 # Windows 10 TH2 - - -def interactive_console(mainmodule=None, quiet=False, pythonstartup=False): - global CAN_USE_PYREPL - if not CAN_USE_PYREPL: - return sys._baserepl() - - startup_path = os.getenv("PYTHONSTARTUP") - if pythonstartup and startup_path: - import tokenize - with tokenize.open(startup_path) as f: - startup_code = compile(f.read(), startup_path, "exec") - exec(startup_code) - - # set sys.{ps1,ps2} just before invoking the interactive interpreter. This - # mimics what CPython does in pythonrun.c - if not hasattr(sys, "ps1"): - sys.ps1 = ">>> " - if not hasattr(sys, "ps2"): - sys.ps2 = "... " - - run_interactive = None - try: - import errno - if not os.isatty(sys.stdin.fileno()): - raise OSError(errno.ENOTTY, "tty required", "stdin") - from .simple_interact import check - if err := check(): - raise RuntimeError(err) - from .simple_interact import run_multiline_interactive_console - run_interactive = run_multiline_interactive_console - except Exception as e: - from .trace import trace - msg = f"warning: can't use pyrepl: {e}" - trace(msg) - print(msg, file=sys.stderr) - CAN_USE_PYREPL = False - if run_interactive is None: - return sys._baserepl() - return run_interactive(mainmodule) - if __name__ == "__main__": - interactive_console() + from .main import interactive_console as __pyrepl_interactive_console + __pyrepl_interactive_console() diff --git a/Lib/_pyrepl/main.py b/Lib/_pyrepl/main.py new file mode 100644 index 000000000000000..041a4009f42ed85 --- /dev/null +++ b/Lib/_pyrepl/main.py @@ -0,0 +1,55 @@ +import os +import sys + +CAN_USE_PYREPL: bool +if sys.platform != "win32": + CAN_USE_PYREPL = True +else: + CAN_USE_PYREPL = sys.getwindowsversion().build >= 10586 # Windows 10 TH2 + + +def interactive_console(mainmodule=None, quiet=False, pythonstartup=False): + global CAN_USE_PYREPL + if not CAN_USE_PYREPL: + return sys._baserepl() + + if mainmodule: + namespace = mainmodule.__dict__ + else: + import __main__ + namespace = __main__.__dict__ + namespace.pop("__pyrepl_interactive_console", None) + + startup_path = os.getenv("PYTHONSTARTUP") + if pythonstartup and startup_path: + import tokenize + with tokenize.open(startup_path) as f: + startup_code = compile(f.read(), startup_path, "exec") + exec(startup_code, namespace) + + # set sys.{ps1,ps2} just before invoking the interactive interpreter. This + # mimics what CPython does in pythonrun.c + if not hasattr(sys, "ps1"): + sys.ps1 = ">>> " + if not hasattr(sys, "ps2"): + sys.ps2 = "... " + + run_interactive = None + try: + import errno + if not os.isatty(sys.stdin.fileno()): + raise OSError(errno.ENOTTY, "tty required", "stdin") + from .simple_interact import check + if err := check(): + raise RuntimeError(err) + from .simple_interact import run_multiline_interactive_console + run_interactive = run_multiline_interactive_console + except Exception as e: + from .trace import trace + msg = f"warning: can't use pyrepl: {e}" + trace(msg) + print(msg, file=sys.stderr) + CAN_USE_PYREPL = False + if run_interactive is None: + return sys._baserepl() + run_interactive(namespace) diff --git a/Lib/_pyrepl/simple_interact.py b/Lib/_pyrepl/simple_interact.py index 2de3b38c37a9da6..bc16c1f6a23159d 100644 --- a/Lib/_pyrepl/simple_interact.py +++ b/Lib/_pyrepl/simple_interact.py @@ -80,23 +80,13 @@ def _clear_screen(): "clear": _clear_screen, } -DEFAULT_NAMESPACE: dict[str, Any] = { - '__name__': '__main__', - '__doc__': None, - '__package__': None, - '__loader__': None, - '__spec__': None, - '__annotations__': {}, - '__builtins__': builtins, -} def run_multiline_interactive_console( - mainmodule: ModuleType | None = None, + namespace: dict[str, Any], future_flags: int = 0, console: code.InteractiveConsole | None = None, ) -> None: from .readline import _setup - namespace = mainmodule.__dict__ if mainmodule else DEFAULT_NAMESPACE _setup(namespace) if console is None: