Composable complex class support for attrs and dataclasses with (un)structuring and validation.
npx @tessl/cli install tessl/pypi-cattrs@25.2.0Cattrs is a Swiss Army knife for (un)structuring and validating data in Python. It converts unstructured dictionaries into proper classes and back, while validating their contents. Built on the principle of separating un/structuring rules from data models, cattrs excels at recursive handling of complex nested data structures and provides extensive customization options.
pip install cattrsimport cattrsCommon imports for direct usage:
from cattrs import structure, unstructureFor creating custom converters:
from cattrs import Converterfrom attrs import define
from cattrs import structure, unstructure
@define
class Person:
name: str
age: int
email: str | None = None
# Unstructure: Convert class instance to dictionary
person = Person(name="Alice", age=30, email="alice@example.com")
data = unstructure(person)
print(data) # {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}
# Structure: Convert dictionary to class instance
person_copy = structure(data, Person)
print(person_copy) # Person(name='Alice', age=30, email='alice@example.com')
# Works with complex nested structures
@define
class Team:
name: str
members: list[Person]
team_data = {
'name': 'Engineering',
'members': [
{'name': 'Alice', 'age': 30, 'email': 'alice@example.com'},
{'name': 'Bob', 'age': 25, 'email': None}
]
}
team = structure(team_data, Team)
print(team.members[0].name) # AliceCattrs is built around a converter-based architecture that enables flexible data transformation:
cattrs.global_converter) used by module-level functionsConverter instances for specialized use casesThis design allows cattrs to handle complex type hierarchies while maintaining excellent performance and providing extensive customization options for edge cases.
The fundamental cattrs API for converting between structured and unstructured data. Provides module-level functions that use the global converter, as well as converter classes for custom configurations.
def structure(obj, cl, converter=None):
"""Convert unstructured data to structured data."""
def unstructure(obj, unstructure_as=None, converter=None):
"""Convert structured data to unstructured data."""
class Converter:
"""Main converter class with specialized un/structuring functions."""
def __init__(self, **kwargs): ...
def structure(self, obj, cl): ...
def unstructure(self, obj, unstructure_as=None): ...Ready-to-use converters pre-configured for specific serialization formats including JSON, YAML, MessagePack, TOML, BSON, CBOR2, and more. Each provides optimal settings and type handling for their respective formats.
# JSON converter example
from cattrs.preconf.json import make_converter
converter = make_converter()
json_data = converter.unstructure(obj)
obj_copy = converter.structure(json_data, MyClass)Powerful strategies for handling complex type scenarios including union types, subclass hierarchies, and class method integration. Provides tools for configuring converters to handle advanced typing patterns.
from cattrs.strategies import configure_tagged_union, include_subclasses
def configure_tagged_union(union_type, converter, **kwargs): ...
def include_subclasses(base_class, converter, **kwargs): ...Comprehensive error handling system with detailed validation errors, structured exception hierarchies, and error transformation utilities for better debugging and user feedback.
class BaseValidationError(ExceptionGroup):
"""Base class for validation errors."""
def transform_error(exc, path=None, **kwargs):
"""Transform validation errors into detailed error messages."""High-performance code generation utilities for creating specialized structuring and unstructuring functions. Enables optimization of performance-critical code paths.
from cattrs.gen import make_dict_structure_fn, make_dict_unstructure_fn
def make_dict_structure_fn(cl, converter, **kwargs): ...
def make_dict_unstructure_fn(cl, converter, **kwargs): ...from typing import Protocol, TypeVar, Any, Callable
from enum import Enum
T = TypeVar('T')
class SimpleStructureHook(Protocol):
"""Protocol for structure hooks with optional second argument."""
def __call__(self, val: Any, type: type[T] = None) -> T: ...
class UnstructureStrategy(Enum):
"""Enum defining unstructuring strategies."""
AS_DICT = "AS_DICT"
AS_TUPLE = "AS_TUPLE"
# Type aliases for hook functions
StructureHook = Callable[[Any, type[T]], T]
UnstructureHook = Callable[[T], Any]