Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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]]
Expand Down Expand Up @@ -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):
Expand Down
22 changes: 22 additions & 0 deletions Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4855,6 +4855,28 @@ 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"
# 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)


def load_tests(loader, tests, pattern):
from test import test_pdb
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Do not complete :mod:`pdb` commands in ``interact`` mode of :mod:`pdb`.
Loading