https://github.com/python/cpython/commit/602fcf97df1665538d4e9841f9dc6bc33e38bece
commit: 602fcf97df1665538d4e9841f9dc6bc33e38bece
branch: main
author: Matt Wozniski <[email protected]>
committer: pablogsal <[email protected]>
date: 2024-08-25T22:54:06Z
summary:

gh-123177: Fix prompt for wrapped lines in pyrepl (#123324)

When display lines above the cursor come from the cache, the first line
to not come from the cache may be a wrapped line, starting half way
through a logical line in the buffer. Detect and handle this case to
avoid accidentally drawing a stray prompt in the middle of a logical
line.

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2024-08-25-18-27-49.gh-issue-123177.yLuyqE.rst
M Lib/_pyrepl/reader.py
M Lib/test/test_pyrepl/test_reader.py

diff --git a/Lib/_pyrepl/reader.py b/Lib/_pyrepl/reader.py
index 13b1f3eb9d118a..aa3f5fd283eb7d 100644
--- a/Lib/_pyrepl/reader.py
+++ b/Lib/_pyrepl/reader.py
@@ -345,7 +345,10 @@ def calc_screen(self) -> list[str]:
         pos = self.pos
         pos -= offset
 
+        prompt_from_cache = (offset and self.buffer[offset - 1] != "\n")
+
         lines = "".join(self.buffer[offset:]).split("\n")
+
         cursor_found = False
         lines_beyond_cursor = 0
         for ln, line in enumerate(lines, num_common_lines):
@@ -359,7 +362,12 @@ def calc_screen(self) -> list[str]:
                     # No need to keep formatting lines.
                     # The console can't show them.
                     break
-            prompt = self.get_prompt(ln, ll >= pos >= 0)
+            if prompt_from_cache:
+                # Only the first line's prompt can come from the cache
+                prompt_from_cache = False
+                prompt = ""
+            else:
+                prompt = self.get_prompt(ln, ll >= pos >= 0)
             while "\n" in prompt:
                 pre_prompt, _, prompt = prompt.partition("\n")
                 last_refresh_line_end_offsets.append(offset)
diff --git a/Lib/test/test_pyrepl/test_reader.py 
b/Lib/test/test_pyrepl/test_reader.py
index e82c3ca0bb5cc2..6c72a1d39c55df 100644
--- a/Lib/test/test_pyrepl/test_reader.py
+++ b/Lib/test/test_pyrepl/test_reader.py
@@ -30,6 +30,37 @@ def test_calc_screen_wrap_three_lines(self):
         reader, _ = handle_events_narrow_console(events)
         self.assert_screen_equals(reader, f"{9*"a"}\\\n{9*"a"}\\\naa")
 
+    def test_calc_screen_prompt_handling(self):
+        def prepare_reader_keep_prompts(*args, **kwargs):
+            reader = prepare_reader(*args, **kwargs)
+            del reader.get_prompt
+            reader.ps1 = ">>> "
+            reader.ps2 = ">>> "
+            reader.ps3 = "... "
+            reader.ps4 = ""
+            reader.can_colorize = False
+            reader.paste_mode = False
+            return reader
+
+        events = code_to_events("if some_condition:\nsome_function()")
+        reader, _ = handle_events_narrow_console(
+            events,
+            prepare_reader=prepare_reader_keep_prompts,
+        )
+        # fmt: off
+        self.assert_screen_equals(
+            reader,
+            (
+            ">>> if so\\\n"
+            "me_condit\\\n"
+            "ion:\n"
+            "...     s\\\n"
+            "ome_funct\\\n"
+            "ion()"
+            )
+        )
+        # fmt: on
+
     def test_calc_screen_wrap_three_lines_mixed_character(self):
         # fmt: off
         code = (
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2024-08-25-18-27-49.gh-issue-123177.yLuyqE.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2024-08-25-18-27-49.gh-issue-123177.yLuyqE.rst
new file mode 100644
index 00000000000000..1f1791d9a6cf50
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2024-08-25-18-27-49.gh-issue-123177.yLuyqE.rst
@@ -0,0 +1,2 @@
+Fix a bug causing stray prompts to appear in the middle of wrapped lines in
+the new REPL.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to