diff --git a/Lib/_pyrepl/commands.py b/Lib/_pyrepl/commands.py index 2ef5dada9d9e58..e94e8c25d379c1 100644 --- a/Lib/_pyrepl/commands.py +++ b/Lib/_pyrepl/commands.py @@ -221,6 +221,7 @@ def do(self) -> None: class ctrl_c(Command): def do(self) -> None: + self.reader.finish() raise KeyboardInterrupt diff --git a/Lib/test/test_pyrepl/support.py b/Lib/test/test_pyrepl/support.py index e807b5f3404550..70e12286f7d781 100644 --- a/Lib/test/test_pyrepl/support.py +++ b/Lib/test/test_pyrepl/support.py @@ -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 d02815bfa11d74..079c963d19aad5 100644 --- a/Lib/test/test_pyrepl/test_reader.py +++ b/Lib/test/test_pyrepl/test_reader.py @@ -179,6 +179,22 @@ 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) + self.assertEqual(reader.calc_screen(), code.split("\n")) + def test_prompt_length(self): # Handles simple ASCII prompt ps1 = ">>> "