]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-133351: Fix remote PDB's multi-line block tab completion (#133387)
authorMatt Wozniski <mwozniski@bloomberg.net>
Sun, 4 May 2025 19:20:28 +0000 (15:20 -0400)
committerGitHub <noreply@github.com>
Sun, 4 May 2025 19:20:28 +0000 (15:20 -0400)
Lib/pdb.py
Lib/test/test_remote_pdb.py
Misc/NEWS.d/next/Library/2025-05-04-13-46-20.gh-issue-133351.YsZls1.rst [new file with mode: 0644]

index 343cf4404d7f8c0a6b431a1edcf425432162e8d6..2aa60c75396085d1786e2357a350170ceb7e4fc4 100644 (file)
@@ -2933,6 +2933,7 @@ class _PdbClient:
         self.completion_matches = []
         self.state = "dumb"
         self.write_failed = False
+        self.multiline_block = False
 
     def _ensure_valid_message(self, msg):
         # Ensure the message conforms to our protocol.
@@ -2979,6 +2980,7 @@ class _PdbClient:
             self.write_failed = True
 
     def read_command(self, prompt):
+        self.multiline_block = False
         reply = input(prompt)
 
         if self.state == "dumb":
@@ -3003,6 +3005,7 @@ class _PdbClient:
             return prefix + reply
 
         # Otherwise, valid first line of a multi-line statement
+        self.multiline_block = True
         continue_prompt = "...".ljust(len(prompt))
         while codeop.compile_command(reply, "<stdin>", "single") is None:
             reply += "\n" + input(continue_prompt)
@@ -3105,9 +3108,13 @@ class _PdbClient:
 
             origline = readline.get_line_buffer()
             line = origline.lstrip()
-            stripped = len(origline) - len(line)
-            begidx = readline.get_begidx() - stripped
-            endidx = readline.get_endidx() - stripped
+            if self.multiline_block:
+                # We're completing a line contained in a multi-line block.
+                # Force the remote to treat it as a Python expression.
+                line = "! " + line
+            offset = len(origline) - len(line)
+            begidx = readline.get_begidx() - offset
+            endidx = readline.get_endidx() - offset
 
             msg = {
                 "complete": {
index e4c44c78d4a53702aaf194ef305a1d5c9f5ed6ab..9fbe94fcdd6da798a4c4de71ca332fe9d85805d5 100644 (file)
@@ -531,6 +531,44 @@ class PdbClientTestCase(unittest.TestCase):
             expected_state={"state": "pdb"},
         )
 
+    def test_multiline_completion_in_pdb_state(self):
+        """Test requesting tab completions at a (Pdb) continuation prompt."""
+        # GIVEN
+        incoming = [
+            ("server", {"prompt": "(Pdb) ", "state": "pdb"}),
+            ("user", {"prompt": "(Pdb) ", "input": "if True:"}),
+            (
+                "user",
+                {
+                    "prompt": "...   ",
+                    "completion_request": {
+                        "line": "    b",
+                        "begidx": 4,
+                        "endidx": 5,
+                    },
+                    "input": "    bool()",
+                },
+            ),
+            ("server", {"completions": ["bin", "bool", "bytes"]}),
+            ("user", {"prompt": "...   ", "input": ""}),
+        ]
+        self.do_test(
+            incoming=incoming,
+            expected_outgoing=[
+                {
+                    "complete": {
+                        "text": "b",
+                        "line": "! b",
+                        "begidx": 2,
+                        "endidx": 3,
+                    }
+                },
+                {"reply": "if True:\n    bool()\n"},
+            ],
+            expected_completions=["bin", "bool", "bytes"],
+            expected_state={"state": "pdb"},
+        )
+
     def test_completion_in_interact_state(self):
         """Test requesting tab completions at a >>> prompt."""
         incoming = [
diff --git a/Misc/NEWS.d/next/Library/2025-05-04-13-46-20.gh-issue-133351.YsZls1.rst b/Misc/NEWS.d/next/Library/2025-05-04-13-46-20.gh-issue-133351.YsZls1.rst
new file mode 100644 (file)
index 0000000..c843f3e
--- /dev/null
@@ -0,0 +1,3 @@
+Fix remote PDB to correctly request tab completions for Python expressions
+from the server when completing a continuation line of a multi-line Python
+block.