Skip to main content

A wrapper around the standard argparse module that allows you to describe argument parsers declaratively.

Project description

https://coveralls.io/repos/github/mosquito/argclass/badge.svg?branch=master Actions Latest Version https://img.shields.io/pypi/pyversions/argclass.svg https://img.shields.io/pypi/l/argclass.svg

A wrapper around the standard argparse module that allows you to describe argument parsers declaratively.

By default, the argparse module suggests creating parsers imperative, which is not convenient from the point of view of type checking and access to attributes, of course, IDE autocompletion and type hints not applicable in this case.

This module allows you to declare command-line parsers with classes.

Simple example:

import logging

import argclass


class CopyParser(argclass.Parser):
    recursive: bool
    preserve_attributes: bool


parser = CopyParser()
parser.parse_args(["--recursive", "--preserve-attributes"])
assert parser.recursive
assert parser.preserve_attributes

As you can see this example shown a basic module usage, when you want specify argument default and other options you have to use argclass.Argument.

Following example use argclass.Argument and argument groups:

import logging

import argclass


class AddressPortGroup(argclass.Group):
    address: str = argclass.Argument(default="127.0.0.1")
    port: int


class Parser(argclass.Parser):
    log_level: int = argclass.LogLevel
    http = AddressPortGroup(title="HTTP options", defaults=dict(port=8080))
    rpc = AddressPortGroup(title="RPC options", defaults=dict(port=9090))


parser = Parser(
    config_files=[".example.ini", "~/.example.ini", "/etc/example.ini"],
    auto_env_var_prefix="EXAMPLE_"
)
parser.parse_args([])

logging.basicConfig(level=parser.log_level)
logging.info('Listening http://%s:%d', parser.http.address, parser.http.port)
logging.info(f'Listening rpc://%s:%d', parser.rpc.address, parser.rpc.port)


assert parser.http.address == '127.0.0.1'
assert parser.rpc.address == '127.0.0.1'

assert parser.http.port == 8080
assert parser.rpc.port == 9090

Run this script:

$ python example.py
INFO:root:Listening http://127.0.0.1:8080
INFO:root:Listening rpc://127.0.0.1:9090

Example of --help output:

$ python example.py --help
usage: example.py [-h] [--log-level {debug,info,warning,error,critical}]
                 [--http-address HTTP_ADDRESS] [--http-port HTTP_PORT]
                 [--rpc-address RPC_ADDRESS] [--rpc-port RPC_PORT]

optional arguments:
  -h, --help            show this help message and exit
  --log-level {debug,info,warning,error,critical}
                        (default: info) [ENV: EXAMPLE_LOG_LEVEL]

HTTP options:
  --http-address HTTP_ADDRESS
                        (default: 127.0.0.1) [ENV: EXAMPLE_HTTP_ADDRESS]
  --http-port HTTP_PORT
                        (default: 8080) [ENV: EXAMPLE_HTTP_PORT]

RPC options:
  --rpc-address RPC_ADDRESS
                        (default: 127.0.0.1) [ENV: EXAMPLE_RPC_ADDRESS]
  --rpc-port RPC_PORT   (default: 9090) [ENV: EXAMPLE_RPC_PORT]

Default values will based on following configuration files ['example.ini',
'~/.example.ini', '/etc/example.ini']. Now 1 files has been applied
['example.ini']. The configuration files is INI-formatted files where
configuration groups is INI sections.
See more https://pypi-hypernode.com/project/argclass/#configs

Configs

The parser objects might be get default values from environment variables or one of passed configuration files.

class AddressPortGroup(argclass.Group):
    address: str = argclass.Argument(default="127.0.0.1")
    port: int


class Parser(argclass.Parser):
    spam: str
    quantity: int
    log_level: int = argclass.LogLevel
    http = AddressPortGroup(title="HTTP options")
    rpc = AddressPortGroup(title="RPC options")


# Trying to parse all passed configuration files
# and break after first success.
parser = Parser(
    config_files=[".example.ini", "~/.example.ini", "/etc/example.ini"],
)
parser.parse_args()

In this case each passed and existent configuration file will be opened.

The root level arguments might described in the [DEFAULT] section.

Other arguments might be described in group specific sections.

So the full example of config file for above example is:

[DEFAULT]
log_level=info
spam=egg
quantity=100

[http]
address=127.0.0.1
port=8080

[rpc]
address=127.0.0.1
port=9090

Subparsers

Complex example with subparsers:

import logging
from functools import singledispatch
from pathlib import Path
from typing import Optional, Any

import argclass


class AddressPortGroup(argclass.Group):
    address: str = argclass.Argument(default="127.0.0.1")
    port: int


class CommitCommand(argclass.Parser):
    comment: str = argclass.Argument()


class PushCommand(argclass.Parser):
    comment: str = argclass.Argument()


class Parser(argclass.Parser):
    log_level: int = argclass.LogLevel
    endpoint = AddressPortGroup(
        title="Endpoint options",
        defaults=dict(port=8080)
    )
    commit: Optional[CommitCommand] = CommitCommand()
    push: Optional[PushCommand] = PushCommand()


@singledispatch
def handle_subparser(subparser: Any) -> None:
    raise NotImplementedError(
        f"Unexpected subparser type {subparser.__class__!r}"
    )


@handle_subparser.register(type(None))
def handle_commit(_: None) -> None:
    pass


@handle_subparser.register(CommitCommand)
def handle_commit(subparser: CommitCommand) -> None:
    pass


@handle_subparser.register(PushCommand)
def handle_commit(subparser: PushCommand) -> None:
    pass


parser = Parser(
    config_files=["example.ini", "~/.example.ini", "/etc/example.ini"],
    auto_env_var_prefix="EXAMPLE_"
)
parser.parse_args()
handle_subparser(parser.current_subparser)

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

argclass-0.5.1.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

argclass-0.5.1-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file argclass-0.5.1.tar.gz.

File metadata

  • Download URL: argclass-0.5.1.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.11.0 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.10.2

File hashes

Hashes for argclass-0.5.1.tar.gz
Algorithm Hash digest
SHA256 ebd8e6c528cae041f57489e4c1862aa8d856a9b8f2147909e86944a605c5e1f5
MD5 9f76faa00aa4357b43383c3c8d9a153d
BLAKE2b-256 5e779c372ca7b5a1d6872317010207a4d30d651ba256a70f36c3ee56c156cae1

See more details on using hashes here.

File details

Details for the file argclass-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: argclass-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 12.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.11.0 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.10.2

File hashes

Hashes for argclass-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3a0be4bc9543887ac05fa1605202a4a06fec84c121fbc64ae1bd8337f097699c
MD5 7fd3895eac556838590ae67eaf865c93
BLAKE2b-256 16cd939ae00fa22715a330ba56819000a20ce529c3b4183d52fba9cdd3818285

See more details on using hashes here.

Supported by

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