diff options
author | Daniel Hollas <daniel.hollas@bristol.ac.uk> | 2024-05-20 18:21:56 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-20 18:21:56 (GMT) |
commit | c0d81b256604a1079349d82d136db43eefcb3df1 (patch) | |
tree | 7b329473132f5c28cdbedc306314d9530431cda4 | |
parent | 7e1a130b8ff1ed8b3a5f00fe0f06d3916b852216 (diff) | |
download | cpython-c0d81b256604a1079349d82d136db43eefcb3df1.zip cpython-c0d81b256604a1079349d82d136db43eefcb3df1.tar.gz cpython-c0d81b256604a1079349d82d136db43eefcb3df1.tar.bz2 |
gh-118877: Fix AssertionError crash in pyrepl (#118936)
-rw-r--r-- | Lib/_pyrepl/commands.py | 4 | ||||
-rw-r--r-- | Lib/test/test_pyrepl.py | 25 |
2 files changed, 25 insertions, 4 deletions
diff --git a/Lib/_pyrepl/commands.py b/Lib/_pyrepl/commands.py index 456cba0..51c7afe 100644 --- a/Lib/_pyrepl/commands.py +++ b/Lib/_pyrepl/commands.py @@ -34,9 +34,7 @@ import os # types if False: - from .reader import Reader from .historical_reader import HistoricalReader - from .console import Event class Command: @@ -245,7 +243,7 @@ class up(MotionCommand): x, y = r.pos2xy() new_y = y - 1 - if new_y < 0: + if r.bol() == 0: if r.historyi > 0: r.select_item(r.historyi - 1) return diff --git a/Lib/test/test_pyrepl.py b/Lib/test/test_pyrepl.py index c8990b6..ee6ba65 100644 --- a/Lib/test/test_pyrepl.py +++ b/Lib/test/test_pyrepl.py @@ -607,6 +607,30 @@ class TestPyReplCompleter(TestCase): output = multiline_input(reader, namespace) self.assertEqual(output, "python") + def test_updown_arrow_with_completion_menu(self): + """Up arrow in the middle of unfinished tab completion when the menu is displayed + should work and trigger going back in history. Down arrow should subsequently + get us back to the incomplete command.""" + code = "import os\nos.\t\t" + namespace = {"os": os} + + events = itertools.chain( + code_to_events(code), + [ + Event(evt='key', data='up', raw=bytearray(b'\x1bOA')), + Event(evt="key", data="down", raw=bytearray(b"\x1bOB")), + ], + code_to_events("\n") + ) + reader = self.prepare_reader(events, namespace=namespace) + output = multiline_input(reader, namespace) + # This is the first line, nothing to see here + self.assertEqual(output, "import os") + # This is the second line. We pressed up and down arrows + # so we should end up where we were when we initiated tab completion. + output = multiline_input(reader, namespace) + self.assertEqual(output, "os.") + @patch("_pyrepl.curses.tigetstr", lambda x: b"") class TestUnivEventQueue(TestCase): @@ -1001,6 +1025,5 @@ class TestReader(TestCase): reader, _ = handle_all_events(events) self.assert_screen_equals(reader, "") - if __name__ == '__main__': unittest.main() |