Skip to content

Commit 4646a49

Browse files
committed
fix: default REPL where prompts containing newlines would be dup
Signed-off-by: yihong0618 <[email protected]>
1 parent 89b5571 commit 4646a49

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

Lib/_pyrepl/reader.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,13 @@ def calc_screen(self) -> list[str]:
297297
if self.last_refresh_cache.valid(self):
298298
offset, num_common_lines = self.last_refresh_cache.get_cached_location(self)
299299

300-
screen = self.last_refresh_cache.screen
300+
screen = self.last_refresh_cache.screen.copy()
301301
del screen[num_common_lines:]
302302

303-
screeninfo = self.last_refresh_cache.screeninfo
303+
screeninfo = self.last_refresh_cache.screeninfo.copy()
304304
del screeninfo[num_common_lines:]
305305

306-
last_refresh_line_end_offsets = self.last_refresh_cache.line_end_offsets
306+
last_refresh_line_end_offsets = self.last_refresh_cache.line_end_offsets.copy()
307307
del last_refresh_line_end_offsets[num_common_lines:]
308308

309309
pos = self.pos

Lib/test/test_pyrepl/test_reader.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,33 @@ def test_setpos_from_xy_for_non_printing_char(self):
358358
reader.setpos_from_xy(8, 0)
359359
self.assertEqual(reader.pos, 7)
360360

361+
def test_prompt_with_newline_no_duplicate(self):
362+
# gh-127068: prompts with newlines should not duplicate
363+
# The bug is that screen = cache.screen creates a reference, not a copy,
364+
from unittest.mock import MagicMock
365+
366+
console = MagicMock()
367+
console.height = 100
368+
console.width = 80
369+
370+
reader = prepare_reader(console)
371+
372+
screen = reader.calc_screen()
373+
reader.last_refresh_cache.update_cache(reader, screen, reader.screeninfo)
374+
375+
cache_screen_before = reader.last_refresh_cache.screen
376+
original_cache_content = cache_screen_before.copy()
377+
378+
reader.insert("h")
379+
screen = reader.calc_screen()
380+
381+
self.assertEqual(
382+
cache_screen_before, original_cache_content,
383+
f"Cache was modified during calc_screen! "
384+
f"Original: {original_cache_content}, Now: {cache_screen_before}"
385+
)
386+
387+
361388
@force_colorized_test_class
362389
class TestReaderInColor(ScreenEqualMixin, TestCase):
363390
def test_syntax_highlighting_basic(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an issue in default REPL where prompts containing newlines would be duplicated
2+
on each keypress.

0 commit comments

Comments
 (0)