From 12e2495c3b84a94f50f61312ba708163f972eeda Mon Sep 17 00:00:00 2001 From: Matt Wozniski Date: Sat, 3 May 2025 21:36:10 -0400 Subject: [PATCH 1/4] Fix Cmd completion for lines beginning with `! ` When a line begins with `!` and there's no `do_shell` method defined, `parsecmd` returns `None` as the `cmd`, which incorrectly leads to `None` being concatenated to `complete_` and triggering a `TypeError`. Instead, recognize `None` as a sentinel that means we should call `completedefault`, as an empty string already is. --- Lib/cmd.py | 2 +- Lib/test/test_cmd.py | 25 +++++++++++++++++++ ...-05-03-21-55-33.gh-issue-133363.PTLnRP.rst | 5 ++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2025-05-03-21-55-33.gh-issue-133363.PTLnRP.rst diff --git a/Lib/cmd.py b/Lib/cmd.py index 438b88aa1049cc..9ae81178aa5feb 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 cmd in ('', None): compfunc = self.completedefault else: try: diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py index 46ec82b704963d..727a164b7f9306 100644 --- a/Lib/test/test_cmd.py +++ b/Lib/test/test_cmd.py @@ -289,6 +289,31 @@ 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 == "! hello": + print('tab completion success') + else: + print('tab completion failure') + return True + + simplecmd().cmdloop() + """) + + # '! h' and complete 'ello' to '! hello' + input = b"! h\t\n" + + output = run_pty(script, input) + + self.assertIn(b'ello', 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..379482d6369a87 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-03-21-55-33.gh-issue-133363.PTLnRP.rst @@ -0,0 +1,5 @@ +The :class:`cmd.Cmd` class has been fixed to call the ``completedefault`` +method whenever the ``do_shell`` method is not defined and tab completion is +requested for a line beginning with ``!``. Previously ``completedefault`` +was called only if there were no spaces between the ``!`` and the cursor +position where tab completion was attempted. From 973bef66152640abb820841b20b2a948ff00cd03 Mon Sep 17 00:00:00 2001 From: Matt Wozniski Date: Sat, 3 May 2025 22:00:06 -0400 Subject: [PATCH 2/4] Check falsiness instead --- Lib/cmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/cmd.py b/Lib/cmd.py index 9ae81178aa5feb..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 in ('', None): + if not cmd: compfunc = self.completedefault else: try: From 1c6248e427184be34f41011310099d40b76fdb4c Mon Sep 17 00:00:00 2001 From: Matt Wozniski Date: Sat, 3 May 2025 22:07:06 -0400 Subject: [PATCH 3/4] Make news entry less descriptive --- .../Library/2025-05-03-21-55-33.gh-issue-133363.PTLnRP.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 index 379482d6369a87..d44c685e75e6c1 100644 --- 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 @@ -1,5 +1,3 @@ -The :class:`cmd.Cmd` class has been fixed to call the ``completedefault`` +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 ``!``. Previously ``completedefault`` -was called only if there were no spaces between the ``!`` and the cursor -position where tab completion was attempted. +requested for a line beginning with ``!``. From c259bef79c6a6eae676b65510bfe50e8a37829f4 Mon Sep 17 00:00:00 2001 From: Matt Wozniski Date: Sat, 3 May 2025 22:16:23 -0400 Subject: [PATCH 4/4] Test with and without a space after ! --- Lib/test/test_cmd.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py index 727a164b7f9306..0ae44f3987d324 100644 --- a/Lib/test/test_cmd.py +++ b/Lib/test/test_cmd.py @@ -297,7 +297,7 @@ def completedefault(self, text, line, begidx, endidx): return ["hello"] def default(self, line): - if line == "! hello": + if line.replace(" ", "") == "!hello": print('tab completion success') else: print('tab completion failure') @@ -306,13 +306,12 @@ def default(self, line): simplecmd().cmdloop() """) - # '! h' and complete 'ello' to '! hello' - input = b"! h\t\n" - - output = run_pty(script, input) - - self.assertIn(b'ello', output) - self.assertIn(b'tab completion success', output) + # '! 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()) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy