From d4d1562cd64b230a5f0b6469fa396a10ca8ea004 Mon Sep 17 00:00:00 2001 From: lazerg Date: Sat, 17 Oct 2026 13:49:52 +0500 Subject: [PATCH] [3.14] gh-159617: Fix _pyrepl dropping the end of long wrapped lines --- Lib/_pyrepl/reader.py | 6 +++++- Lib/test/test_pyrepl/test_reader.py | 5 +++++ .../Library/2026-10-17-08-49-47.gh-issue-159617.tWKOER.rst | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-17-08-49-47.gh-issue-159617.tWKOER.rst diff --git a/Lib/_pyrepl/reader.py b/Lib/_pyrepl/reader.py index f0116e742d2398e..cfe1be7984c0c67 100644 --- a/Lib/_pyrepl/reader.py +++ b/Lib/_pyrepl/reader.py @@ -353,7 +353,7 @@ def calc_screen(self) -> list[str]: else: pre = prompt prelen = prompt_len - for wrap in range(wrapcount + 1): + while True: index_to_wrap_before = 0 column = 0 for char_width in char_widths: @@ -361,6 +361,8 @@ def calc_screen(self) -> list[str]: break index_to_wrap_before += 1 column += char_width + if index_to_wrap_before == 0 and not prelen: + index_to_wrap_before = 1 # force progress if len(chars) > index_to_wrap_before: offset += index_to_wrap_before post = "\\" @@ -378,6 +380,8 @@ def calc_screen(self) -> list[str]: char_widths = char_widths[index_to_wrap_before:] pre = "" prelen = 0 + if not post: + break self.screeninfo = screeninfo self.cxy = self.pos2xy() if self.msg: diff --git a/Lib/test/test_pyrepl/test_reader.py b/Lib/test/test_pyrepl/test_reader.py index fbf557115f8a254..db4e62d380e3b1c 100644 --- a/Lib/test/test_pyrepl/test_reader.py +++ b/Lib/test/test_pyrepl/test_reader.py @@ -35,6 +35,11 @@ def test_calc_screen_wrap_three_lines(self): reader, _ = handle_events_narrow_console(events) self.assert_screen_equal(reader, f"{9*"a"}\\\n{9*"a"}\\\naa") + def test_calc_screen_wrap_three_lines_last_char(self): + events = code_to_events(19 * "a") + reader, _ = handle_events_narrow_console(events) + self.assert_screen_equal(reader, f"{9*"a"}\\\n{9*"a"}\\\na") + def test_calc_screen_prompt_handling(self): def prepare_reader_keep_prompts(*args, **kwargs): reader = prepare_reader(*args, **kwargs) diff --git a/Misc/NEWS.d/next/Library/2026-10-17-08-49-47.gh-issue-159617.tWKOER.rst b/Misc/NEWS.d/next/Library/2026-10-17-08-49-47.gh-issue-159617.tWKOER.rst new file mode 100644 index 000000000000000..61a79678ca0bde0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-17-08-49-47.gh-issue-159617.tWKOER.rst @@ -0,0 +1,3 @@ +Fix the :term:`REPL` dropping the last characters of a long line that wraps +across several rows, which could raise :exc:`IndexError` when moving the +cursor with the arrow keys.