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.8
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)
- Set
_allow_extra_keys = True
in the class definition to allow unknown fields in the input
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
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
File details
Details for the file typedparser-0.21.1.tar.gz
.
File metadata
- Download URL: typedparser-0.21.1.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.15
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 081ad691400d6e516c3d85aff7427816bbb8220f8895390b72bc93d146a9ba91 |
|
MD5 | 685b3080877e0fc9b755b6b8a47968ae |
|
BLAKE2b-256 | 2f66b4a22382fa4a50babd72d9c6b36c8cafee0165aa3900a0a77ba9c7f6ea21 |
File details
Details for the file typedparser-0.21.1-py3-none-any.whl
.
File metadata
- Download URL: typedparser-0.21.1-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.15
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3316a6aa5e64e2cf205aac3a08b2dced2557208dc4ddc1be00da629325050487 |
|
MD5 | 427f300bb190fa9de2b20266d91ae164 |
|
BLAKE2b-256 | 2e78cdef5f3b1bac1db25b1195d5d4342c695146c90a76178c32ed08b32948ae |