gh-110944: Make pdb completion work for alias and convenience vars (GH-110945)

This commit is contained in:
Tian Gao 2023-11-14 04:22:25 -08:00 committed by GitHub
parent 324531df90
commit f44d6ff6e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 1 deletions

View file

@ -238,7 +238,7 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
try:
import readline
# remove some common file name delimiters
readline.set_completer_delims(' \t\n`@#$%^&*()=+[{]}\\|;:\'",<>?')
readline.set_completer_delims(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?')
except ImportError:
pass
self.allow_kbdint = False
@ -686,6 +686,18 @@ def set_convenience_variable(self, frame, name, value):
# Generic completion functions. Individual complete_foo methods can be
# assigned below to one of these functions.
def completenames(self, text, line, begidx, endidx):
# Overwrite completenames() of cmd so for the command completion,
# if no current command matches, check for expressions as well
commands = super().completenames(text, line, begidx, endidx)
for alias in self.aliases:
if alias.startswith(text):
commands.append(alias)
if commands:
return commands
else:
return self._complete_expression(text, line, begidx, endidx)
def _complete_location(self, text, line, begidx, endidx):
# Complete a file/module/function location for break/tbreak/clear.
if line.strip().endswith((':', ',')):
@ -720,6 +732,10 @@ def _complete_expression(self, text, line, begidx, endidx):
# complete builtins, and they clutter the namespace quite heavily, so we
# leave them out.
ns = {**self.curframe.f_globals, **self.curframe_locals}
if text.startswith("$"):
# Complete convenience variables
conv_vars = self.curframe.f_globals.get('__pdb_convenience_variables', {})
return [f"${name}" for name in conv_vars if name.startswith(text[1:])]
if '.' in text:
# Walk an attribute chain up to the last part, similar to what
# rlcompleter does. This will bail if any of the parts are not

View file

@ -3289,6 +3289,27 @@ def test_basic_completion(self):
self.assertIn(b'continue', output)
self.assertIn(b'hello!', output)
def test_expression_completion(self):
script = textwrap.dedent("""
value = "speci"
import pdb; pdb.Pdb().set_trace()
""")
# Complete: value + 'al'
input = b"val\t + 'al'\n"
# Complete: p value + 'es'
input += b"p val\t + 'es'\n"
# Complete: $_frame
input += b"$_fra\t\n"
# Continue
input += b"c\n"
output = run_pty(script, input)
self.assertIn(b'special', output)
self.assertIn(b'species', output)
self.assertIn(b'$_frame', output)
def load_tests(loader, tests, pattern):
from test import test_pdb

View file

@ -0,0 +1 @@
Support alias and convenience vars for :mod:`pdb` completion