From dcac54871f018c35ec67ca85650313ec0ac129be Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Thu, 30 May 2024 20:54:58 +0200 Subject: [PATCH 1/2] gh-119553: Clear reader on Ctrl-C command Also, do not print extra newline on before KeyboardInterrupt. --- Lib/_pyrepl/commands.py | 1 + Lib/_pyrepl/simple_interact.py | 4 ++-- Lib/test/test_pyrepl/support.py | 4 +++- Lib/test/test_pyrepl/test_reader.py | 18 ++++++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Lib/_pyrepl/commands.py b/Lib/_pyrepl/commands.py index ed977f84baac4e..84241e0bbc99fe 100644 --- a/Lib/_pyrepl/commands.py +++ b/Lib/_pyrepl/commands.py @@ -216,6 +216,7 @@ def do(self) -> None: import signal self.reader.console.finish() + self.reader.finish() os.kill(os.getpid(), signal.SIGINT) diff --git a/Lib/_pyrepl/simple_interact.py b/Lib/_pyrepl/simple_interact.py index 11e831c1d6c5d4..5859a67dc6da43 100644 --- a/Lib/_pyrepl/simple_interact.py +++ b/Lib/_pyrepl/simple_interact.py @@ -182,8 +182,8 @@ def more_lines(unicodetext: str) -> bool: assert not more input_n += 1 except KeyboardInterrupt: - console.write("\nKeyboardInterrupt\n") + console.write("KeyboardInterrupt\n") console.resetbuffer() except MemoryError: - console.write("\nMemoryError\n") + console.write("MemoryError\n") console.resetbuffer() diff --git a/Lib/test/test_pyrepl/support.py b/Lib/test/test_pyrepl/support.py index 75539049d43c2a..c97de1e05bdf86 100644 --- a/Lib/test/test_pyrepl/support.py +++ b/Lib/test/test_pyrepl/support.py @@ -39,7 +39,7 @@ def code_to_events(code: str): def prepare_reader(console: Console, **kwargs): - config = ReadlineConfig(readline_completer=None) + config = ReadlineConfig(readline_completer=kwargs.pop("readline_completer", None)) reader = ReadlineAlikeReader(console=console, config=config) reader.more_lines = partial(more_lines, namespace=None) reader.paste_mode = True # Avoid extra indents @@ -75,6 +75,8 @@ def handle_all_events( reader.handle1() except StopIteration: pass + except KeyboardInterrupt: + pass return reader, console diff --git a/Lib/test/test_pyrepl/test_reader.py b/Lib/test/test_pyrepl/test_reader.py index 7bf7a36d8d7bb9..76398985fd4ac5 100644 --- a/Lib/test/test_pyrepl/test_reader.py +++ b/Lib/test/test_pyrepl/test_reader.py @@ -1,5 +1,6 @@ import itertools import functools +import rlcompleter from unittest import TestCase from .support import handle_all_events, handle_events_narrow_console, code_to_events, prepare_reader @@ -176,3 +177,20 @@ def test_newline_within_block_trailing_whitespace(self): ) self.assert_screen_equals(reader, expected) self.assertTrue(reader.finished) + + def test_keyboard_interrupt_clears_screen(self): + namespace = {"itertools": itertools} + code = "import itertools\nitertools." + events = itertools.chain(code_to_events(code), [ + Event(evt='key', data='\t', raw=bytearray(b'\t')), # Two tabs for completion + Event(evt='key', data='\t', raw=bytearray(b'\t')), + Event(evt='key', data='\x03', raw=bytearray(b'\x03')), # Ctrl-C + ]) + + completing_reader = functools.partial( + prepare_reader, + readline_completer=rlcompleter.Completer(namespace).complete + ) + reader, _ = handle_all_events(events, prepare_reader=completing_reader) + print(reader.screen) + self.assert_screen_equals(reader, code) From 009b0766f4117051e8f344817c8efa33ff089c3c Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Tue, 4 Jun 2024 18:33:07 +0200 Subject: [PATCH 2/2] Fix after ctrl_c command was introduced --- Lib/_pyrepl/commands.py | 2 +- Lib/_pyrepl/simple_interact.py | 4 ++-- Lib/test/test_pyrepl/test_reader.py | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/_pyrepl/commands.py b/Lib/_pyrepl/commands.py index 0201715f5df4fe..3063e156e09ac4 100644 --- a/Lib/_pyrepl/commands.py +++ b/Lib/_pyrepl/commands.py @@ -216,12 +216,12 @@ def do(self) -> None: import signal self.reader.console.finish() - self.reader.finish() os.kill(os.getpid(), signal.SIGINT) class ctrl_c(Command): def do(self) -> None: + self.reader.finish() raise KeyboardInterrupt diff --git a/Lib/_pyrepl/simple_interact.py b/Lib/_pyrepl/simple_interact.py index ad19d407c38fa0..256bbc7c6d7626 100644 --- a/Lib/_pyrepl/simple_interact.py +++ b/Lib/_pyrepl/simple_interact.py @@ -149,8 +149,8 @@ def more_lines(unicodetext: str) -> bool: assert not more input_n += 1 except KeyboardInterrupt: - console.write("KeyboardInterrupt\n") + console.write("\nKeyboardInterrupt\n") console.resetbuffer() except MemoryError: - console.write("MemoryError\n") + console.write("\nMemoryError\n") console.resetbuffer() diff --git a/Lib/test/test_pyrepl/test_reader.py b/Lib/test/test_pyrepl/test_reader.py index 45fe185b24c797..079c963d19aad5 100644 --- a/Lib/test/test_pyrepl/test_reader.py +++ b/Lib/test/test_pyrepl/test_reader.py @@ -193,8 +193,7 @@ def test_keyboard_interrupt_clears_screen(self): readline_completer=rlcompleter.Completer(namespace).complete ) reader, _ = handle_all_events(events, prepare_reader=completing_reader) - print(reader.screen) - self.assert_screen_equals(reader, code) + self.assertEqual(reader.calc_screen(), code.split("\n")) def test_prompt_length(self): # Handles simple ASCII prompt