From 4eb8f43dc4c989f6388086cd49f1d6b1b06226e1 Mon Sep 17 00:00:00 2001 From: Tan Long Date: Fri, 9 May 2025 02:56:00 +0800 Subject: [PATCH 1/4] Fix pdb multiline auto-indent not work with comments --- Lib/pdb.py | 23 ++++++++++++++++++++++- Lib/test/test_pdb.py | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Lib/pdb.py b/Lib/pdb.py index f89d104fcddb9a..f9a034a34be167 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -762,9 +762,30 @@ def input_auto_indent(): # If the last line is empty, we don't need to indent return + in_string: list[str] = [] + last_char = None last_line = last_line.rstrip('\r\n') indent = len(last_line) - len(last_line.lstrip()) - if last_line.endswith(":"): + + i = -1 + while i < len(last_line) - 1: + i += 1 + char = last_line[i] + if char == "#": + if in_string: + last_char = char # hashtag in string, not comment + else: + break # ignore from comment start to line end + elif char not in " \t" and not in_string: + last_char = char + + if char in "\"'" and (i == 0 or last_line[i - 1] != "\\"): + if in_string and in_string[-1] == char: + in_string.pop() + else: + in_string.append(char) + + if last_char == ":": indent += 4 readline.insert_text(' ' * indent) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 68c2b508fa64dc..00c35dd0f6614e 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4870,6 +4870,22 @@ def test_multiline_auto_indent(self): self.assertIn(b'42', output) + # can ignore comment to locate trailing colon + input = b"def f(s): # comment\n" + # can distinguish hashtag from comment + input += b"if s == '#':\n" + input += b"return 's == ' + '#'\n" + # can ignore all comments, not just from the rightmost '#' to end + input += b"\x08\x08\x08\x08else: ##\n" + input += b"return 's != ' + '#'\n" + input += b"\n" + input += b"f('#')\n" + input += b"c\n" + + output = run_pty(script, input) + + self.assertIn(b's == #', output) + def test_multiline_completion(self): script = textwrap.dedent(""" import pdb; pdb.Pdb().set_trace() From c86fa0032458c2f927613f7436689420c04392a7 Mon Sep 17 00:00:00 2001 From: Tan Long Date: Fri, 9 May 2025 03:00:48 +0800 Subject: [PATCH 2/4] Add news entry --- .../next/Library/2025-05-09-03-00-41.gh-issue-133698.xeJehW.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-05-09-03-00-41.gh-issue-133698.xeJehW.rst diff --git a/Misc/NEWS.d/next/Library/2025-05-09-03-00-41.gh-issue-133698.xeJehW.rst b/Misc/NEWS.d/next/Library/2025-05-09-03-00-41.gh-issue-133698.xeJehW.rst new file mode 100644 index 00000000000000..42a3cc1cd566eb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-09-03-00-41.gh-issue-133698.xeJehW.rst @@ -0,0 +1 @@ +Fix :mod:`pdb` multiline auto-indent not work with comments. From 5bb284234d9d08499ad56de07fa50023c64bae40 Mon Sep 17 00:00:00 2001 From: Tan Long Date: Fri, 9 May 2025 03:07:03 +0800 Subject: [PATCH 3/4] Add comments for `in_string` --- Lib/pdb.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/pdb.py b/Lib/pdb.py index f9a034a34be167..68fc5b8d771716 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -762,6 +762,11 @@ def input_auto_indent(): # If the last line is empty, we don't need to indent return + # A stack to keep track of string delimiters (quotes). Push a + # quote when entering a string, and pop it when the string + # ends. When the stack is empty, we're not inside a string. If + # encounter a '#' while not inside a string, it's a comment + # start; otherwise, it's just a '#' character within a string. in_string: list[str] = [] last_char = None last_line = last_line.rstrip('\r\n') From b2dc6f4573e2b3b631c1c8c6ad7a3b722b04b48c Mon Sep 17 00:00:00 2001 From: Tan Long Date: Fri, 9 May 2025 03:12:15 +0800 Subject: [PATCH 4/4] Replace while-loop with enumeration --- Lib/pdb.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Lib/pdb.py b/Lib/pdb.py index 68fc5b8d771716..cbe7b30b52fd22 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -772,10 +772,7 @@ def input_auto_indent(): last_line = last_line.rstrip('\r\n') indent = len(last_line) - len(last_line.lstrip()) - i = -1 - while i < len(last_line) - 1: - i += 1 - char = last_line[i] + for i, char in enumerate(last_line): if char == "#": if in_string: last_char = char # hashtag in string, not comment