diff options
-rwxr-xr-x | cmd2.py | 51 | ||||
-rw-r--r-- | docs/argument_processing.rst | 22 | ||||
-rwxr-xr-x | examples/argparse_example.py | 6 | ||||
-rwxr-xr-x | examples/pirate.py | 4 | ||||
-rw-r--r-- | tests/conftest.py | 2 | ||||
-rw-r--r-- | tests/test_argparse.py | 10 |
6 files changed, 46 insertions, 49 deletions
@@ -288,13 +288,10 @@ def with_argparser_and_unknown_args(argparser): argparser.prog = func.__name__[3:] # put the help message in the method docstring - funcdoc = func.__doc__ - if funcdoc: - funcdoc += '\n' - else: - # if it's None, make it an empty string - funcdoc = '' - cmd_wrapper.__doc__ = '{}{}'.format(funcdoc, argparser.format_help()) + if func.__doc__: + argparser.description = func.__doc__ + + cmd_wrapper.__doc__ = argparser.format_help() return cmd_wrapper return arg_decorator @@ -315,13 +312,10 @@ def with_argument_parser(argparser): argparser.prog = func.__name__[3:] # put the help message in the method docstring - funcdoc = func.__doc__ - if funcdoc: - funcdoc += '\n' - else: - # if it's None, make it an empty string - funcdoc = '' - cmd_wrapper.__doc__ = '{}{}'.format(funcdoc, argparser.format_help()) + if func.__doc__: + argparser.description = func.__doc__ + + cmd_wrapper.__doc__ = argparser.format_help() return cmd_wrapper return arg_decorator @@ -1341,7 +1335,7 @@ class Cmd(cmd.Cmd): else: raise LookupError("Parameter '%s' not supported (type 'show' for list of parameters)." % param) - set_parser = argparse.ArgumentParser(description='show or set value of a parameter') + set_parser = argparse.ArgumentParser() set_parser.add_argument('-a', '--all', action='store_true', help='display read-only settings as well') set_parser.add_argument('-l', '--long', action='store_true', help='describe function of parameter') set_parser.add_argument('settable', nargs='*', help='[param_name] [value]') @@ -1693,13 +1687,11 @@ Paths or arguments that contain spaces must be enclosed in quotes exit_msg = 'Leaving IPython, back to {}'.format(sys.argv[0]) embed(banner1=banner, exit_msg=exit_msg) - history_parser = argparse.ArgumentParser( - description='run, edit, and save previously entered commands', - formatter_class=argparse.RawTextHelpFormatter, - ) + history_parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) history_parser_group = history_parser.add_mutually_exclusive_group() history_parser_group.add_argument('-r', '--run', action='store_true', help='run selected history items') - history_parser_group.add_argument('-e', '--edit', action='store_true', help='edit and then run selected history items') + history_parser_group.add_argument('-e', '--edit', action='store_true', + help='edit and then run selected history items') history_parser_group.add_argument('-o', '--output-file', metavar='FILE', help='output to file') history_parser.add_argument('-s', '--script', action='store_true', help='script format; no separation lines') _history_arg_help = """empty all history items @@ -1711,8 +1703,8 @@ a..b, a:b, a:, ..b items by indices (inclusive) @with_argument_parser(history_parser) def do_history(self, args): - # If an argument was supplied, then retrieve partial contents of the - # history + """View, run, edit, and save previously entered commands.""" + # If an argument was supplied, then retrieve partial contents of the history cowardly_refuse_to_run = False if args.arg: # If a character indicating a slice is present, retrieve @@ -1735,7 +1727,8 @@ a..b, a:b, a:, ..b items by indices (inclusive) if args.run: if cowardly_refuse_to_run: self.perror("Cowardly refusing to run all previously entered commands.", traceback_war=False) - self.perror("If this is what you want to do, specify '1:' as the range of history.", traceback_war=False) + self.perror("If this is what you want to do, specify '1:' as the range of history.", + traceback_war=False) else: for runme in history: self.pfeedback(runme) @@ -1744,20 +1737,20 @@ a..b, a:b, a:, ..b items by indices (inclusive) elif args.edit: fd, fname = tempfile.mkstemp(suffix='.txt', text=True) with os.fdopen(fd, 'w') as fobj: - for cmd in history: - fobj.write('{}\n'.format(cmd)) + for command in history: + fobj.write('{}\n'.format(command)) try: os.system('"{}" "{}"'.format(self.editor, fname)) self.do_load(fname) - except: + except Exception: raise finally: os.remove(fname) elif args.output_file: try: with open(os.path.expanduser(args.output_file), 'w') as fobj: - for cmd in history: - fobj.write('{}\n'.format(cmd)) + for command in history: + fobj.write('{}\n'.format(command)) plural = 's' if len(history) > 1 else '' self.pfeedback('{} command{} saved to {}'.format(len(history), plural, args.output_file)) except Exception as e: @@ -1770,7 +1763,6 @@ a..b, a:b, a:, ..b items by indices (inclusive) else: self.poutput(hi.pr()) - @with_argument_list def do_edit(self, arglist): """Edit a file or command in a text editor. @@ -1876,7 +1868,6 @@ Script should contain one command per line, just like command would be typed in self._script_dir.append(os.path.dirname(expanded_path)) - @staticmethod def is_text_file(file_path): """ diff --git a/docs/argument_processing.rst b/docs/argument_processing.rst index 69d0d7ce..cc08e4e5 100644 --- a/docs/argument_processing.rst +++ b/docs/argument_processing.rst @@ -58,25 +58,26 @@ Help Messages By default, cmd2 uses the docstring of the command method when a user asks for help on the command. When you use the ``@with_argument_parser`` -decorator, the formatted help from the ``argparse.ArgumentParser`` is -appended to the docstring for the method of that command. With this code:: +decorator, the docstring for the ``do_*`` method is used to set the description for the ``argparse.ArgumentParser`` is +With this code:: argparser = argparse.ArgumentParser() - argparser.add_argument('tag', nargs=1, help='tag') + argparser.add_argument('tag', help='tag') argparser.add_argument('content', nargs='+', help='content to surround with tag') @with_argument_parser(argparser) def do_tag(self, args): """create a html tag""" - self.stdout.write('<{0}>{1}</{0}>'.format(args.tag[0], ' '.join(args.content))) + self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content))) self.stdout.write('\n') The ``help tag`` command displays: .. code-block:: none - create a html tag usage: tag [-h] tag content [content ...] + create a html tag + positional arguments: tag tag content content to surround with tag @@ -85,14 +86,15 @@ The ``help tag`` command displays: -h, --help show this help message and exit -If you would prefer the short description of your command to come after the usage message, leave the docstring on your method empty, but supply a ``description`` variable to the argument parser:: +If you would prefer you can set the ``description`` while instantiating the ``argparse.ArgumentParser`` and leave the +docstring on your method empty:: argparser = argparse.ArgumentParser(description='create an html tag') - argparser.add_argument('tag', nargs=1, help='tag') + argparser.add_argument('tag', help='tag') argparser.add_argument('content', nargs='+', help='content to surround with tag') @with_argument_parser(argparser) def do_tag(self, args): - self.stdout.write('<{0}>{1}</{0}>'.format(args.tag[0], ' '.join(args.content))) + self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content))) self.stdout.write('\n') Now when the user enters ``help tag`` they see: @@ -117,11 +119,11 @@ To add additional text to the end of the generated help message, use the ``epilo description='create an html tag', epilog='This command can not generate tags with no content, like <br/>.' ) - argparser.add_argument('tag', nargs=1, help='tag') + argparser.add_argument('tag', help='tag') argparser.add_argument('content', nargs='+', help='content to surround with tag') @with_argument_parser(argparser) def do_tag(self, args): - self.stdout.write('<{0}>{1}</{0}>'.format(args.tag[0], ' '.join(args.content))) + self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content))) self.stdout.write('\n') Which yields: diff --git a/examples/argparse_example.py b/examples/argparse_example.py index ae45411c..9f6548de 100755 --- a/examples/argparse_example.py +++ b/examples/argparse_example.py @@ -64,14 +64,14 @@ class CmdLineApp(Cmd): do_say = do_speak # now "say" is a synonym for "speak" do_orate = do_speak # another synonym, but this one takes multi-line input - tag_parser = argparse.ArgumentParser(description='create a html tag') - tag_parser.add_argument('tag', nargs=1, help='tag') + tag_parser = argparse.ArgumentParser() + tag_parser.add_argument('tag', help='tag') tag_parser.add_argument('content', nargs='+', help='content to surround with tag') @with_argument_parser(tag_parser) def do_tag(self, args): """create a html tag""" - self.poutput('<{0}>{1}</{0}>'.format(args.tag[0], ' '.join(args.content))) + self.poutput('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content))) @with_argument_list diff --git a/examples/pirate.py b/examples/pirate.py index 55457e06..dd9fd98c 100755 --- a/examples/pirate.py +++ b/examples/pirate.py @@ -76,7 +76,7 @@ class Pirate(Cmd): yo_parser = argparse.ArgumentParser() yo_parser.add_argument('--ho', type=int, default=2, help="How often to chant 'ho'") yo_parser.add_argument('-c', '--commas', action='store_true', help='Intersperse commas') - yo_parser.add_argument('beverage', nargs=1, help='beverage to drink with the chant') + yo_parser.add_argument('beverage', help='beverage to drink with the chant') @with_argument_parser(yo_parser) def do_yo(self, args): @@ -84,7 +84,7 @@ class Pirate(Cmd): chant = ['yo'] + ['ho'] * args.ho separator = ', ' if args.commas else ' ' chant = separator.join(chant) - print('{0} and a bottle of {1}'.format(chant, args.beverage[0])) + print('{0} and a bottle of {1}'.format(chant, args.beverage)) if __name__ == '__main__': diff --git a/tests/conftest.py b/tests/conftest.py index 387322b1..021af193 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,7 +21,7 @@ edit help history load py pyscript quit set shell shortcuts # Help text for the history command HELP_HISTORY = """usage: history [-h] [-r | -e | -o FILE] [-s] [arg] -run, edit, and save previously entered commands +View, run, edit, and save previously entered commands. positional arguments: arg empty all history items diff --git a/tests/test_argparse.py b/tests/test_argparse.py index fea9bebb..21e81603 100644 --- a/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -37,12 +37,12 @@ class ArgparseApp(cmd2.Cmd): self.stdout.write('\n') tag_parser = argparse.ArgumentParser(description='create a html tag') - tag_parser.add_argument('tag', nargs=1, help='tag') + tag_parser.add_argument('tag', help='tag') tag_parser.add_argument('content', nargs='+', help='content to surround with tag') @cmd2.with_argument_parser(tag_parser) def do_tag(self, args): - self.stdout.write('<{0}>{1}</{0}>'.format(args.tag[0], ' '.join(args.content))) + self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content))) self.stdout.write('\n') @cmd2.with_argument_list @@ -140,10 +140,14 @@ def test_argparse_quoted_arguments_posix_multiple(argparse_app): def test_argparse_help_docstring(argparse_app): out = run_cmd(argparse_app, 'help say') - assert out[0] == 'Repeat what you tell me to.' + assert out[0].startswith('usage: say') + assert out[1] == '' + assert out[2] == 'Repeat what you tell me to.' def test_argparse_help_description(argparse_app): out = run_cmd(argparse_app, 'help tag') + assert out[0].startswith('usage: tag') + assert out[1] == '' assert out[2] == 'create a html tag' def test_argparse_prog(argparse_app): |