Package: validated-dc
ValidatedDCDataclass with data validation. Checks the value of its fields by their annotations.CapabilitiesValidatedDCis a regular Python dataclass.Support for standard types and custom Python classes.Support for some aliases from thetypingmodule, namely:Any,List,Literal,Optional,Union. These aliases can be embedded in each other.When initializing an instance of a class, you can use the value of the fielddictinstead of theValidatedDCinstance specified in the field annotation (useful, for example, when retrieving data via api).Data validation occurs immediately after an instance is created, and can also be run by theis_valid()function at any time.Theget_errors()function will show the full traceback of errors in the fields, including errors of nested classes.See detailed in theexamplesfolder.Installationpipinstallvalidated-dcPython versions supportVersions3.7,3.8and3.9are currently supported.To work with versionpython 3.7you need to install:pipinstalltyping_extensionsQuick examplefromdataclassesimportdataclassfromtypingimportList,Unionfromvalidated_dcimportValidatedDC,get_errors,is_valid# Some combinations of List and Union@dataclassclassFoo(ValidatedDC):value:Union[int,List[int]]@dataclassclassBar(ValidatedDC):foo:Union[Foo,List[Foo]]# --- Valid input ---foo={'value':1}instance=Bar(foo=foo)assertget_errors(instance)isNoneassertinstance==Bar(foo=Foo(value=1))foo={'value':[1,2]}instance=Bar(foo=foo)assertget_errors(instance)isNoneassertinstance==Bar(foo=Foo(value=[1,2]))foo=[{'value':1},{'value':2}]instance=Bar(foo=foo)assertget_errors(instance)isNoneassertinstance==Bar(foo=[Foo(value=1),Foo(value=2)])foo=[{'value':[1,2]},{'value':[3,4]}]instance=Bar(foo=foo)assertget_errors(instance)isNoneassertinstance==Bar(foo=[Foo(value=[1,2]),Foo(value=[3,4])])# --- Invalid input ---foo={'value':'S'}instance=Bar(foo=foo)assertget_errors(instance)assertinstance==Bar(foo={'value':'S'})# fixinstance.foo['value']=1assertis_valid(instance)assertget_errors(instance)isNoneassertinstance==Bar(foo=Foo(value=1))foo=[{'value':[1,2]},{'value':['S',4]}]instance=Bar(foo=foo)assertget_errors(instance)assertinstance==Bar(foo=[{'value':[1,2]},{'value':['S',4]}])# fixinstance.foo[1]['value'][0]=3assertis_valid(instance)assertget_errors(instance)isNoneassertinstance==Bar(foo=[Foo(value=[1,2]),Foo(value=[3,4])])# --- get_errors() ---foo={'value':'S'}instance=Bar(foo=foo)print(get_errors(instance))# {#   'foo': [#       # An unsuccessful attempt to use the dictionary to create a Foo instance#       InstanceValidationError(#           value_repr="{'value': 'S'}",#           value_type=<class 'dict'>,#           annotation=<class '__main__.Foo'>,#           exception=None,#           errors={#               'value': [#                   BasicValidationError(  # because the str isn't an int#                       value_repr='S', value_type=<class 'str'>,#                       annotation=<class 'int'>, exception=None#                   ),#                   BasicValidationError(  # and the str is not a list of int#                       value_repr='S', value_type=<class 'str'>,#                       annotation=typing.List[int], exception=None#                   )#               ]#           }#       ),#       BasicValidationError(  # the dict is not a list of Foo#           value_repr="{'value': 'S'}",#           value_type=<class 'dict'>,#           annotation=typing.List[__main__.Foo],#           exception=None#       )#   ]# }