Skip to content

Commit b034f6d

Browse files
committed
Improved how new argparse-based decorators provide help
Now "help command_name" and "command_name -h" provide exactly the same text. The function docstring for the "do_*" command sets and overrides the ArgumentParser "description" if the docstring is not empty.
1 parent 91bc999 commit b034f6d

File tree

4 files changed

+28
-33
lines changed

4 files changed

+28
-33
lines changed

cmd2.py

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,10 @@ def cmd_wrapper(instance, cmdline):
288288
argparser.prog = func.__name__[3:]
289289

290290
# put the help message in the method docstring
291-
funcdoc = func.__doc__
292-
if funcdoc:
293-
funcdoc += '\n'
294-
else:
295-
# if it's None, make it an empty string
296-
funcdoc = ''
297-
cmd_wrapper.__doc__ = '{}{}'.format(funcdoc, argparser.format_help())
291+
if func.__doc__:
292+
argparser.description = func.__doc__
293+
294+
cmd_wrapper.__doc__ = argparser.format_help()
298295
return cmd_wrapper
299296
return arg_decorator
300297

@@ -315,13 +312,10 @@ def cmd_wrapper(instance, cmdline):
315312
argparser.prog = func.__name__[3:]
316313

317314
# put the help message in the method docstring
318-
funcdoc = func.__doc__
319-
if funcdoc:
320-
funcdoc += '\n'
321-
else:
322-
# if it's None, make it an empty string
323-
funcdoc = ''
324-
cmd_wrapper.__doc__ = '{}{}'.format(funcdoc, argparser.format_help())
315+
if func.__doc__:
316+
argparser.description = func.__doc__
317+
318+
cmd_wrapper.__doc__ = argparser.format_help()
325319
return cmd_wrapper
326320
return arg_decorator
327321

@@ -1341,7 +1335,7 @@ def show(self, args, parameter):
13411335
else:
13421336
raise LookupError("Parameter '%s' not supported (type 'show' for list of parameters)." % param)
13431337

1344-
set_parser = argparse.ArgumentParser(description='show or set value of a parameter')
1338+
set_parser = argparse.ArgumentParser()
13451339
set_parser.add_argument('-a', '--all', action='store_true', help='display read-only settings as well')
13461340
set_parser.add_argument('-l', '--long', action='store_true', help='describe function of parameter')
13471341
set_parser.add_argument('settable', nargs='*', help='[param_name] [value]')
@@ -1693,13 +1687,11 @@ def do_ipy(self, arg):
16931687
exit_msg = 'Leaving IPython, back to {}'.format(sys.argv[0])
16941688
embed(banner1=banner, exit_msg=exit_msg)
16951689

1696-
history_parser = argparse.ArgumentParser(
1697-
description='run, edit, and save previously entered commands',
1698-
formatter_class=argparse.RawTextHelpFormatter,
1699-
)
1690+
history_parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
17001691
history_parser_group = history_parser.add_mutually_exclusive_group()
17011692
history_parser_group.add_argument('-r', '--run', action='store_true', help='run selected history items')
1702-
history_parser_group.add_argument('-e', '--edit', action='store_true', help='edit and then run selected history items')
1693+
history_parser_group.add_argument('-e', '--edit', action='store_true',
1694+
help='edit and then run selected history items')
17031695
history_parser_group.add_argument('-o', '--output-file', metavar='FILE', help='output to file')
17041696
history_parser.add_argument('-s', '--script', action='store_true', help='script format; no separation lines')
17051697
_history_arg_help = """empty all history items
@@ -1711,8 +1703,8 @@ def do_ipy(self, arg):
17111703

17121704
@with_argument_parser(history_parser)
17131705
def do_history(self, args):
1714-
# If an argument was supplied, then retrieve partial contents of the
1715-
# history
1706+
"""View, run, edit, and save previously entered commands."""
1707+
# If an argument was supplied, then retrieve partial contents of the history
17161708
cowardly_refuse_to_run = False
17171709
if args.arg:
17181710
# If a character indicating a slice is present, retrieve
@@ -1735,7 +1727,8 @@ def do_history(self, args):
17351727
if args.run:
17361728
if cowardly_refuse_to_run:
17371729
self.perror("Cowardly refusing to run all previously entered commands.", traceback_war=False)
1738-
self.perror("If this is what you want to do, specify '1:' as the range of history.", traceback_war=False)
1730+
self.perror("If this is what you want to do, specify '1:' as the range of history.",
1731+
traceback_war=False)
17391732
else:
17401733
for runme in history:
17411734
self.pfeedback(runme)
@@ -1744,20 +1737,20 @@ def do_history(self, args):
17441737
elif args.edit:
17451738
fd, fname = tempfile.mkstemp(suffix='.txt', text=True)
17461739
with os.fdopen(fd, 'w') as fobj:
1747-
for cmd in history:
1748-
fobj.write('{}\n'.format(cmd))
1740+
for command in history:
1741+
fobj.write('{}\n'.format(command))
17491742
try:
17501743
os.system('"{}" "{}"'.format(self.editor, fname))
17511744
self.do_load(fname)
1752-
except:
1745+
except Exception:
17531746
raise
17541747
finally:
17551748
os.remove(fname)
17561749
elif args.output_file:
17571750
try:
17581751
with open(os.path.expanduser(args.output_file), 'w') as fobj:
1759-
for cmd in history:
1760-
fobj.write('{}\n'.format(cmd))
1752+
for command in history:
1753+
fobj.write('{}\n'.format(command))
17611754
plural = 's' if len(history) > 1 else ''
17621755
self.pfeedback('{} command{} saved to {}'.format(len(history), plural, args.output_file))
17631756
except Exception as e:
@@ -1770,7 +1763,6 @@ def do_history(self, args):
17701763
else:
17711764
self.poutput(hi.pr())
17721765

1773-
17741766
@with_argument_list
17751767
def do_edit(self, arglist):
17761768
"""Edit a file or command in a text editor.
@@ -1876,7 +1868,6 @@ def do_load(self, arglist):
18761868

18771869
self._script_dir.append(os.path.dirname(expanded_path))
18781870

1879-
18801871
@staticmethod
18811872
def is_text_file(file_path):
18821873
"""

examples/argparse_example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def do_speak(self, args):
6464
do_say = do_speak # now "say" is a synonym for "speak"
6565
do_orate = do_speak # another synonym, but this one takes multi-line input
6666

67-
tag_parser = argparse.ArgumentParser(description='create a html tag')
67+
tag_parser = argparse.ArgumentParser()
6868
tag_parser.add_argument('tag', nargs=1, help='tag')
6969
tag_parser.add_argument('content', nargs='+', help='content to surround with tag')
7070

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# Help text for the history command
2222
HELP_HISTORY = """usage: history [-h] [-r | -e | -o FILE] [-s] [arg]
2323
24-
run, edit, and save previously entered commands
24+
View, run, edit, and save previously entered commands.
2525
2626
positional arguments:
2727
arg empty all history items

tests/test_argparse.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,14 @@ def test_argparse_quoted_arguments_posix_multiple(argparse_app):
140140

141141
def test_argparse_help_docstring(argparse_app):
142142
out = run_cmd(argparse_app, 'help say')
143-
assert out[0] == 'Repeat what you tell me to.'
143+
assert out[0].startswith('usage: say')
144+
assert out[1] == ''
145+
assert out[2] == 'Repeat what you tell me to.'
144146

145147
def test_argparse_help_description(argparse_app):
146148
out = run_cmd(argparse_app, 'help tag')
149+
assert out[0].startswith('usage: tag')
150+
assert out[1] == ''
147151
assert out[2] == 'create a html tag'
148152

149153
def test_argparse_prog(argparse_app):

0 commit comments

Comments
 (0)