Package: typedparser
typedparserTyping extension for python argparse usingattrs.Includes typechecking and conversion utilities to parse a dictionary into an attrs instance.InstallRequirespython>=3.7pipinstalltypedparserBasic usageCreate an attrs class (decorate with@attr.define). Note that optional arguments must also be typed as optional.Define and type the fields withtypedparser.add_argument- the syntax extendsadd_argument from argparse.Parse the args withTypedParserand enjoy args with type hints. Disable typechecking by settingstrict=False.fromtypingimportOptionalfromattrsimportdefinefromtypedparserimportadd_argument,TypedParser@defineclassArgs:# omit the argument name to have it inferred from the field namefoo: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")defmain():parser=TypedParser.create_parser(Args,strict=True)args:Args=parser.parse_args()print(args)if__name__=="__main__":main()FeaturesCreate 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 typesSupports old and new style typing (e.g.typing.Listandlist)Supports positional and keyword arguments in classesCan also typecheck existing attrs instancesAllows custom conversions, by default converts source typestrto target typePathandinttofloatAllows to redefine which objects will be recursed into, by default recurses into standard
containers (list, dict, etc.)@definenumpydecorator for equality check if the instances contains numpy arraysSome object utilities intypedparser.objectsrequired for everything elseAdvanced usageUseTypedParser.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 listsxarg: List[int] = add_argument(shortcut="-x", type=int, action="append", help="Xarg", default=[]),
use as-x 1 -x 2to get[1, 2]in the args instance.Usage of attr utilitiesDefine the class hierarchy and parse the input usingattrs_from_dict.
Use@define(slots=False)to allow multiple inheritance and setting attributes later.fromattrsimportdefinefromtypingimportOptionalfromtypedparserimportattrs_from_dict@defineclassCfg:foo:int=12bar:Optional[int]=Noneprint(attrs_from_dict(Cfg,{"foo":1,"bar":2}))# Cfg(foo=1, bar=2)@defineclassCfgNested:sub_cfg:Cfg=Noneprint(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 tupleRaise errors if types cannot be matched, there are unknown fields in the input or
abstract annotation types are used (e.g. Sequence)Non-strict modeEnabled by callingattrs_from_dictwithstrict=FalseNo conversion except for creating the attrs instance from the dictIgnore silently if types cannot be matched or abstract annotation types are usedUnknown fields in the input will be added to the attrs instance if possible
(see the hint below about slots)Skip unknownsSetskip_unknowns=Trueto ignore all unknown input fields.HintsThe following behaviour stems from theattrspackage:New attributes cannot to be added after class definition to an attrs instance,
unless it is created with@define(slots=False)ExplanationUntyped fields or "ClassVar" typed fields will be ignored by @attrs.define
and therefore also by this library.Install locally and run testsClone repository and cd into. Setup python 3.7 or higher.
Note: Some tests are skipped for python 3.7.pipinstall-e.
pipinstallpytestpytest-covpylintpytest-lazy-fixture
pylinttypedparser# run testspython-mpytest--cov
pylinttests