Declarative `ArgumentParser` definition with `dataclass` notation.
Project description
classparse
Declarative ArgumentParser
definition with dataclass
notation.
- No
ArgumentParser
boilerplate 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:
Enum
supportarg/pos_arg/no_arg
functionality- Implicit positional argument
nargs
support
lebrice/simple-parsing
- Allow adding dataclass to
ArgumentParser
by usingparser.add_arguments()
- Requires boilerplate code to create the parser
- Positional arguments
nargs
support
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
classparse-0.1.4.tar.gz
(17.5 kB
view details)
Built Distribution
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 |