Extension for python argparse with typehints and typechecks.
Project description
typedparser
Typing extension for python argparse using attrs.
Includes typechecking and conversion utilities to parse a dictionary into an attrs instance.
Install
Requires python>=3.7
pip install typedparser
Basic usage
- Create an attrs class (decorate with
@attr.define
). Note that optional arguments must also be typed as optional. - Define and type the fields with
typedparser.add_argument
- the syntax extends add_argument from argparse. - Parse the args with
TypedParser
and enjoy args with type hints. Disable typechecking by settingstrict=False
.
from typing import Optional
from attrs import define
from typedparser import add_argument, TypedParser
@define
class Args:
# omit the argument name to have it inferred from the field name
foo: str = add_argument(positional=True)
bar: int = add_argument(shortcut="-b", type=int, default=0)
opt: Optional[str] = add_argument()
# # in case you prefer the regular argparse syntax:
# foo: str = add_argument("foo")
# bar: int = add_argument("-b", "--bar", type=int, default=0)
# opt: Optional[str] = add_argument("--opt")
def main():
parser = TypedParser.create_parser(Args, strict=True)
args: Args = parser.parse_args()
print(args)
if __name__ == "__main__":
main()
Features
- Create commandline arguments with type hints and checks while staying close to the syntax of the standard library's argparse.
- Utilities for typechecking and converting nested objects:
- Nested checking and conversion of python standard types
- Supports old and new style typing (e.g.
typing.List
andlist
) - Supports positional and keyword arguments in classes
- Can also typecheck existing attrs instances
- Allows custom conversions, by default converts source type
str
to target typePath
andint
tofloat
- Allows to redefine which objects will be recursed into, by default recurses into standard containers (list, dict, etc.)
@definenumpy
decorator for equality check if the instances contains numpy arrays
- Some object utilities in
typedparser.objects
required for everything else
Advanced usage
- Use
TypedParser.from_parser(parser, Args)
to add typing to an existing parser. This is useful to cover usecases like subparsers or argument groups. - Snippet for argument lists
xarg: List[int] = add_argument(shortcut="-x", type=int, action="append", help="Xarg", default=[])
, use as-x 1 -x 2
to get[1, 2]
in the args instance.
Usage of attr utilities
Define the class hierarchy and parse the input using attrs_from_dict
.
Use @define(slots=False)
to allow multiple inheritance and setting attributes later.
from attrs import define
from typing import Optional
from typedparser import attrs_from_dict
@define
class Cfg:
foo: int = 12
bar: Optional[int] = None
print(attrs_from_dict(Cfg, {"foo": 1, "bar": 2}))
# Cfg(foo=1, bar=2)
@define
class CfgNested:
sub_cfg: Cfg = None
print(attrs_from_dict(CfgNested, {"sub_cfg": {"foo": 1, "bar": 2}}))
# CfgNested(sub_cfg=Cfg(foo=1, bar=2))
Strict mode (default)
- Convert everything to the target type, e.g. if the input is a list and the annotation is a tuple, the output will be a tuple
- Raise errors if types cannot be matched, there are unknown fields in the input or abstract annotation types are used (e.g. Sequence)
Non-strict mode
Enabled by calling attrs_from_dict
with strict=False
- No conversion except for creating the attrs instance from the dict
- Ignore silently if types cannot be matched or abstract annotation types are used
- Unknown fields in the input will be added to the attrs instance if possible (see the hint below about slots)
Skip unknowns
Set skip_unknowns=True
to ignore all unknown input fields.
Hints
The following behaviour stems from the attrs
package:
- New attributes cannot to be added after class definition to an attrs instance,
unless it is created with
@define(slots=False)
Explanation - Untyped fields or "ClassVar" typed fields will be ignored by @attrs.define and therefore also by this library.
Install locally and run tests
Clone repository and cd into. Setup python 3.7 or higher. Note: Some tests are skipped for python 3.7.
pip install -e .
pip install pytest pytest-cov pylint pytest-lazy-fixture
pylint typedparser
# run tests
python -m pytest --cov
pylint tests
Project details
Release history Release notifications | RSS feed
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
Hashes for typedparser-0.10.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 61c0c4c4ef158dc1636274bce29b3b81c44c33f3289a14f1baa35226461d4311 |
|
MD5 | 138617688ade4128342c76196ea396b7 |
|
BLAKE2b-256 | b02abe07a03000420d46c26423e901d25cf7eed1d5d4eb584b9d0b58df7c3813 |