Skip to content

Commit b6769e9

Browse files
authoredMar 4, 2025··
gh-125377: Improve tab indentation for pdb multi-line input (#130471)
1 parent c989e74 commit b6769e9

File tree

4 files changed

+49
-3
lines changed

4 files changed

+49
-3
lines changed
 

‎Doc/whatsnew/3.14.rst

+4
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,10 @@ pdb
785785
(if any).
786786
(Contributed by Tian Gao in :gh:`130493`.)
787787

788+
* ``<tab>`` at the beginning of the line in :mod:`pdb` multi-line input will
789+
fill in a 4-space indentation now, instead of inserting a ``\t`` character.
790+
(Contributed by Tian Gao in :gh:`130471`.)
791+
788792

789793
pickle
790794
------

‎Lib/pdb.py

+18-3
Original file line numberDiff line numberDiff line change
@@ -652,10 +652,10 @@ def displayhook(self, obj):
652652
self.message(repr(obj))
653653

654654
@contextmanager
655-
def _disable_command_completion(self):
655+
def _enable_multiline_completion(self):
656656
completenames = self.completenames
657657
try:
658-
self.completenames = self.completedefault
658+
self.completenames = self.complete_multiline_names
659659
yield
660660
finally:
661661
self.completenames = completenames
@@ -753,7 +753,7 @@ def default(self, line):
753753
buffer = line
754754
if (code := codeop.compile_command(line + '\n', '<stdin>', 'single')) is None:
755755
# Multi-line mode
756-
with self._disable_command_completion():
756+
with self._enable_multiline_completion():
757757
buffer = line
758758
continue_prompt = "... "
759759
while (code := codeop.compile_command(buffer, '<stdin>', 'single')) is None:
@@ -996,6 +996,21 @@ def _complete_expression(self, text, line, begidx, endidx):
996996
# Complete a simple name.
997997
return [n for n in ns.keys() if n.startswith(text)]
998998

999+
def _complete_indentation(self, text, line, begidx, endidx):
1000+
try:
1001+
import readline
1002+
except ImportError:
1003+
return []
1004+
# Fill in spaces to form a 4-space indent
1005+
return [' ' * (4 - readline.get_begidx() % 4)]
1006+
1007+
def complete_multiline_names(self, text, line, begidx, endidx):
1008+
# If text is space-only, the user entered <tab> before any text.
1009+
# That normally means they want to indent the current line.
1010+
if not text.strip():
1011+
return self._complete_indentation(text, line, begidx, endidx)
1012+
return self.completedefault(text, line, begidx, endidx)
1013+
9991014
def completedefault(self, text, line, begidx, endidx):
10001015
if text.startswith("$"):
10011016
# Complete convenience variables

‎Lib/test/test_pdb.py

+26
Original file line numberDiff line numberDiff line change
@@ -4513,6 +4513,32 @@ def test_multiline_completion(self):
45134513

45144514
self.assertIn(b'42', output)
45154515

4516+
def test_multiline_indent_completion(self):
4517+
script = textwrap.dedent("""
4518+
import pdb; pdb.Pdb().set_trace()
4519+
""")
4520+
4521+
# \t should always complete a 4-space indent
4522+
# This piece of code will raise an IndentationError or a SyntaxError
4523+
# if the completion is not working as expected
4524+
input = textwrap.dedent("""\
4525+
def func():
4526+
\ta = 1
4527+
\ta += 1
4528+
\ta += 1
4529+
\tif a > 0:
4530+
a += 1
4531+
\t\treturn a
4532+
4533+
func()
4534+
c
4535+
""").encode()
4536+
4537+
output = run_pty(script, input)
4538+
4539+
self.assertIn(b'4', output)
4540+
self.assertNotIn(b'Error', output)
4541+
45164542

45174543
def load_tests(loader, tests, pattern):
45184544
from test import test_pdb
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``<tab>`` at the beginning of the line in :mod:`pdb` multi-line input will fill in a 4-space indentation now, instead of inserting a ``\t`` character.

0 commit comments

Comments
 (0)
Please sign in to comment.