Skip to main content

Super-charged argparse for python

Project description

argx

pypi tag codacy quality codacy quality github action pyver

Supercharged argparse for Python

Installation

pip install -U argx

Features enhanced or added

Option exit_on_void

If all arguments are optional, argparse will not raise an error if no arguments are provided. This is not always desirable. argx provides the option exit_on_void to change this behavior. If exit_on_void is set to True and no arguments are provided, argx will exit with an error (No arguments provided).

import argx as argparse

parser = argparse.ArgumentParser(exit_on_void=True)
parser.add_argument('--foo', action='store_true')

args = parser.parse_args([])
# No arguments provided
# standard argparse produces: Namespace(foo=False)

Subcommand shortcut

argparse requires to create subparsers first and then add the subcommands to the subparsers. argx allows to add subcommands directly to the main parser.

# standard argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(title='subcommands')
parser_a = subparsers.add_parser('a')
parser_b = subparsers.add_parser('b')

# argx
parser = argparse.ArgumentParser()
parser.add_command('a')  # or parser.add_subparser('a')
parser.add_command('b')
# args = parser.parse_args(['a'])
# Namespace(COMMAND='a')

The subparsers is added automatically with the title subcommands and the dest is set to COMMAND. You can add subcommands to subcommands directly, then the dest is set to COMMAND2, COMMAND3, etc. If you want to change the behavior, you can always fall back to the standard argparse way.

Namespace arguments

The values of arguments like --foo.bar can be accessed as vars(args)['foo.bar']. With argx you can access them as args.foo.bar.

The arguments --foo.bar, --foo.baz and --foo.qux are automatically grouped in a namespace foo.

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo.bar', type=int)
parser.add_argument('--foo.baz', type=int)
parser.add_argument('--foo.qux', type=int)

parser.print_help()
Usage: test.py [-h] [--foo.bar BAR] [--foo.baz BAZ] [--foo.qux QUX]

Optional arguments:
  -h, --help            show this help message and exit

Namespace <foo>:
  --foo.bar BAR
  --foo.baz BAZ
  --foo.qux QUX

You can modify the namespace by adding the namespace manually before adding the arguments.

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_namespace('foo', title="Foo's options")
parser.add_argument('--foo.bar', type=int)
parser.add_argument('--foo.baz', type=int)
parser.add_argument('--foo.qux', type=int)

parser.print_help()
Usage: test.py [-h] [--foo.bar BAR] [--foo.baz BAZ] [--foo.qux QUX]

Optional Arguments:
  -h, --help            show this help message and exit

Foo's Options:
    --foo.bar BAR
    --foo.baz BAZ
    --foo.qux QUX

You can also add a namespace action argument to take a json that can be parsed as a dict:

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo', action="namespace") # or action="ns"
parser.add_argument('--foo.bar', type=int)
parser.add_argument('--foo.baz', type=int)
parser.add_argument('--foo.qux', type=int)

parser.parse_args(['--foo', '{"bar": 1, "baz": 2, "qux": 3}', '--foo.qux', '4'])
# Namespace(foo=Namespace(bar=1, baz=2, qux=4))

Brief help message for massive arguments

If you have a lot of arguments, the help message can be very long. argx allows to show only the most important arguments in the help message.

import argx as argparse

# Advanced help options to show the brief help message or the full help message
parser = argparse.ArgumentParser(add_help='+')
parser.add_argument('--foo', type=int)
parser.add_argument('--bar', type=int, show=False)
parser.parse_args(['--help'])
Usage: test.py [-h] [--foo FOO]

Optional Arguments:
  -h, --help, -h+, --help+
                        show help message (with + to show more options) and exit
  --foo FOO

With parser.parse_args(['--help+']) you can show the full help message.

Usage: test.py [-h] [--foo FOO] [--bar BAR]

Optional Arguments:
  -h, --help, -h+, --help+
                        show help message (with + to show more options) and exit
  --foo FOO
  --bar BAR

You can also set show=False for argument groups.

Default value in argument help

With argparse, the default value is not shown in the help message. With argx, the default value is added to the help message automatically.

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo', type=int, default=1)
parser.add_argument('--bar', type=int, default=2, help='bar [default: two]')
parser.add_argument('--baz', type=int, default=3, help='baz [nodefault]')
parser.print_help()
Usage: test.py [-h] [--foo FOO]

Optional Arguments:
  -h, --help            show help message and exit
  --foo FOO             [default: 1]
  --bar BAR             bar [default: two]
  --baz BAZ             baz

Newlines kept in help

By default, argparse replaces the newlines with spaces in the argument help message. However, sometimes you want to keep the newlines. With argx, if there is not newline, it is handled as the default behavior. If there is a newline, the newlines and spaces are kept.

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo', help='foo\n- bar\n  indent also kept')
parser.print_help()
Usage: test.py [-h] [--foo FOO]

Optional Arguments:
  -h, --help            show this help message and exit
  --foo FOO             foo
                        - bar
                          indent also kept

Defaults from files

With standard argparse, when fromfile_prefix_chars is set, the arguments can be read from a file. The file can be specified with @filename. The arguments in the file are separated by newlines by default.

With argx, Other than a text file to provide command line arguments, you can also provide other types of configuration files. The extension of the file can be .json, .yaml, .ini, .env or .toml.

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo', type=int)
parser.add_argument('--bar', type=int)
parser.add_argument('--baz', type=int)

# config.json
# { "foo": 1, "bar": 2, "baz": 3 }
args = parser.parse_args(['@config.json'])
# Namespace(foo=1, bar=2, baz=3)

You can also use set_defaults_from_configs method:

parser.set_defaults_from_configs('config.json')

Clear_append/extend action

The clear_append/clear_extend action is similar to append and extend, but the initial value is cleared.

This is useful when you want to accept a new list of values from the command line, instead of append/extend to the existing list or default.

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo', action='clear_append', default=[1, 2, 3], type=int)
parser.add_argument('--bar', action='append', default=[1, 2, 3], type=int)

args = parser.parse_args('--foo 4 --foo 5 --bar 4 --bar 5'.split())
# Namespace(foo=[4, 5], bar=[1, 2, 3, 4, 5])

Grouping required arguments by default

By default, argparse puts both required=True and required=False arguments in the same group (optional arguments), which is sometimes confusing. argx groups required=True arguments in a separate group (required arguments).

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo')
parser.add_argument('--bar', required=True)

parser.print_help()
Usage: test.py [-h] [--foo FOO] --bar BAR

Required Arguments:
  --bar BAR

Optional Arguments:
  -h, --help            show help message and exit
  --foo FOO

Order of groups in help message

Allow to add an order attribute to groups to change the order of groups in help message

import argx as argparse

parser = argparse.ArgumentParser()
group1 = parser.add_argument_group('group1', order=2)
group1.add_argument('--foo')
group2 = parser.add_argument_group('group2', order=1)
group2.add_argument('--bar')

parser.print_help()
Usage: test.py [-h] [--bar BAR] [--foo FOO]

Optional arguments:
  -h, --help            show help message and exit

Group2:
  --bar BAR

Group1:
  --foo FOO

The order by default is 0. The groups with the same order are sorted by title. Groups with small numbers are displayed first. required arguments has a order of -1.

Additional types

parser.add_argument() accepts type as a function to convert the argument value. It has to be a callable that accepts a single string argument and returns the converted value. While argx supports string for type so it can be configured in the configuration file. Builtin functions and types can also be specified by its name.

We also have additional types:

import argx as argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo', type='py')
parser.add_argument('--bar', type='json')
parser.add_argument('--baz', type='path')
parser.add_argument('--qux', type='auto')

args = parser.parse_args(
    '--foo 1 --bar {"a":1} --baz path/to/file --qux true'.split()
)
# Namespace(foo=1, bar={'a': 1}, baz=PosixPath('path/to/file'), qux=True)
  • py: Python expression. The string is evaluated by ast.literal_eval.
  • json: JSON string. The string is loaded by json.loads.
  • path: Path string. The string is converted by pathlib.Path.
  • auto: Automatic type conversion.
    • True if the string is True/TRUE/true
    • False if the string is False/FALSE/false
    • None if the string is None/NONE/none
    • An integer if the string can be converted to an integer
    • A float if the string can be converted to a float
    • A dict if the string is a JSON string
    • The string itself otherwise

Configuration file to create the parser

You can create the parser from a configuration file.

import argx as argparse

# config.json
# {
#   "prog": "myprog",
#   "arguments": [ {"flags": ["-a", "--abc"], "help": "Optiona a help"} ]
# }
parser = argparse.ArgumentParser.from_configs('config.json')
parser.print_help()
Usage: myprog [-h] [-a ABC]

Optional Arguments:
  -h, --help            show help message and exit
  -a ABC, --abc ABC     Optiona a help

Pre-parse hook

You can add a pre-parse hook to the parser. The hook is called before parsing the arguments. It can be used to modify the arguments before parsing.

import argx as argparse

def pre_parse(parser, args, namespace):
    """We can modify the parser (i.e. add arguments)
    the arguments to be parsed, and even manipulate the namespace.
    """
    parser.add_argument('--foo', type=int)
    parser.add_argument('--bar', type=int)
    namespace.baz = 2
    return args + ["--bar", "3"]

parser = argparse.ArgumentParser()
parser.add_command('command1', pre_parse=pre_parse)
parsed = parser.parse_args('command1 --foo 1'.split())
# Namespace(COMMAND='command1', baz=2, foo=1, bar=3)

This is especially useful when you have a lot of subcommands and each has a lot of arguments, when it takes time to add these arguments, for example, some of the values need to be parsed from a file. Using this hook, you can add the arguments only when the subcommand is called, instead of adding them all at the beginning.

Backward compatibility

All features are optional. You can use argx as a drop-in replacement for argparse.

argx supports python 3.7+. Some of the later-introduced features are also supported in python 3.7. For example, extend action is added in python 3.8, argx supports in python 3.7.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

argx-0.2.5.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

argx-0.2.5-py3-none-any.whl (15.2 kB view details)

Uploaded Python 3

File details

Details for the file argx-0.2.5.tar.gz.

File metadata

  • Download URL: argx-0.2.5.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.4.0 CPython/3.10.6 Linux/5.15.0-1033-azure

File hashes

Hashes for argx-0.2.5.tar.gz
Algorithm Hash digest
SHA256 b594d6eef0a77917113e32849e174c33dbb914edddb3589c539a1a693d226ed2
MD5 098485c5bd5507ebf8d88fe530fa83c0
BLAKE2b-256 94dcbc2a573b603ac3eb4b4937e1c123916b4964151914128701dbdfb6e00016

See more details on using hashes here.

File details

Details for the file argx-0.2.5-py3-none-any.whl.

File metadata

  • Download URL: argx-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 15.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.4.0 CPython/3.10.6 Linux/5.15.0-1033-azure

File hashes

Hashes for argx-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 a2e97ddf3d95ed79f27d38958ec7db4cc0585242fae9036aed0545594b566c3a
MD5 be88f5b56e5149913ae4125cf1da76da
BLAKE2b-256 aab5556f187c87992dd588fe8999fd1a7fa158f72b200bf6759b1647caa1948a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page