Closed
Description
This examples should clairfy the issue:
from attrs import define, field
from cattrs import Converter
from cattrs.gen import make_dict_structure_fn, make_dict_unstructure_fn, override
from cattrs.strategies import include_subclasses
converter = Converter()
# Define a base class and some subclasses
@define
class Animal:
name: str = field()
@define
class Dog(Animal):
breed: str = field()
@define
class Cat(Animal):
color: str = field()
def register_rename(cls, renames: dict):
over = {k: override(rename=v) for k, v in renames.items()}
unst_hook = make_dict_unstructure_fn(
cls, converter, **over
)
st_hook = make_dict_structure_fn(
cls, converter, **over
)
converter.register_unstructure_hook(cls, unst_hook)
converter.register_structure_hook(cls, st_hook)
return over
register_rename(Dog, {"breed": "Breed"})
register_rename(Animal, {"name": "NAME"}) # by registering a rename for the base class, this breaks include_subclasses
include_subclasses(Animal, converter=converter, subclasses=(Dog, Cat))
# Create instances
animals = [Dog(name="Fido", breed="Labrador"), Cat(name="Whiskers", color="Tabby")]
# Structure and unstructure
unstructured = [converter.unstructure(a, Animal) for a in animals]
print("Unstructured:", unstructured)
restructured = [converter.structure(obj, Animal) for obj in unstructured]
print("Restructured:", restructured)
output is
Unstructured: [{'NAME': 'Fido'}, {'NAME': 'Whiskers'}]
Restructured: [Animal(name='Fido'), Animal(name='Whiskers')]
while, by commenting out the register_rename line for Animal:
Unstructured: [{'name': 'Fido', 'Breed': 'Labrador'}, {'name': 'Whiskers', 'color': 'Tabby'}]
Restructured: [Dog(name='Fido', breed='Labrador'), Cat(name='Whiskers', color='Tabby')]
I could try to better investigate this with some assistance.
thanks for cattrs!
Luca
Metadata
Metadata
Assignees
Labels
No labels