https://github.com/python/cpython/commit/327f5ff9fa4291e66079c61c77b273cb953c302f commit: 327f5ff9fa4291e66079c61c77b273cb953c302f branch: main author: Tian Gao <gaogaotiant...@hotmail.com> committer: gaogaotiantian <gaogaotiant...@hotmail.com> date: 2025-04-30T18:19:13-04:00 summary:
gh-133153: Use rlcompleter for pdb's interact command (#133176) files: A Misc/NEWS.d/next/Library/2025-04-29-23-20-52.gh-issue-133153.M-w9yC.rst M Lib/pdb.py M Lib/test/test_pdb.py diff --git a/Lib/pdb.py b/Lib/pdb.py index e2c7468c50c354..343cf4404d7f8c 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -1157,6 +1157,22 @@ def completedefault(self, text, line, begidx, endidx): state += 1 return matches + @contextmanager + def _enable_rlcompleter(self, ns): + try: + import readline + except ImportError: + yield + return + + try: + old_completer = readline.get_completer() + completer = Completer(ns) + readline.set_completer(completer.complete) + yield + finally: + readline.set_completer(old_completer) + # Pdb meta commands, only intended to be used internally by pdb def _pdbcmd_print_frame_status(self, arg): @@ -2242,9 +2258,10 @@ def do_interact(self, arg): contains all the (global and local) names found in the current scope. """ ns = {**self.curframe.f_globals, **self.curframe.f_locals} - console = _PdbInteractiveConsole(ns, message=self.message) - console.interact(banner="*pdb interact start*", - exitmsg="*exit from pdb interact command*") + with self._enable_rlcompleter(ns): + console = _PdbInteractiveConsole(ns, message=self.message) + console.interact(banner="*pdb interact start*", + exitmsg="*exit from pdb interact command*") def do_alias(self, arg): """alias [name [command]] @@ -2749,14 +2766,18 @@ def _read_reply(self): self.error(f"Ignoring invalid message from client: {msg}") def _complete_any(self, text, line, begidx, endidx): - if begidx == 0: - return self.completenames(text, line, begidx, endidx) - - cmd = self.parseline(line)[0] - if cmd: - compfunc = getattr(self, "complete_" + cmd, self.completedefault) - else: + # If we're in 'interact' mode, we need to use the default completer + if self._interact_state: compfunc = self.completedefault + else: + if begidx == 0: + return self.completenames(text, line, begidx, endidx) + + cmd = self.parseline(line)[0] + if cmd: + compfunc = getattr(self, "complete_" + cmd, self.completedefault) + else: + compfunc = self.completedefault return compfunc(text, line, begidx, endidx) def cmdloop(self, intro=None): diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index ae84fe3ce7d65a..be365a5a3ddeec 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4855,6 +4855,34 @@ def func(): self.assertIn(b'4', output) self.assertNotIn(b'Error', output) + def test_interact_completion(self): + script = textwrap.dedent(""" + value = "speci" + import pdb; pdb.Pdb().set_trace() + """) + + # Enter interact mode + input = b"interact\n" + # Should fail to complete 'display' because that's a pdb command + input += b"disp\t\n" + # 'value' should still work + input += b"val\t + 'al'\n" + # Let's define a function to test <tab> + input += b"def f():\n" + input += b"\treturn 42\n" + input += b"\n" + input += b"f() * 2\n" + # Exit interact mode + input += b"exit()\n" + # continue + input += b"c\n" + + output = run_pty(script, input) + + self.assertIn(b"'disp' is not defined", output) + self.assertIn(b'special', output) + self.assertIn(b'84', output) + def load_tests(loader, tests, pattern): from test import test_pdb diff --git a/Misc/NEWS.d/next/Library/2025-04-29-23-20-52.gh-issue-133153.M-w9yC.rst b/Misc/NEWS.d/next/Library/2025-04-29-23-20-52.gh-issue-133153.M-w9yC.rst new file mode 100644 index 00000000000000..c609fa698dca49 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-29-23-20-52.gh-issue-133153.M-w9yC.rst @@ -0,0 +1 @@ +Do not complete :mod:`pdb` commands in ``interact`` mode of :mod:`pdb`. _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com