Skip to content

Commit f44d6ff

Browse files
gh-110944: Make pdb completion work for alias and convenience vars (GH-110945)
1 parent 324531d commit f44d6ff

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

Lib/pdb.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
238238
try:
239239
import readline
240240
# remove some common file name delimiters
241-
readline.set_completer_delims(' \t\n`@#$%^&*()=+[{]}\\|;:\'",<>?')
241+
readline.set_completer_delims(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?')
242242
except ImportError:
243243
pass
244244
self.allow_kbdint = False
@@ -686,6 +686,18 @@ def set_convenience_variable(self, frame, name, value):
686686
# Generic completion functions. Individual complete_foo methods can be
687687
# assigned below to one of these functions.
688688

689+
def completenames(self, text, line, begidx, endidx):
690+
# Overwrite completenames() of cmd so for the command completion,
691+
# if no current command matches, check for expressions as well
692+
commands = super().completenames(text, line, begidx, endidx)
693+
for alias in self.aliases:
694+
if alias.startswith(text):
695+
commands.append(alias)
696+
if commands:
697+
return commands
698+
else:
699+
return self._complete_expression(text, line, begidx, endidx)
700+
689701
def _complete_location(self, text, line, begidx, endidx):
690702
# Complete a file/module/function location for break/tbreak/clear.
691703
if line.strip().endswith((':', ',')):
@@ -720,6 +732,10 @@ def _complete_expression(self, text, line, begidx, endidx):
720732
# complete builtins, and they clutter the namespace quite heavily, so we
721733
# leave them out.
722734
ns = {**self.curframe.f_globals, **self.curframe_locals}
735+
if text.startswith("$"):
736+
# Complete convenience variables
737+
conv_vars = self.curframe.f_globals.get('__pdb_convenience_variables', {})
738+
return [f"${name}" for name in conv_vars if name.startswith(text[1:])]
723739
if '.' in text:
724740
# Walk an attribute chain up to the last part, similar to what
725741
# rlcompleter does. This will bail if any of the parts are not

Lib/test/test_pdb.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,6 +3289,27 @@ def test_basic_completion(self):
32893289
self.assertIn(b'continue', output)
32903290
self.assertIn(b'hello!', output)
32913291

3292+
def test_expression_completion(self):
3293+
script = textwrap.dedent("""
3294+
value = "speci"
3295+
import pdb; pdb.Pdb().set_trace()
3296+
""")
3297+
3298+
# Complete: value + 'al'
3299+
input = b"val\t + 'al'\n"
3300+
# Complete: p value + 'es'
3301+
input += b"p val\t + 'es'\n"
3302+
# Complete: $_frame
3303+
input += b"$_fra\t\n"
3304+
# Continue
3305+
input += b"c\n"
3306+
3307+
output = run_pty(script, input)
3308+
3309+
self.assertIn(b'special', output)
3310+
self.assertIn(b'species', output)
3311+
self.assertIn(b'$_frame', output)
3312+
32923313

32933314
def load_tests(loader, tests, pattern):
32943315
from test import test_pdb
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support alias and convenience vars for :mod:`pdb` completion

0 commit comments

Comments
 (0)