diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 6eb12f1c6f00df..ace5748ea7c7ab 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1260,6 +1260,11 @@ pdb fill in a 4-space indentation now, instead of inserting a ``\t`` character. (Contributed by Tian Gao in :gh:`130471`.) +* Auto-indent is introduced in :mod:`pdb` multi-line input. It will either + keep the indentation of the last line or insert a 4-space indentation when + it detects a new code block. + (Contributed by Tian Gao in :gh:`133350`.) + * ``$_asynctask`` is added to access the current asyncio task if applicable. (Contributed by Tian Gao in :gh:`124367`.) diff --git a/Lib/pdb.py b/Lib/pdb.py index 343cf4404d7f8c..1240258a4ab205 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -743,12 +743,34 @@ def displayhook(self, obj): self.message(repr(obj)) @contextmanager - def _enable_multiline_completion(self): + def _enable_multiline_input(self): + try: + import readline + except ImportError: + yield + return + + def input_auto_indent(): + last_index = readline.get_current_history_length() + last_line = readline.get_history_item(last_index) + if last_line: + if last_line.isspace(): + # If the last line is empty, we don't need to indent + return + + last_line = last_line.rstrip('\r\n') + indent = len(last_line) - len(last_line.lstrip()) + if last_line.endswith(":"): + indent += 4 + readline.insert_text(' ' * indent) + completenames = self.completenames try: self.completenames = self.complete_multiline_names + readline.set_startup_hook(input_auto_indent) yield finally: + readline.set_startup_hook() self.completenames = completenames return @@ -857,7 +879,7 @@ def _read_code(self, line): try: if (code := codeop.compile_command(line + '\n', '', 'single')) is None: # Multi-line mode - with self._enable_multiline_completion(): + with self._enable_multiline_input(): buffer = line continue_prompt = "... " while (code := codeop.compile_command(buffer, '', 'single')) is None: @@ -879,7 +901,11 @@ def _read_code(self, line): return None, None, False else: line = line.rstrip('\r\n') - buffer += '\n' + line + if line.isspace(): + # empty line, just continue + buffer += '\n' + else: + buffer += '\n' + line self.lastcmd = buffer except SyntaxError as e: # Maybe it's an await expression/statement diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index be365a5a3ddeec..fef75ac51c0db3 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4812,14 +4812,35 @@ def f(): self.assertIn(b'I love Python', output) + def test_multiline_auto_indent(self): + script = textwrap.dedent(""" + import pdb; pdb.Pdb().set_trace() + """) + + input = b"def f(x):\n" + input += b"if x > 0:\n" + input += b"x += 1\n" + input += b"return x\n" + # We need to do backspaces to remove the auto-indentation + input += b"\x08\x08\x08\x08else:\n" + input += b"return -x\n" + input += b"\n" + input += b"f(-21-21)\n" + input += b"c\n" + + output = run_pty(script, input) + + self.assertIn(b'42', output) + def test_multiline_completion(self): script = textwrap.dedent(""" import pdb; pdb.Pdb().set_trace() """) input = b"def func():\n" - # Complete: \treturn 40 + 2 - input += b"\tret\t 40 + 2\n" + # Auto-indent + # Complete: return 40 + 2 + input += b"ret\t 40 + 2\n" input += b"\n" # Complete: func() input += b"fun\t()\n" @@ -4839,12 +4860,13 @@ def test_multiline_indent_completion(self): # 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 + a = 1 + \x08\ta += 1 + \x08\x08\ta += 1 + \x08\x08\x08\ta += 1 + \x08\x08\x08\x08\tif a > 0: + a += 1 + \x08\x08\x08\x08return a func() c @@ -4852,7 +4874,7 @@ def func(): output = run_pty(script, input) - self.assertIn(b'4', output) + self.assertIn(b'5', output) self.assertNotIn(b'Error', output) def test_interact_completion(self): diff --git a/Misc/NEWS.d/next/Library/2025-05-03-16-04-04.gh-issue-133349.kAhJDY.rst b/Misc/NEWS.d/next/Library/2025-05-03-16-04-04.gh-issue-133349.kAhJDY.rst new file mode 100644 index 00000000000000..cf0c19926c3688 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-03-16-04-04.gh-issue-133349.kAhJDY.rst @@ -0,0 +1 @@ +Introduced auto-indent in :mod:`pdb` multi-line input.