diff options
| author | kotfu <kotfu@kotfu.net> | 2019-07-02 19:02:36 -0600 |
|---|---|---|
| committer | kotfu <kotfu@kotfu.net> | 2019-07-02 19:02:36 -0600 |
| commit | 92ae130c38520b249eb7351cfb0da1ad67d3d3cf (patch) | |
| tree | a403641a1a9412b19e26b52fae83635d812f9409 /docs/argument_processing.rst | |
| parent | 80950bfa4216ed20df5d63f1ebe63bac5b3746b4 (diff) | |
| download | cmd2-git-92ae130c38520b249eb7351cfb0da1ad67d3d3cf.tar.gz | |
Major overhaul of documentation structure for #709
Diffstat (limited to 'docs/argument_processing.rst')
| -rw-r--r-- | docs/argument_processing.rst | 314 |
1 files changed, 0 insertions, 314 deletions
diff --git a/docs/argument_processing.rst b/docs/argument_processing.rst deleted file mode 100644 index a1fc107b..00000000 --- a/docs/argument_processing.rst +++ /dev/null @@ -1,314 +0,0 @@ -.. _decorators: - -=================== -Argument Processing -=================== - -``cmd2`` makes it easy to add sophisticated argument processing to your commands using the ``argparse`` python module. -``cmd2`` handles the following for you: - -1. Parsing input and quoted strings like the Unix shell -2. Parse the resulting argument list using an instance of ``argparse.ArgumentParser`` that you provide -3. Passes the resulting ``argparse.Namespace`` object to your command function. The ``Namespace`` includes the - ``Statement`` object that was created when parsing the command line. It is stored in the ``__statement__`` - attribute of the ``Namespace``. -4. Adds the usage message from the argument parser to your command. -5. Checks if the ``-h/--help`` option is present, and if so, display the help message for the command - -These features are all provided by the ``@with_argparser`` decorator which is importable from ``cmd2``. - -See the either the argprint_ or decorator_ example to learn more about how to use the various ``cmd2`` argument -processing decorators in your ``cmd2`` applications. - -.. _argprint: https://github.com/python-cmd2/cmd2/blob/master/examples/arg_print.py -.. _decorator: https://github.com/python-cmd2/cmd2/blob/master/examples/decorator_example.py - - -Decorators provided by cmd2 for argument processing -=================================================== -``cmd2`` provides the following decorators for assisting with parsing arguments passed to commands: - -.. automethod:: cmd2.cmd2.with_argument_list -.. automethod:: cmd2.cmd2.with_argparser -.. automethod:: cmd2.cmd2.with_argparser_and_unknown_args - -All of these decorators accept an optional **preserve_quotes** argument which defaults to ``False``. -Setting this argument to ``True`` is useful for cases where you are passing the arguments to another -command which might have its own argument parsing. - - -Using the argument parser decorator -=================================== - -For each command in the ``cmd2`` subclass which requires argument parsing, -create a unique instance of ``argparse.ArgumentParser()`` which can parse the -input appropriately for the command. Then decorate the command method with -the ``@with_argparser`` decorator, passing the argument parser as the -first parameter to the decorator. This changes the second argument to the command method, which will contain the results -of ``ArgumentParser.parse_args()``. - -Here's what it looks like:: - - import argparse - from cmd2 import with_argparser - - argparser = argparse.ArgumentParser() - argparser.add_argument('-p', '--piglatin', action='store_true', help='atinLay') - argparser.add_argument('-s', '--shout', action='store_true', help='N00B EMULATION MODE') - argparser.add_argument('-r', '--repeat', type=int, help='output [n] times') - argparser.add_argument('word', nargs='?', help='word to say') - - @with_argparser(argparser) - def do_speak(self, opts) - """Repeats what you tell me to.""" - arg = opts.word - if opts.piglatin: - arg = '%s%say' % (arg[1:], arg[0]) - if opts.shout: - arg = arg.upper() - repetitions = opts.repeat or 1 - for i in range(min(repetitions, self.maxrepeats)): - self.poutput(arg) - -.. warning:: - - It is important that each command which uses the ``@with_argparser`` decorator be passed a unique instance of a - parser. This limitation is due to bugs in CPython prior to Python 3.7 which make it impossible to make a deep copy - of an instance of a ``argparse.ArgumentParser``. - - See the table_display_ example for a work-around that demonstrates how to create a function which returns a unique - instance of the parser you want. - - -.. note:: - - The ``@with_argparser`` decorator sets the ``prog`` variable in - the argument parser based on the name of the method it is decorating. - This will override anything you specify in ``prog`` variable when - creating the argument parser. - -.. _table_display: https://github.com/python-cmd2/cmd2/blob/master/examples/table_display.py - - -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_argparser`` -decorator, the docstring for the ``do_*`` method is used to set the description for the ``argparse.ArgumentParser``. - -With this code:: - - import argparse - from cmd2 import with_argparser - - argparser = argparse.ArgumentParser() - argparser.add_argument('tag', help='tag') - argparser.add_argument('content', nargs='+', help='content to surround with tag') - @with_argparser(argparser) - def do_tag(self, args): - """create a html tag""" - self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content))) - self.stdout.write('\n') - -the ``help tag`` command displays: - -.. code-block:: none - - usage: tag [-h] tag content [content ...] - - create a html tag - - positional arguments: - tag tag - content content to surround with tag - - optional arguments: - -h, --help show this help message and exit - - -If you would prefer you can set the ``description`` while instantiating the ``argparse.ArgumentParser`` and leave the -docstring on your method empty:: - - import argparse - from cmd2 import with_argparser - - argparser = argparse.ArgumentParser(description='create an html tag') - argparser.add_argument('tag', help='tag') - argparser.add_argument('content', nargs='+', help='content to surround with tag') - @with_argparser(argparser) - def do_tag(self, args): - 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: - -.. code-block:: none - - usage: tag [-h] tag content [content ...] - - create an html tag - - positional arguments: - tag tag - content content to surround with tag - - optional arguments: - -h, --help show this help message and exit - - -To add additional text to the end of the generated help message, use the ``epilog`` variable:: - - import argparse - from cmd2 import with_argparser - - argparser = argparse.ArgumentParser(description='create an html tag', - epilog='This command can not generate tags with no content, like <br/>.') - argparser.add_argument('tag', help='tag') - argparser.add_argument('content', nargs='+', help='content to surround with tag') - @with_argparser(argparser) - def do_tag(self, args): - self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content))) - self.stdout.write('\n') - -Which yields: - -.. code-block:: none - - usage: tag [-h] tag content [content ...] - - create an html tag - - positional arguments: - tag tag - content content to surround with tag - - optional arguments: - -h, --help show this help message and exit - - This command can not generate tags with no content, like <br/> - -.. warning:: - - If a command **foo** is decorated with one of cmd2's argparse decorators, then **help_foo** will not - be invoked when ``help foo`` is called. The argparse_ module provides a rich API which can be used to - tweak every aspect of the displayed help and we encourage ``cmd2`` developers to utilize that. - -.. _argparse: https://docs.python.org/3/library/argparse.html - - -Receiving an argument list -========================== - -The default behavior of ``cmd2`` is to pass the user input directly to your -``do_*`` methods as a string. The object passed to your method is actually a -``Statement`` object, which has additional attributes that may be helpful, -including ``arg_list`` and ``argv``:: - - class CmdLineApp(cmd2.Cmd): - """ Example cmd2 application. """ - - def do_say(self, statement): - # statement contains a string - self.poutput(statement) - - def do_speak(self, statement): - # statement also has a list of arguments - # quoted arguments remain quoted - for arg in statement.arg_list: - self.poutput(arg) - - def do_articulate(self, statement): - # statement.argv contains the command - # and the arguments, which have had quotes - # stripped - for arg in statement.argv: - self.poutput(arg) - - -If you don't want to access the additional attributes on the string passed to -you``do_*`` method you can still have ``cmd2`` apply shell parsing rules to the -user input and pass you a list of arguments instead of a string. Apply the -``@with_argument_list`` decorator to those methods that should receive an -argument list instead of a string:: - - from cmd2 import with_argument_list - - class CmdLineApp(cmd2.Cmd): - """ Example cmd2 application. """ - - def do_say(self, cmdline): - # cmdline contains a string - pass - - @with_argument_list - def do_speak(self, arglist): - # arglist contains a list of arguments - pass - - -Using the argument parser decorator and also receiving a list of unknown positional arguments -=============================================================================================== -If you want all unknown arguments to be passed to your command as a list of strings, then -decorate the command method with the ``@with_argparser_and_unknown_args`` decorator. - -Here's what it looks like:: - - import argparse - from cmd2 import with_argparser_and_unknown_args - - dir_parser = argparse.ArgumentParser() - dir_parser.add_argument('-l', '--long', action='store_true', help="display in long format with one item per line") - - @with_argparser_and_unknown_args(dir_parser) - def do_dir(self, args, unknown): - """List contents of current directory.""" - # No arguments for this command - if unknown: - self.perror("dir does not take any positional arguments:") - self.do_help('dir') - self.last_result = CommandResult('', 'Bad arguments') - return - - # Get the contents as a list - contents = os.listdir(self.cwd) - - ... - -Using custom argparse.Namespace with argument parser decorators -=============================================================================================== -In some cases, it may be necessary to write custom ``argparse`` code that is dependent on state data of your -application. To support this ability while still allowing use of the decorators, both ``@with_argparser`` and -``@with_argparser_and_unknown_args`` have an optional argument called ``ns_provider``. - -``ns_provider`` is a Callable that accepts a ``cmd2.Cmd`` object as an argument and returns an ``argparse.Namespace``:: - - Callable[[cmd2.Cmd], argparse.Namespace] - -For example:: - - def settings_ns_provider(self) -> argparse.Namespace: - """Populate an argparse Namespace with current settings""" - ns = argparse.Namespace() - ns.app_settings = self.settings - return ns - -To use this function with the argparse decorators, do the following:: - - @with_argparser(my_parser, ns_provider=settings_ns_provider) - -The Namespace is passed by the decorators to the ``argparse`` parsing functions which gives your custom code access -to the state data it needs for its parsing logic. - -Sub-commands -============ -Sub-commands are supported for commands using either the ``@with_argparser`` or -``@with_argparser_and_unknown_args`` decorator. The syntax for supporting them is based on argparse sub-parsers. - -You may add multiple layers of sub-commands for your command. Cmd2 will automatically traverse and tab-complete -sub-commands for all commands using argparse. - -See the subcommands_ and tab_autocompletion_ example to learn more about how to use sub-commands in your ``cmd2`` application. - -.. _subcommands: https://github.com/python-cmd2/cmd2/blob/master/examples/subcommands.py -.. _tab_autocompletion: https://github.com/python-cmd2/cmd2/blob/master/examples/tab_autocompletion.py |
