From: Tian Gao Date: Wed, 12 Mar 2025 21:23:53 +0000 (-0400) Subject: gh-131123: Support completion in `pdb` for convenience variable attributes (#131124) X-Git-Tag: v3.14.0a6~50 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b52866953a64c5e0fe57784fbcfc6bec87861563;p=thirdparty%2FPython%2Fcpython.git gh-131123: Support completion in `pdb` for convenience variable attributes (#131124) --- diff --git a/Lib/pdb.py b/Lib/pdb.py index 75fc29068fa8..2842f3d497b9 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -975,17 +975,16 @@ class Pdb(bdb.Bdb, cmd.Cmd): # complete builtins, and they clutter the namespace quite heavily, so we # leave them out. ns = {**self.curframe.f_globals, **self.curframe.f_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 # simple attribute access, which is what we want. dotted = text.split('.') try: - obj = ns[dotted[0]] + if dotted[0].startswith('$'): + obj = self.curframe.f_globals['__pdb_convenience_variables'][dotted[0][1:]] + else: + obj = ns[dotted[0]] for part in dotted[1:-1]: obj = getattr(obj, part) except (KeyError, AttributeError): @@ -993,6 +992,10 @@ class Pdb(bdb.Bdb, cmd.Cmd): prefix = '.'.join(dotted[:-1]) + '.' return [prefix + n for n in dir(obj) if n.startswith(dotted[-1])] else: + 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:])] # Complete a simple name. return [n for n in ns.keys() if n.startswith(text)] diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 94332f1daee4..910b8fcb74d1 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4478,6 +4478,25 @@ class PdbTestReadline(unittest.TestCase): self.assertIn(b'special', output) + def test_convvar_completion(self): + script = textwrap.dedent(""" + import pdb; pdb.Pdb().set_trace() + """) + + # Complete: $_frame + input = b"$_fram\t\n" + + # Complete: $_frame.f_lineno + 100 + input += b"$_frame.f_line\t + 100\n" + + # Continue + input += b"c\n" + + output = run_pty(script, input) + + self.assertIn(b'