Package: ruamel.std.argparse
This package provides extensions to argparse on two levels:basic argparse extensions: default subparser, subparser aliases in
2.Xadditional actions that can be specified for add_argumentsmart formatter that allows combination of defaults help formattingandraw desciptionswrapper for argparse using decoratorsExtensions to basic argparseInsert the following to be able to specifyaliasesin
subparser definitions in 2.6 and 2.7:from __future__ import print_function

import sys
from ruamel.std.argparse import ArgumentParser, SubParsersAction

parser = ArgumentParser()
if sys.version_info < (3,):  # add aliases support
    parser.register('action', 'parsers', SubParsersAction)
subparsers = parser.add_subparsers()
checkout = subparsers.add_parser('checkout', aliases=['co'])
checkout.add_argument('foo')
args = parser.parse_args(['co', 'bar'])
print(args)Resulting in:Namespace(foo='bar')Additional actionsCountActionCount up and down:from __future__ import print_function

from ruamel.std.argparse import CountAction
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action=CountAction, const=1, nargs=0)
parser.add_argument('--quiet', '-q', action=CountAction, dest='verbose',
                    const=-1, nargs=0)

print(parser.parse_args("--verbose -v -q".split()))results in:Namespace(verbose=1)SplitAppendAppend after splitting on “,”. Running:from __future__ import print_function

from ruamel.std.argparse import SplitAppendAction
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-d', action=SplitAppendAction)

print(parser.parse_args("-d ab -d cd -d kl -d mn".split()))
print(parser.parse_args("-d ab,cd,kl,mn".split()))
print(parser.parse_args("-d ab,cd -d kl,mn".split()))results in:Namespace(d=['ab', 'cd', 'kl', 'mn'])
Namespace(d=['ab', 'cd', 'kl', 'mn'])
Namespace(d=['ab', 'cd', 'kl', 'mn'])CheckSingleStoreActionComplain if the same option is called  multiple times:from __future__ import print_function

from ruamel.std.argparse import CheckSingleStoreAction
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--check', '-c', action=CheckSingleStoreAction, const=1,
                    nargs=0)

print(parser.parse_args("--check -c".split()))results in:WARNING: previous optional argument "-c []" overwritten by "-c []"
Namespace(check=[])Smart formattingYou can only specify one formatter in standard argparse, so you cannot
both have pre-formatted description. using
RawDescriptionHelpFormatter,as well as default arguments with
ArgumentDefaultsHelpFormatter.TheSmartFormatteris a subclass ofargparse.HelpFormatterand
has the normal formatter as default. Help text can be marked at the
beginning for variations in formatting:"R|.."format raw, i.e. don’t wrap and fill out, observer newline"*|.."format a password help, never echo password defaults"D|.."add defaults toallentries (that is why having*|is important)The version string is formatted using _split_lines and preserves any
line breaks in the version string.from __future__ import print_function

from ruamel.std.argparse import SmartFormatter
import argparse


def exit(self, *args, **kw):
    pass

argparse.ArgumentParser.exit = exit

# the 'D|....' in the second pass triggers generating defaults for all entries,
# while being smart about which one already have a %(default)s

for index, log_s in enumerate(['log to file', 'D|log to file']):
    parser = argparse.ArgumentParser(formatter_class=SmartFormatter)

    parser.add_argument('--log', default='abc.log', help=log_s)
    parser.add_argument('--username',
                        help='username to login with (default: %(default)s)')
    parser.add_argument('--password', help='*|password to use for login')
    parser.add_argument('--recursive', '-r', action='store_true',
                        help="R|recurse into subdirectories \nto find files")
    parser.set_defaults(username='anthon', password="test123")

    if index > 0:
        print('--------------------------------------\n')
    parser.parse_args(["--help"])results in:usage: smartformatter.py [-h] [--log LOG] [--username USERNAME]
                         [--password PASSWORD] [--recursive]

optional arguments:
  -h, --help           show this help message and exit
  --log LOG            log to file
  --username USERNAME  username to login with (default: anthon)
  --password PASSWORD  password to use for login
  --recursive, -r      recurse into subdirectories
                       to find files
--------------------------------------

usage: smartformatter.py [-h] [--log LOG] [--username USERNAME]
                         [--password PASSWORD] [--recursive]

optional arguments:
  -h, --help           show this help message and exit
  --log LOG            log to file (default: abc.log)
  --username USERNAME  username to login with (default: anthon)
  --password PASSWORD  password to use for login (default: *******)
  --recursive, -r      recurse into subdirectories
                       to find files (default: False)Wrapping argparseWhen using argparse with subparser, each of which have their own
function ( using.set_defaults(func=function) that can be called,
there is a lot of repetitive code.An alternative is provided by theProgramBaseclass that should be
subclassed and thesub_parser,optionandversiondecorators that can be applied to methods of that subclass.A typical use case is:from __future__ import print_function

import sys
import os

from ruamel.std.argparse import ProgramBase, option, sub_parser, version, \
    SmartFormatter


class TestCmd(ProgramBase):
    def __init__(self):
        super(TestCmd, self).__init__(
            formatter_class=SmartFormatter
        )

    # you can put these on __init__, but subclassing TestCmd
    # will cause that to break
    @option('--quiet', '-q', help='suppress verbosity', action='store_true',
            global_option=True)
    @version('version: 1.2.3')
    def _pb_init(self):
        # special name for which attribs are included in help
        pass

    def run(self):
        if self._args.func:
            return self._args.func()

    def parse_args(self, *args):
        self._parse_args(*args)

    @sub_parser(help='specific help for readit')
    @option('--name', default='abc')
    def readit(self):
        print('calling readit')

    @sub_parser('writeit', help='help for writeit')
    @option('--target')
    def other_name(self):
        print('calling writeit')


n = TestCmd()
n.parse_args(['--help'])
n.run()and output:usage: testcmd.py [-h] [--quiet] [--version] {readit,writeit} ...

positional arguments:
  {readit,writeit}
    readit          specific help for readit
    writeit         help for writeit

optional arguments:
  -h, --help        show this help message and exit
  --quiet, -q       suppress verbosity
  --version         show program's version number and exitThe method name is by default the name of the sub_parser. This can be
overriden by providing a non-keyword argument tosub_parser. The
keyword arguments are passed to theadd_parsermethod.Theoptionfunctions asadd_argument. Ifoptionis put on
a method that is not a sub_parser, such an option will be a global
option. These have to be specified before any sub_parser argument when
invoking the script. Often it is handy to specify such an option with
anglobal_option=Truekeyword argument. This makes sure that
option is added to all the sub_parsers as well. This allows you to
invoke bothprog--quietwriteitandprog writeit--quiet).
You can assing these options to__init__, but when sub classingTestCmdthis will lead to problems. It is therefore better to pu
them on the special handled method_pb_initif subclassing might
happen.Care should be taken that all attributes onTestCmdare accessed
during scanning for sub parsers. In particular any property method
will be accessedi and its code executed.Default commandIn case you want to have specific sub_parser be invoked as the default, you
can use:self._parse_args(default_sub_parser='show')to have the following invocations on the commandline of a program calledpassbe the same:pass
pass showHelp on all subcommandsIf you provide a True value to the optional help_all parameter forself._parse_args():self._parse_args(help_all=True)then the commandline is checked for the option--help-alland the global
help is printed, follow by the help for each sub parsers, separated by a dashed
line.TestingTesting is done using thetox, which
usesvirtualenvandpytest.