]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-118877: Fix AssertionError crash in pyrepl (#118936)
authorDaniel Hollas <daniel.hollas@bristol.ac.uk>
Mon, 20 May 2024 18:21:56 +0000 (19:21 +0100)
committerGitHub <noreply@github.com>
Mon, 20 May 2024 18:21:56 +0000 (20:21 +0200)
Lib/_pyrepl/commands.py
Lib/test/test_pyrepl.py

index 456cba0769c952e949c5bfc909ca47e0f5660f50..51c7afebede5a87eaeadbe09438827572be89129 100644 (file)
@@ -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
index c8990b699b214cb1b61fca2045be4955b97d30ba..ee6ba658f11e39456860a7ed7ea93a7f22e75c53 100644 (file)
@@ -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()