https://github.com/python/cpython/commit/1d9406e426d95eb088e4a474fccf294cc106b2b6
commit: 1d9406e426d95eb088e4a474fccf294cc106b2b6
branch: main
author: Matt Wozniski <[email protected]>
committer: gaogaotiantian <[email protected]>
date: 2025-05-03T22:50:37-04:00
summary:

gh-133363: Fix Cmd completion for lines beginning with `! ` (#133364)

files:
A Misc/NEWS.d/next/Library/2025-05-03-21-55-33.gh-issue-133363.PTLnRP.rst
M Lib/cmd.py
M Lib/test/test_cmd.py

diff --git a/Lib/cmd.py b/Lib/cmd.py
index 438b88aa1049cc..51495fb32160b0 100644
--- a/Lib/cmd.py
+++ b/Lib/cmd.py
@@ -273,7 +273,7 @@ def complete(self, text, state):
             endidx = readline.get_endidx() - stripped
             if begidx>0:
                 cmd, args, foo = self.parseline(line)
-                if cmd == '':
+                if not cmd:
                     compfunc = self.completedefault
                 else:
                     try:
diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py
index 46ec82b704963d..0ae44f3987d324 100644
--- a/Lib/test/test_cmd.py
+++ b/Lib/test/test_cmd.py
@@ -289,6 +289,30 @@ def do_tab_completion_test(self, args):
         self.assertIn(b'ab_completion_test', output)
         self.assertIn(b'tab completion success', output)
 
+    def test_bang_completion_without_do_shell(self):
+        script = textwrap.dedent("""
+            import cmd
+            class simplecmd(cmd.Cmd):
+                def completedefault(self, text, line, begidx, endidx):
+                    return ["hello"]
+
+                def default(self, line):
+                    if line.replace(" ", "") == "!hello":
+                        print('tab completion success')
+                    else:
+                        print('tab completion failure')
+                    return True
+
+            simplecmd().cmdloop()
+        """)
+
+        # '! h' or '!h' and complete 'ello' to 'hello'
+        for input in [b"! h\t\n", b"!h\t\n"]:
+            with self.subTest(input=input):
+                output = run_pty(script, input)
+                self.assertIn(b'hello', output)
+                self.assertIn(b'tab completion success', output)
+
 def load_tests(loader, tests, pattern):
     tests.addTest(doctest.DocTestSuite())
     return tests
diff --git 
a/Misc/NEWS.d/next/Library/2025-05-03-21-55-33.gh-issue-133363.PTLnRP.rst 
b/Misc/NEWS.d/next/Library/2025-05-03-21-55-33.gh-issue-133363.PTLnRP.rst
new file mode 100644
index 00000000000000..d44c685e75e6c1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-05-03-21-55-33.gh-issue-133363.PTLnRP.rst
@@ -0,0 +1,3 @@
+The :class:`cmd.Cmd` class has been fixed to reliably call the 
``completedefault``
+method whenever the ``do_shell`` method is not defined and tab completion is
+requested for a line beginning with ``!``.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to