Declarative `ArgumentParser` definition with `dataclass` notation.
Project description
classparse
Declarative ArgumentParser definition with dataclass notation.
- No
ArgumentParserboilerplate code - IDE autocompletion and type hints
Install
pip install classparse==0.1.4
Simple Example
This is a simple example of the most basic usage of this library.
# examples/simple.py
from dataclasses import dataclass
from classparse import classparser
@classparser
@dataclass
class SimpleArgs:
"""My simple program's arguments"""
retries: int = 5 # number of retries
eps: float = 1e-3 # epsilon
if __name__ == "__main__":
print(SimpleArgs.parse_args())
$ python examples/simple.py --help
usage: simple.py [-h] [--retries RETRIES] [--eps EPS]
My simple program's arguments
options:
-h, --help show this help message and exit
--retries RETRIES number of retries
--eps EPS epsilon
$ python examples/simple.py --retries 10 --eps 1e-6
SimpleArgs(retries=10, eps=1e-06)
Exhaustive Usage Example
This example demonstrates all the usage scenarios of this library.
# examples/usage.py
import dataclasses
from dataclasses import dataclass
from enum import Enum, auto
from pathlib import Path
from typing import List, Literal, Optional, Tuple, Union
from classparse import arg, classparser, no_arg, pos_arg, to_arg_name, to_var_name
class Action(Enum):
Initialize = "init"
Execute = "exec"
class Animal(Enum):
Cat = auto()
Dog = auto()
@classparser(
prog="my_program.py", # Keyword arguments are passed to the parser init.
default_argument_args=dict(help="(type: %(type)s)"), # Set default arguments for each call of add_argument().
)
@dataclass(frozen=True)
class AllOptions:
"""
Class doc string ==> parser description.
The fields' inline/above comment ==> argument's help.
"""
pos_arg_1: str # Field with no explicit default ==> positional arguments (default=%(default)s)
pos_arg_2: int = pos_arg(
5,
nargs="?",
help=(
"pos_arg() is a wrapper around dataclasses.field()."
"The first argument (optional) is the argument default (default=%(default)s)."
"The following keyword arguments can be any argparse.add_argument() parameter."
),
) # When the help field is specified explicitly, the inline comment is ignored
int_arg: int = 1 # Field's type and default are applied to the parser (type=%(type)s, default=%(default)s)
str_enum_choice_arg: Action = Action.Initialize # StrEnum ==> choice argument (type=%(type)s, default=%(default)s)
int_enum_choice_arg: Animal = Animal.Cat # IntEnum ==> choice argument (type=%(type)s, default=%(default)s)
literal_arg: Literal["a", "b", "c"] = None # Literal ==> choice argument (type=%(type)s, default=%(default)s)
literal_int_arg: Literal[1, 2, 3] = None # Literal's type is automatically inferred (type=%(type)s)
mixed_literal: Literal[1, 2, "3", "4", True, Animal.Cat] = None # We can mix multiple literal types (type=%(type)s)
optional_arg: Optional[int] = None # Optional can be used for type hinting (type=%(type)s)
just_optional_arg: Optional = None # Bare optional also works (type=%(type)s)
optional_choice_arg: Optional[Action] = None # Nested types are supported (type=%(type)s)
union_arg: Union[int, float, bool] = None # Tries to convert to type in order until first success (type=%(type)s)
path_arg: Path = None
flag_arg: int = arg(
"-f",
help=(
"arg() is a wrapper around dataclasses.field()."
"The first argument (optional) is the short argument name."
"The following keyword arguments can be any argparse.add_argument() parameter."
),
default=1,
)
required_arg: float = arg("-r", required=True) # E.g., required=%(required)s
metavar_arg: str = arg(metavar="M") # E.g., metavar=%(metavar)s
int_list: List[int] = (1,) # List type hint ==> nargs="+" (type=%(type)s)
int_2_list: Tuple[int, int] = (1, 2) # Tuple type hint ==> nargs=<tuple length> (nargs=%(nargs)s, type=%(type)s)
multi_type_tuple: Tuple[int, float, str] = (1, 1e-3, "a") # We can use multiple types (type=%(type)s)
actions: List[Action] = () # List[Enum] ==> choices with nargs="+" (nargs=%(nargs)s, type=%(type)s)
animals: List[Animal] = () # List[Enum] ==> choices with nargs="+" (nargs=%(nargs)s, type=%(type)s)
literal_list: List[Literal["aa", "bb", 11, 22, Animal.Cat]] = ("aa",) # List[Literal] ==> choices with nargs="+"
union_list: List[Union[int, float, str, bool]] = ()
union_with_literal: List[Union[Literal["a", "b", 1, 2], float, bool]] = ()
typeless_list: list = () # If list type is unspecified, then it uses argparse default (type=%(type)s)
typeless_typing_list: List = () # typing.List or list are supported
none_bool_arg: bool = None # boolean args ==> argparse.BooleanOptionalAction (type=%(type)s)
true_bool_arg: bool = True # We can set any default value
false_bool_arg: bool = False
complex_arg: complex = complex(1, -1)
# no_arg() is used to not include this argument in the parser.
# The first argument (optional) sets the default value.
# The following keyword arguments is forwarded to the dataclasses.field() method.
no_arg: int = no_arg(0)
# We used this argument for the README example.
# Note that comments above the arg are also included in the help of the argument.
# This is a convenient way to include long help messages.
show: List[str] = arg("-s", default=())
def __repr__(self):
"""Print only the specified fields"""
fields = self.show or list(dataclasses.asdict(self))
return "\n".join([f"{to_arg_name(k)}: {getattr(self, to_var_name(k))}" for k in fields])
if __name__ == "__main__":
print(AllOptions.parse_args())
$ python examples/usage.py --help
usage: my_program.py [-h] [--int-arg INT_ARG]
[--str-enum-choice-arg {Initialize/init,Execute/exec}]
[--int-enum-choice-arg {Cat/1,Dog/2}]
[--literal-arg {a,b,c}] [--literal-int-arg {1,2,3}]
[--mixed-literal {1,2,3,4,True,Cat/1}]
[--optional-arg OPTIONAL_ARG]
[--just-optional-arg JUST_OPTIONAL_ARG]
[--optional-choice-arg {Initialize/init,Execute/exec}]
[--union-arg UNION_ARG] [--path-arg PATH_ARG]
[-f FLAG_ARG] -r REQUIRED_ARG [--metavar-arg M]
[--int-list INT_LIST [INT_LIST ...]]
[--int-2-list INT_2_LIST INT_2_LIST]
[--multi-type-tuple MULTI_TYPE_TUPLE MULTI_TYPE_TUPLE MULTI_TYPE_TUPLE]
[--actions {Initialize/init,Execute/exec} [{Initialize/init,Execute/exec} ...]]
[--animals {Cat/1,Dog/2} [{Cat/1,Dog/2} ...]]
[--literal-list {aa,bb,11,22,Cat/1} [{aa,bb,11,22,Cat/1} ...]]
[--union-list UNION_LIST [UNION_LIST ...]]
[--union-with-literal UNION_WITH_LITERAL [UNION_WITH_LITERAL ...]]
[--typeless-list TYPELESS_LIST [TYPELESS_LIST ...]]
[--typeless-typing-list TYPELESS_TYPING_LIST [TYPELESS_TYPING_LIST ...]]
[--none-bool-arg | --no-none-bool-arg]
[--true-bool-arg | --no-true-bool-arg]
[--false-bool-arg | --no-false-bool-arg]
[--complex-arg COMPLEX_ARG] [-s SHOW [SHOW ...]]
pos-arg-1 [pos-arg-2]
Class doc string ==> parser description. The fields' inline/above comment ==>
argument's help.
positional arguments:
pos-arg-1 Field with no explicit default ==> positional
arguments (default=None)
pos-arg-2 pos_arg() is a wrapper around dataclasses.field().The
first argument (optional) is the argument default
(default=5).The following keyword arguments can be any
argparse.add_argument() parameter.
options:
-h, --help show this help message and exit
--int-arg INT_ARG Field's type and default are applied to the parser
(type=int, default=1)
--str-enum-choice-arg {Initialize/init,Execute/exec}
StrEnum ==> choice argument (type=Action,
default=Initialize)
--int-enum-choice-arg {Cat/1,Dog/2}
IntEnum ==> choice argument (type=Animal, default=Cat)
--literal-arg {a,b,c}
Literal ==> choice argument (type=str, default=None)
--literal-int-arg {1,2,3}
Literal's type is automatically inferred (type=int)
--mixed-literal {1,2,3,4,True,Cat/1}
We can mix multiple literal types
(type=typing.Literal[1, 2, '3', '4', True,
<Animal.Cat: 1>])
--optional-arg OPTIONAL_ARG
Optional can be used for type hinting (type=int)
--just-optional-arg JUST_OPTIONAL_ARG
Bare optional also works (type=None)
--optional-choice-arg {Initialize/init,Execute/exec}
Nested types are supported (type=Action)
--union-arg UNION_ARG
Tries to convert to type in order until first success
(type=typing.Union[int, float, bool])
--path-arg PATH_ARG (type: Path)
-f FLAG_ARG, --flag-arg FLAG_ARG
arg() is a wrapper around dataclasses.field().The
first argument (optional) is the short argument
name.The following keyword arguments can be any
argparse.add_argument() parameter.
-r REQUIRED_ARG, --required-arg REQUIRED_ARG
E.g., required=True
--metavar-arg M E.g., metavar=M
--int-list INT_LIST [INT_LIST ...]
List type hint ==> nargs="+" (type=int)
--int-2-list INT_2_LIST INT_2_LIST
Tuple type hint ==> nargs=<tuple length> (nargs=2,
type=int)
--multi-type-tuple MULTI_TYPE_TUPLE MULTI_TYPE_TUPLE MULTI_TYPE_TUPLE
We can use multiple types (type=typing.Union[int,
float, str])
--actions {Initialize/init,Execute/exec} [{Initialize/init,Execute/exec} ...]
List[Enum] ==> choices with nargs="+" (nargs=+,
type=Action)
--animals {Cat/1,Dog/2} [{Cat/1,Dog/2} ...]
List[Enum] ==> choices with nargs="+" (nargs=+,
type=Animal)
--literal-list {aa,bb,11,22,Cat/1} [{aa,bb,11,22,Cat/1} ...]
List[Literal] ==> choices with nargs="+"
--union-list UNION_LIST [UNION_LIST ...]
(type: typing.Union[int, float, str, bool])
--union-with-literal UNION_WITH_LITERAL [UNION_WITH_LITERAL ...]
(type: typing.Union[typing.Literal['a', 'b', 1, 2],
float, bool])
--typeless-list TYPELESS_LIST [TYPELESS_LIST ...]
If list type is unspecified, then it uses argparse
default (type=None)
--typeless-typing-list TYPELESS_TYPING_LIST [TYPELESS_TYPING_LIST ...]
typing.List or list are supported
--none-bool-arg, --no-none-bool-arg
boolean args ==> argparse.BooleanOptionalAction
(type=bool)
--true-bool-arg, --no-true-bool-arg
We can set any default value (default: True)
--false-bool-arg, --no-false-bool-arg
(type: bool) (default: False)
--complex-arg COMPLEX_ARG
(type: complex)
-s SHOW [SHOW ...], --show SHOW [SHOW ...]
We used this argument for the README example. Note
that comments above the arg are also included in the
help of the argument. This is a convenient way to
include long help messages.
Note that for Enums, we can use either the enum name or its value.
$ python examples/usage.py str-choices --actions Initialize init Execute exec -r1 -s actions
actions: [<Action.Initialize: 'init'>, <Action.Initialize: 'init'>, <Action.Execute: 'exec'>, <Action.Execute: 'exec'>]
$ python examples/usage.py int-choices --animals Cat 1 Dog 2 -r1 -s animals
animals: [<Animal.Cat: 1>, <Animal.Cat: 1>, <Animal.Dog: 2>, <Animal.Dog: 2>]
Alternatives
mivade/argparse_dataclass
- Allow transforming dataclass to
ArgumentParser. - Missing features:
Enumsupportarg/pos_arg/no_argfunctionality- Implicit positional argument
nargssupport
lebrice/simple-parsing
- Allow adding dataclass to
ArgumentParserby usingparser.add_arguments() - Requires boilerplate code to create the parser
- Positional arguments
nargssupport
swansonk14/typed-argument-parser
- Creating argument parser from classes and functions
- Rich functionality
- Post-processing of arguments
- Save/load arguments
- Load from dict
License
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file classparse-0.1.4.tar.gz.
File metadata
- Download URL: classparse-0.1.4.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f4f93a35ae5f01aa797c14c34ec27f1832df4603ae9303fa3851c431412d2d8
|
|
| MD5 |
d2d790f86c2531495af721aa808786b0
|
|
| BLAKE2b-256 |
d337cce3269c3d65569f962fbabc3bfe5d678fcd0daa43b788220dae910cb930
|
File details
Details for the file classparse-0.1.4-py3-none-any.whl.
File metadata
- Download URL: classparse-0.1.4-py3-none-any.whl
- Upload date:
- Size: 15.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c08a64c6c0f19f46805c2ab90a30af6ab5cb5fc11b6c6e3c8173e968c2b145a
|
|
| MD5 |
54ef2121d7c93bd78ef416ce11bb6c63
|
|
| BLAKE2b-256 |
6f7215cd8467e5f058e979e42ac4e556fda263b1b98607e8fc681c354f23738b
|