From cbb6f3a6e940179921c90f861b574146eb7c59fe Mon Sep 17 00:00:00 2001 From: Eugene Triguba Date: Tue, 21 May 2024 12:33:55 -0400 Subject: [PATCH 1/3] Fix error being thrown on quit when REPL has TERM=dumb --- Lib/_pyrepl/__main__.py | 14 +++++--------- Lib/_pyrepl/env.py | 6 ++++++ Lib/site.py | 4 ++-- Lib/test/test_repl.py | 14 ++++++++++++-- 4 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 Lib/_pyrepl/env.py diff --git a/Lib/_pyrepl/__main__.py b/Lib/_pyrepl/__main__.py index c598019e7cd4ad..c8ff596905866d 100644 --- a/Lib/_pyrepl/__main__.py +++ b/Lib/_pyrepl/__main__.py @@ -1,12 +1,10 @@ import os import sys -CAN_USE_PYREPL = sys.platform != "win32" - def interactive_console(mainmodule=None, quiet=False, pythonstartup=False): - global CAN_USE_PYREPL - if not CAN_USE_PYREPL: + from _pyrepl import env + if not env.IS_PYREPL_SUPPORTED_PLATFORM: return sys._baserepl() startup_path = os.getenv("PYTHONSTARTUP") @@ -23,7 +21,6 @@ def interactive_console(mainmodule=None, quiet=False, pythonstartup=False): if not hasattr(sys, "ps2"): sys.ps2 = "... " - run_interactive = None try: import errno if not os.isatty(sys.stdin.fileno()): @@ -32,16 +29,15 @@ def interactive_console(mainmodule=None, quiet=False, pythonstartup=False): if err := check(): raise RuntimeError(err) from .simple_interact import run_multiline_interactive_console - run_interactive = run_multiline_interactive_console + return run_multiline_interactive_console(mainmodule) 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: + env.CAN_USE_PYREPL = False return sys._baserepl() - return run_interactive(mainmodule) + if __name__ == "__main__": interactive_console() diff --git a/Lib/_pyrepl/env.py b/Lib/_pyrepl/env.py new file mode 100644 index 00000000000000..a61477e8e701ce --- /dev/null +++ b/Lib/_pyrepl/env.py @@ -0,0 +1,6 @@ +import sys + +IS_PYREPL_SUPPORTED_PLATFORM = sys.platform != "win32" + +# Note: This will be updated on REPL startup based on additional checks. +CAN_USE_PYREPL = IS_PYREPL_SUPPORTED_PLATFORM diff --git a/Lib/site.py b/Lib/site.py index 4ba078388a37b8..284087f943769f 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -523,9 +523,9 @@ def register_readline(): pass def write_history(): - from _pyrepl.__main__ import CAN_USE_PYREPL + from _pyrepl import env try: - if os.getenv("PYTHON_BASIC_REPL") or not CAN_USE_PYREPL: + if os.getenv("PYTHON_BASIC_REPL") or not env.CAN_USE_PYREPL: readline.write_history_file(history) else: _pyrepl.readline.write_history_file(history) diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index 340178366fc13a..c2e26183d35eea 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -34,8 +34,9 @@ def spawn_repl(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw): # Set TERM=vt100, for the rationale see the comments in spawn_python() of # test.support.script_helper. - env = kw.setdefault('env', dict(os.environ)) - env['TERM'] = 'vt100' + if "env" not in kw: + env = kw.setdefault('env', dict(os.environ)) + env['TERM'] = 'vt100' return subprocess.Popen(cmd_line, executable=sys.executable, text=True, @@ -198,6 +199,15 @@ def bar(x): def test_asyncio_repl_is_ok(self): assert_python_ok("-m", "asyncio") + def test_repl_with_dumb_term_exits_cleanly(self): + env = dict(os.environ) + env.update({"TERM": "dumb"}) + p = spawn_repl(env=env) + p.stdin.write("quit()\n") + output = kill_python(p) + self.assertEqual(p.returncode, 0) + self.assertNotIn("Exception", output) + self.assertNotIn("Traceback", output) class TestInteractiveModeSyntaxErrors(unittest.TestCase): From ba7b94287840c0c0fa9adbe796fda85cec659a47 Mon Sep 17 00:00:00 2001 From: Eugene Triguba Date: Tue, 21 May 2024 13:06:33 -0400 Subject: [PATCH 2/3] Add blurb --- Lib/site.py | 4 ++-- .../Library/2024-05-21-13-06-27.gh-issue-119102.E1k90T.rst | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-05-21-13-06-27.gh-issue-119102.E1k90T.rst diff --git a/Lib/site.py b/Lib/site.py index 284087f943769f..40861ac598300a 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -523,9 +523,9 @@ def register_readline(): pass def write_history(): - from _pyrepl import env + from _pyrepl.env import CAN_USE_PYREPL try: - if os.getenv("PYTHON_BASIC_REPL") or not env.CAN_USE_PYREPL: + if os.getenv("PYTHON_BASIC_REPL") or not CAN_USE_PYREPL: readline.write_history_file(history) else: _pyrepl.readline.write_history_file(history) diff --git a/Misc/NEWS.d/next/Library/2024-05-21-13-06-27.gh-issue-119102.E1k90T.rst b/Misc/NEWS.d/next/Library/2024-05-21-13-06-27.gh-issue-119102.E1k90T.rst new file mode 100644 index 00000000000000..83885ecaf6f67b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-05-21-13-06-27.gh-issue-119102.E1k90T.rst @@ -0,0 +1 @@ +Fix error being thrown on quit() in REPL when TERM is set to dumb From 54aebad84da7cbd0688392703481cfa5c1d4276d Mon Sep 17 00:00:00 2001 From: Eugene Triguba Date: Tue, 21 May 2024 13:25:16 -0400 Subject: [PATCH 3/3] fix mypy error --- Lib/_pyrepl/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_pyrepl/__main__.py b/Lib/_pyrepl/__main__.py index c8ff596905866d..86673a74af7dbf 100644 --- a/Lib/_pyrepl/__main__.py +++ b/Lib/_pyrepl/__main__.py @@ -3,7 +3,7 @@ def interactive_console(mainmodule=None, quiet=False, pythonstartup=False): - from _pyrepl import env + from . import env if not env.IS_PYREPL_SUPPORTED_PLATFORM: return sys._baserepl()