gh-125377: Improve tab indentation for pdb multi-line input (#130471)

This commit is contained in:
Tian Gao 2025-03-04 15:45:38 -05:00 committed by GitHub
parent c989e74446
commit b6769e9404
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 3 deletions

View file

@ -785,6 +785,10 @@ pdb
(if any).
(Contributed by Tian Gao in :gh:`130493`.)
* ``<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.
(Contributed by Tian Gao in :gh:`130471`.)
pickle
------

View file

@ -652,10 +652,10 @@ class Pdb(bdb.Bdb, cmd.Cmd):
self.message(repr(obj))
@contextmanager
def _disable_command_completion(self):
def _enable_multiline_completion(self):
completenames = self.completenames
try:
self.completenames = self.completedefault
self.completenames = self.complete_multiline_names
yield
finally:
self.completenames = completenames
@ -753,7 +753,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
buffer = line
if (code := codeop.compile_command(line + '\n', '<stdin>', 'single')) is None:
# Multi-line mode
with self._disable_command_completion():
with self._enable_multiline_completion():
buffer = line
continue_prompt = "... "
while (code := codeop.compile_command(buffer, '<stdin>', 'single')) is None:
@ -996,6 +996,21 @@ class Pdb(bdb.Bdb, cmd.Cmd):
# Complete a simple name.
return [n for n in ns.keys() if n.startswith(text)]
def _complete_indentation(self, text, line, begidx, endidx):
try:
import readline
except ImportError:
return []
# Fill in spaces to form a 4-space indent
return [' ' * (4 - readline.get_begidx() % 4)]
def complete_multiline_names(self, text, line, begidx, endidx):
# If text is space-only, the user entered <tab> before any text.
# That normally means they want to indent the current line.
if not text.strip():
return self._complete_indentation(text, line, begidx, endidx)
return self.completedefault(text, line, begidx, endidx)
def completedefault(self, text, line, begidx, endidx):
if text.startswith("$"):
# Complete convenience variables

View file

@ -4513,6 +4513,32 @@ class PdbTestReadline(unittest.TestCase):
self.assertIn(b'42', output)
def test_multiline_indent_completion(self):
script = textwrap.dedent("""
import pdb; pdb.Pdb().set_trace()
""")
# \t should always complete a 4-space indent
# This piece of code will raise an IndentationError or a SyntaxError
# if the completion is not working as expected
input = textwrap.dedent("""\
def func():
\ta = 1
\ta += 1
\ta += 1
\tif a > 0:
a += 1
\t\treturn a
func()
c
""").encode()
output = run_pty(script, input)
self.assertIn(b'4', output)
self.assertNotIn(b'Error', output)
def load_tests(loader, tests, pattern):
from test import test_pdb

View file

@ -0,0 +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.