summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Hollas <daniel.hollas@bristol.ac.uk>2024-05-20 18:21:56 (GMT)
committerGitHub <noreply@github.com>2024-05-20 18:21:56 (GMT)
commitc0d81b256604a1079349d82d136db43eefcb3df1 (patch)
tree7b329473132f5c28cdbedc306314d9530431cda4
parent7e1a130b8ff1ed8b3a5f00fe0f06d3916b852216 (diff)
downloadcpython-c0d81b256604a1079349d82d136db43eefcb3df1.zip
cpython-c0d81b256604a1079349d82d136db43eefcb3df1.tar.gz
cpython-c0d81b256604a1079349d82d136db43eefcb3df1.tar.bz2
gh-118877: Fix AssertionError crash in pyrepl (#118936)
-rw-r--r--Lib/_pyrepl/commands.py4
-rw-r--r--Lib/test/test_pyrepl.py25
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()