Skip to content

Commit d7cc6b4

Browse files
committed
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.
1 parent 3b43335 commit d7cc6b4

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

Lib/cmd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ def complete(self, text, state):
273273
endidx = readline.get_endidx() - stripped
274274
if begidx>0:
275275
cmd, args, foo = self.parseline(line)
276-
if cmd == '':
276+
if cmd in ('', None):
277277
compfunc = self.completedefault
278278
else:
279279
try:

Lib/test/test_cmd.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,31 @@ def do_tab_completion_test(self, args):
289289
self.assertIn(b'ab_completion_test', output)
290290
self.assertIn(b'tab completion success', output)
291291

292+
def test_bang_completion_without_do_shell(self):
293+
script = textwrap.dedent("""
294+
import cmd
295+
class simplecmd(cmd.Cmd):
296+
def completedefault(self, text, line, begidx, endidx):
297+
return ["hello"]
298+
299+
def default(self, line):
300+
if line == "! hello":
301+
print('tab completion success')
302+
else:
303+
print('tab completion failure')
304+
return True
305+
306+
simplecmd().cmdloop()
307+
""")
308+
309+
# '! h' and complete 'ello' to '! hello'
310+
input = b"! h\t\n"
311+
312+
output = run_pty(script, input)
313+
314+
self.assertIn(b'ello', output)
315+
self.assertIn(b'tab completion success', output)
316+
292317
def load_tests(loader, tests, pattern):
293318
tests.addTest(doctest.DocTestSuite())
294319
return tests

0 commit comments

Comments
 (0)