From 3ade6789a04271c92bb3450cf2092a7578b447de Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Sat, 2 May 2026 18:35:28 -0700 Subject: [PATCH 1/4] Generator consistent colors for pdb commands --- Lib/pdb.py | 21 +++++++++++++++++++++ Lib/test/test_pdb.py | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/Lib/pdb.py b/Lib/pdb.py index 4dd974b375c259..5b3fec0773812f 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -402,6 +402,7 @@ def __init__(self, pdb_instance, stdin, stdout, prompt): completer_delims=frozenset(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?') ) ) + self.readline_wrapper.get_reader().gen_colors = self.gen_colors def readline(self): @@ -463,6 +464,26 @@ def complete(self, text, state): except IndexError: return None + def gen_colors(self, buffer): + from _pyrepl.utils import ColorSpan, Span + + if not buffer.strip(): + return + + leading_spaces = len(buffer) - len(buffer.lstrip()) + leading_text = buffer.split()[0] + if hasattr(self.pdb_instance, 'do_' + leading_text): + yield ColorSpan( + Span(leading_spaces, leading_spaces + len(leading_text) - 1), + "soft_keyword" + ) + redact_length = leading_spaces + len(leading_text) + else: + redact_length = 0 + + buffer = ' ' * redact_length + buffer[redact_length:] + yield from _pyrepl.utils.gen_colors(buffer) + class Pdb(bdb.Bdb, cmd.Cmd): _previous_sigint_handler = None diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index db90019975521e..be40effa3ce426 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4981,6 +4981,29 @@ def test_stack_entry(self): p.set_trace(commands=['w', 'c']) self.assertIn("\x1b", output.getvalue()) + def test_gen_colors(self): + p = pdb.Pdb() + gen_colors = p.pyrepl_input.gen_colors + + test_cases = [ + ("longlist", [((0, 7), "soft_keyword")]), + ("!longlist", [((0, 0), "op")]), + ("list", [((0, 3), "soft_keyword")]), + ("list(", [((0, 3), "builtin"), ((4, 4), "op")]), + ("a = 1", [ + ((0, 0), "soft_keyword"), + ((2, 2), "op"), + ((4, 4), "number"), + ]) + ] + + for buffer, expected in test_cases: + print(list(gen_colors(buffer))) + for color_span, ((start, end), tag) in zip(gen_colors(buffer), expected, strict=True): + self.assertEqual(color_span.span.start, start) + self.assertEqual(color_span.span.end, end) + self.assertEqual(color_span.tag, tag) + @support.force_not_colorized_test_class @support.requires_subprocess() From 544f4971217397c019e4ce85801caf0fe52b89df Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Sat, 2 May 2026 18:38:50 -0700 Subject: [PATCH 2/4] Move buffer change inside if --- Lib/pdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/pdb.py b/Lib/pdb.py index 5b3fec0773812f..76b7d1d50b5206 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -477,11 +477,11 @@ def gen_colors(self, buffer): Span(leading_spaces, leading_spaces + len(leading_text) - 1), "soft_keyword" ) + # Redact the command text with spaces so there will be no duplicated + # color span generated for it later. redact_length = leading_spaces + len(leading_text) - else: - redact_length = 0 + buffer = ' ' * redact_length + buffer[redact_length:] - buffer = ' ' * redact_length + buffer[redact_length:] yield from _pyrepl.utils.gen_colors(buffer) From 7d89870d70bc1f03757fdf7fcb9c6bdf4a65bbd4 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 01:50:00 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2026-05-03-01-49-57.gh-issue-145378.rtyAWM.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-05-03-01-49-57.gh-issue-145378.rtyAWM.rst diff --git a/Misc/NEWS.d/next/Library/2026-05-03-01-49-57.gh-issue-145378.rtyAWM.rst b/Misc/NEWS.d/next/Library/2026-05-03-01-49-57.gh-issue-145378.rtyAWM.rst new file mode 100644 index 00000000000000..416ad4b1e2072d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-03-01-49-57.gh-issue-145378.rtyAWM.rst @@ -0,0 +1 @@ +Generate consistent colors for :mod:`pdb` commands in :mod:`pdb` REPL. From 9b5aa70be11a85047ef4a85473a521a943e2b065 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Sat, 2 May 2026 20:47:42 -0700 Subject: [PATCH 4/4] Fix test --- Lib/test/test_pdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index be40effa3ce426..8b6ccfbf051e6e 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4981,6 +4981,7 @@ def test_stack_entry(self): p.set_trace(commands=['w', 'c']) self.assertIn("\x1b", output.getvalue()) + @unittest.skipIf(not pdb._pyrepl_available(), "pyrepl is not available") def test_gen_colors(self): p = pdb.Pdb() gen_colors = p.pyrepl_input.gen_colors @@ -4998,7 +4999,6 @@ def test_gen_colors(self): ] for buffer, expected in test_cases: - print(list(gen_colors(buffer))) for color_span, ((start, end), tag) in zip(gen_colors(buffer), expected, strict=True): self.assertEqual(color_span.span.start, start) self.assertEqual(color_span.span.end, end)