Because validation belongs to the edges.
cattrs is a Swiss Army knife for (un)structuring and validating data in Python. In practice, that means it converts unstructured dictionaries into proper classes and back, while validating their contents.
cattrs works best with attrs classes, and dataclasses where simple (un-)structuring works out of the box, even for nested data, without polluting your data model with serialization details:
>>> from attrs import define
>>> from cattrs import structure, unstructure
>>> @define
... class C:
... a: int
... b: list[str]
>>> instance = structure({'a': 1, 'b': ['x', 'y']}, C)
>>> instance
C(a=1, b=['x', 'y'])
>>> unstructure(instance)
{'a': 1, 'b': ['x', 'y']}
Have a look at Why cattrs? for more examples!
attrs.asdict()
, or into tuples in a way similar to attrs.astuple()
.register_unstructure_hook
.Converts unstructured data into structured data, recursively, according to your specification given as a type. The following types are supported:
typing.Optional[T]
and its 3.10+ form, T | None
.list[T]
, typing.List[T]
, typing.MutableSequence[T]
, typing.Sequence[T]
convert to lists.tuple
and typing.Tuple
(both variants, tuple[T, ...]
and tuple[X, Y, Z]
).set[T]
, typing.MutableSet[T]
, and typing.Set[T]
convert to sets.frozenset[T]
, and typing.FrozenSet[T]
convert to frozensets.dict[K, V]
, typing.Dict[K, V]
, typing.MutableMapping[K, V]
, and typing.Mapping[K, V]
convert to dictionaries.typing.TypedDict
, both ordinary and generic.typing.NewType
__init__
[^simple].__init__
, if their complex attributes have type metadata.register_structure_hook
.[^simple]: Simple attributes are attributes that can be assigned unstructured data, like numbers, strings, and collections of unstructured data.
cattrs comes with pre-configured converters for a number of serialization libraries, including JSON (standard library, orjson, UltraJSON), msgpack, cbor2, bson, PyYAML, tomlkit and msgspec (supports only JSON at this time).
For details, see the cattrs.preconf package.
cattrs is based on a few fundamental design decisions:
use_class_methods
strategy.)exceptiongroups
.
A side-effect of this design decision is that, in a lot of cases, when you're solving cattrs problems you're actually learning Python instead of learning cattrs.A foolish consistency is the hobgoblin of little minds, so these decisions can and are sometimes broken, but they have proven to be a good foundation.
Major credits to Hynek Schlawack for creating attrs and its predecessor, characteristic.
cattrs is tested with Hypothesis, by David R. MacIver.
cattrs is benchmarked using perf and pytest-benchmark.
This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage
project template.