]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-133153: Use rlcompleter for pdb's interact command (#133176)
authorTian Gao <gaogaotiantian@hotmail.com>
Wed, 30 Apr 2025 22:19:13 +0000 (15:19 -0700)
committerGitHub <noreply@github.com>
Wed, 30 Apr 2025 22:19:13 +0000 (18:19 -0400)
Lib/pdb.py
Lib/test/test_pdb.py
Misc/NEWS.d/next/Library/2025-04-29-23-20-52.gh-issue-133153.M-w9yC.rst [new file with mode: 0644]

index e2c7468c50c354df17b897ed943dc49efba1f412..343cf4404d7f8c0a6b431a1edcf425432162e8d6 100644 (file)
@@ -1157,6 +1157,22 @@ class Pdb(bdb.Bdb, cmd.Cmd):
             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 @@ class Pdb(bdb.Bdb, cmd.Cmd):
         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 @@ class _PdbServer(Pdb):
             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):
index ae84fe3ce7d65aa57ab39f9aaefb8a093da6b62c..be365a5a3ddeecc7baa3174886fe24b631b80c15 100644 (file)
@@ -4855,6 +4855,34 @@ class PdbTestReadline(unittest.TestCase):
         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 (file)
index 0000000..c609fa6
--- /dev/null
@@ -0,0 +1 @@
+Do not complete :mod:`pdb` commands in ``interact`` mode of :mod:`pdb`.