This is a pre-production deployment of Warehouse, however changes made here WILL affect the production instance of PyPI.
Latest Version Dependencies status unknown Test status unknown Test coverage unknown
Project Description

This package provides extensions to argparse on two levels:

  • basic argparse extensions: default subparser, subparser aliases in 2.X
  • additional actions that can be specified for add_argument
  • smart formatter that allows combination of defaults help formatting and raw desciptions
  • wrapper for argparse using decorators

Extensions to basic argparse

Insert the following to be able to specify aliases in 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 actions

CountAction

Count 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)

SplitAppend

Append 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'])

CheckSingleStoreAction

Complain 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 formatting

You 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.

The SmartFormatter is a subclass of argparse.HelpFormatter and 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 to all entries (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 argparse

When 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 the ProgramBase class that should be subclassed and the sub_parser, option and version decorators 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 exit

The method name is by default the name of the sub_parser. This can be overriden by providing a non-keyword argument to sub_parser. The keyword arguments are passed to the add_parser method.

The option functions as add_argument. If option is 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 an global_option=True keyword argument. This makes sure that option is added to all the sub_parsers as well. This allows you to invoke both prog --quiet writeit and prog writeit --quiet). You can assing these options to __init__, but when sub classing TestCmd this will lead to problems. It is therefore better to pu them on the special handled method _pb_init if subclassing might happen.

Care should be taken that all attributes on TestCmd are accessed during scanning for sub parsers. In particular any property method will be accessedi and its code executed.

Default command

In 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 called pass be the same:

pass
pass show

Help on all subcommands

If you provide a True value to the optional help_all parameter for self._parse_args():

self._parse_args(help_all=True)

then the commandline is checked for the option --help-all and the global help is printed, follow by the help for each sub parsers, separated by a dashed line.

Testing

Testing is done using the tox, which uses virtualenv and pytest.

Release History

Release History

0.6.0

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.2

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.1

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.4.2

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.4.1

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.3.2

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

TODO: Brief introduction on what you do with files - including link to relevant help section.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
ruamel.std.argparse-0.6.0-py2.py3-none-any.whl (17.9 kB) Copy SHA256 Checksum SHA256 py2.py3 Wheel Aug 27, 2015
ruamel.std.argparse-0.6.0.tar.gz (17.6 kB) Copy SHA256 Checksum SHA256 Source Aug 27, 2015

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS HPE HPE Development Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting