diff --git a/Lib/_pyrepl/reader.py b/Lib/_pyrepl/reader.py index d552214f322d76..1195e13a3e70b8 100644 --- a/Lib/_pyrepl/reader.py +++ b/Lib/_pyrepl/reader.py @@ -288,7 +288,6 @@ class Reader: ps3: str = "|.. " ps4: str = R"\__ " kill_ring: list[list[str]] = field(default_factory=list) - error_prefix: str = "! " msg: str = "" arg: int | None = None finished: bool = False @@ -883,12 +882,12 @@ def debug(self, msg: str) -> None: pass def error(self, msg: str = "none") -> None: - error_prefix = self.error_prefix + msg = f"[ {msg} ]" if self.can_colorize: - t = THEME() - error_prefix = f"{t.error}{error_prefix}{t.reset}" + colors = _colorize.ANSIColors + msg = f"{colors.RED}{msg}{colors.RESET}" self.console.beep() - self.msg = error_prefix + msg + self.msg = msg self.invalidate_message() def update_screen(self) -> None: diff --git a/Lib/test/test_pyrepl/test_reader.py b/Lib/test/test_pyrepl/test_reader.py index fd9900d9a32b3d..8975677534d847 100644 --- a/Lib/test/test_pyrepl/test_reader.py +++ b/Lib/test/test_pyrepl/test_reader.py @@ -14,7 +14,7 @@ from _pyrepl.layout import LayoutMap from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig from _pyrepl.reader import Reader -from _colorize import default_theme +from _colorize import ANSIColors, default_theme overrides = {"reset": "z", "soft_keyword": "K"} @@ -467,11 +467,11 @@ def test_colorized_error_message(self): reader.handle1() - theme = default_theme.syntax self.assertEqual( reader.msg, - f"{theme.error}! {theme.reset}nothing to yank", + f"{ANSIColors.RED}[ nothing to yank ]{ANSIColors.RESET}", ) + self.assertEqual(reader.screen[-1], reader.msg) def _test_error_message( self, @@ -490,42 +490,42 @@ def _test_error_message( while not reader.msg: reader.handle1() - self.assertEqual(reader.msg, f"! {expected}") - self.assertEqual(reader.screen[-1], f"! {expected}") + self.assertEqual(reader.msg, expected) + self.assertEqual(reader.screen[-1], expected) console.beep.assert_called_once() def test_invalid_key_message(self): - self._test_error_message("\x1bo", "no command is bound to this key") + self._test_error_message("\x1bo", "[ no command is bound to this key ]") def test_unimplemented_command_message(self): self._test_error_message( "x", - "command 'missing-command' is not implemented", + "[ command 'missing-command' is not implemented ]", command="missing-command", ) def test_nothing_to_yank_message(self): - self._test_error_message("\x19", "nothing to yank") + self._test_error_message("\x19", "[ nothing to yank ]") def test_yank_pop_with_empty_kill_ring_message(self): - self._test_error_message("\x1by", "nothing to yank") + self._test_error_message("\x1by", "[ nothing to yank ]") def test_yank_pop_after_other_command_message(self): self._test_error_message( "x\x01\x0b\x1by", - "previous command was not a yank", + "[ previous command was not a yank ]", ) def test_start_of_history_message(self): - self._test_error_message("\x10", "start of history list") + self._test_error_message("\x10", "[ start of history list ]") def test_end_of_history_message(self): - self._test_error_message("\x0e", "end of history list") + self._test_error_message("\x0e", "[ end of history list ]") def test_yank_arg_at_beginning_of_history_message(self): self._test_error_message( "\x1b.\x1b.\x1b.", - "beginning of history list", + "[ beginning of history list ]", history=["one"], historyi=1, ) @@ -533,7 +533,7 @@ def test_yank_arg_at_beginning_of_history_message(self): def test_yank_arg_with_no_argument_message(self): self._test_error_message( "\x1b.", - "no such arg", + "[ no such arg ]", history=[""], historyi=1, ) @@ -541,23 +541,23 @@ def test_yank_arg_with_no_argument_message(self): def test_empty_incremental_search_backspace_message(self): self._test_error_message( "x", - "nothing to rubout", + "[ nothing to rubout ]", command="isearch-backspace", ) def test_history_search_not_found_message(self): self._test_error_message( "missingx", - "not found", + "[ not found ]", command="history-search-backward", binding="x", ) def test_incremental_search_not_found_message(self): - self._test_error_message("\x12x", "not found") + self._test_error_message("\x12x", "[ not found ]") def test_no_completion_matches_message(self): - self._test_error_message("does_not_exist\t", "no matches") + self._test_error_message("does_not_exist\t", "[ no matches ]") @force_colorized_test_class diff --git a/Misc/NEWS.d/next/Library/2026-10-20-20-00-00.gh-issue-148228.X7mQp2.rst b/Misc/NEWS.d/next/Library/2026-10-20-20-00-00.gh-issue-148228.X7mQp2.rst new file mode 100644 index 00000000000000..bd43bdcbb0801b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-20-20-00-00.gh-issue-148228.X7mQp2.rst @@ -0,0 +1,2 @@ +Display error overlays in the new interactive shell in square brackets +and in non-bold red when color is enabled. Patch by Bartosz Sławecki.