From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Wed, 22 May 2024 01:28:24 +0000 (+0200) Subject: [3.13] gh-118877: Fix AssertionError crash in pyrepl (GH-118936) (#119363) X-Git-Tag: v3.13.0b2~159 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e9922178100e17f0264dd943ac838b2f7e8cfdab;p=thirdparty%2FPython%2Fcpython.git [3.13] gh-118877: Fix AssertionError crash in pyrepl (GH-118936) (#119363) (cherry picked from commit c0d81b256604a1079349d82d136db43eefcb3df1) Co-authored-by: Daniel Hollas --- diff --git a/Lib/_pyrepl/commands.py b/Lib/_pyrepl/commands.py index 456cba0769c9..51c7afebede5 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 c8990b699b21..ee6ba658f11e 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()