Skip to content

Commit eedc70d

Browse files
authored
Upgrade cmd module from CPython v3.14.2 (#6853)
Upgrades the `cmd` module and its tests from CPython v3.14.2 tag.
1 parent da41a0c commit eedc70d

2 files changed

Lines changed: 52 additions & 17 deletions

File tree

Lib/cmd.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
1. End of file on input is processed as the command 'EOF'.
66
2. A command is parsed out of each line by collecting the prefix composed
77
of characters in the identchars member.
8-
3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method
8+
3. A command 'foo' is dispatched to a method 'do_foo()'; the do_ method
99
is passed a single argument consisting of the remainder of the line.
1010
4. Typing an empty line repeats the last command. (Actually, it calls the
11-
method `emptyline', which may be overridden in a subclass.)
12-
5. There is a predefined `help' method. Given an argument `topic', it
13-
calls the command `help_topic'. With no arguments, it lists all topics
11+
method 'emptyline', which may be overridden in a subclass.)
12+
5. There is a predefined 'help' method. Given an argument 'topic', it
13+
calls the command 'help_topic'. With no arguments, it lists all topics
1414
with defined help_ functions, broken into up to three topics; documented
1515
commands, miscellaneous help topics, and undocumented commands.
16-
6. The command '?' is a synonym for `help'. The command '!' is a synonym
17-
for `shell', if a do_shell method exists.
16+
6. The command '?' is a synonym for 'help'. The command '!' is a synonym
17+
for 'shell', if a do_shell method exists.
1818
7. If completion is enabled, completing commands will be done automatically,
1919
and completing of commands args is done by calling complete_foo() with
2020
arguments text, line, begidx, endidx. text is string we are matching
@@ -23,31 +23,34 @@
2323
indexes of the text being matched, which could be used to provide
2424
different completion depending upon which position the argument is in.
2525
26-
The `default' method may be overridden to intercept commands for which there
26+
The 'default' method may be overridden to intercept commands for which there
2727
is no do_ method.
2828
29-
The `completedefault' method may be overridden to intercept completions for
29+
The 'completedefault' method may be overridden to intercept completions for
3030
commands that have no complete_ method.
3131
32-
The data member `self.ruler' sets the character used to draw separator lines
32+
The data member 'self.ruler' sets the character used to draw separator lines
3333
in the help messages. If empty, no ruler line is drawn. It defaults to "=".
3434
35-
If the value of `self.intro' is nonempty when the cmdloop method is called,
35+
If the value of 'self.intro' is nonempty when the cmdloop method is called,
3636
it is printed out on interpreter startup. This value may be overridden
3737
via an optional argument to the cmdloop() method.
3838
39-
The data members `self.doc_header', `self.misc_header', and
40-
`self.undoc_header' set the headers used for the help function's
39+
The data members 'self.doc_header', 'self.misc_header', and
40+
'self.undoc_header' set the headers used for the help function's
4141
listings of documented functions, miscellaneous topics, and undocumented
4242
functions respectively.
4343
"""
4444

45-
import inspect, string, sys
45+
import sys
4646

4747
__all__ = ["Cmd"]
4848

4949
PROMPT = '(Cmd) '
50-
IDENTCHARS = string.ascii_letters + string.digits + '_'
50+
IDENTCHARS = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'
51+
'abcdefghijklmnopqrstuvwxyz'
52+
'0123456789'
53+
'_')
5154

5255
class Cmd:
5356
"""A simple framework for writing line-oriented command interpreters.
@@ -270,7 +273,7 @@ def complete(self, text, state):
270273
endidx = readline.get_endidx() - stripped
271274
if begidx>0:
272275
cmd, args, foo = self.parseline(line)
273-
if cmd == '':
276+
if not cmd:
274277
compfunc = self.completedefault
275278
else:
276279
try:
@@ -303,9 +306,11 @@ def do_help(self, arg):
303306
try:
304307
func = getattr(self, 'help_' + arg)
305308
except AttributeError:
309+
from inspect import cleandoc
310+
306311
try:
307312
doc=getattr(self, 'do_' + arg).__doc__
308-
doc = inspect.cleandoc(doc)
313+
doc = cleandoc(doc)
309314
if doc:
310315
self.stdout.write("%s\n"%str(doc))
311316
return

Lib/test/test_cmd.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@
1111
import io
1212
import textwrap
1313
from test import support
14-
from test.support.import_helper import import_module
14+
from test.support.import_helper import ensure_lazy_imports, import_module
1515
from test.support.pty_helper import run_pty
1616

17+
class LazyImportTest(unittest.TestCase):
18+
@support.cpython_only
19+
def test_lazy_import(self):
20+
ensure_lazy_imports("cmd", {"inspect", "string"})
21+
22+
1723
class samplecmdclass(cmd.Cmd):
1824
"""
1925
Instance the sampleclass:
@@ -289,6 +295,30 @@ def do_tab_completion_test(self, args):
289295
self.assertIn(b'ab_completion_test', output)
290296
self.assertIn(b'tab completion success', output)
291297

298+
def test_bang_completion_without_do_shell(self):
299+
script = textwrap.dedent("""
300+
import cmd
301+
class simplecmd(cmd.Cmd):
302+
def completedefault(self, text, line, begidx, endidx):
303+
return ["hello"]
304+
305+
def default(self, line):
306+
if line.replace(" ", "") == "!hello":
307+
print('tab completion success')
308+
else:
309+
print('tab completion failure')
310+
return True
311+
312+
simplecmd().cmdloop()
313+
""")
314+
315+
# '! h' or '!h' and complete 'ello' to 'hello'
316+
for input in [b"! h\t\n", b"!h\t\n"]:
317+
with self.subTest(input=input):
318+
output = run_pty(script, input)
319+
self.assertIn(b'hello', output)
320+
self.assertIn(b'tab completion success', output)
321+
292322
def load_tests(loader, tests, pattern):
293323
tests.addTest(doctest.DocTestSuite())
294324
return tests

0 commit comments

Comments
 (0)