https://github.com/python/cpython/commit/b52866953a64c5e0fe57784fbcfc6bec87861563
commit: b52866953a64c5e0fe57784fbcfc6bec87861563
branch: main
author: Tian Gao <gaogaotiant...@hotmail.com>
committer: gaogaotiantian <gaogaotiant...@hotmail.com>
date: 2025-03-12T17:23:53-04:00
summary:

gh-131123: Support completion in `pdb` for convenience variable attributes 
(#131124)

files:
A Misc/NEWS.d/next/Library/2025-03-11-23-58-45.gh-issue-131123.WB6tPh.rst
M Lib/pdb.py
M Lib/test/test_pdb.py

diff --git a/Lib/pdb.py b/Lib/pdb.py
index 75fc29068fa843..2842f3d497b978 100644
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -975,17 +975,16 @@ 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.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 @@ def _complete_expression(self, text, line, begidx, endidx):
             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 94332f1daee479..910b8fcb74d1e3 100644
--- a/Lib/test/test_pdb.py
+++ b/Lib/test/test_pdb.py
@@ -4478,6 +4478,25 @@ def test_builtin_completion(self):
 
         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'<frame at 0x', output)
+        self.assertIn(b'102', output)
+
     def test_local_namespace(self):
         script = textwrap.dedent("""
             def f():
diff --git 
a/Misc/NEWS.d/next/Library/2025-03-11-23-58-45.gh-issue-131123.WB6tPh.rst 
b/Misc/NEWS.d/next/Library/2025-03-11-23-58-45.gh-issue-131123.WB6tPh.rst
new file mode 100644
index 00000000000000..b9ecc973915734
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-03-11-23-58-45.gh-issue-131123.WB6tPh.rst
@@ -0,0 +1 @@
+Supported completions for attributes of convenience variables in :mod:`pdb`.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to