Skip to content

include_subsclasses fails when a rename override is used in the parent class #1438

Closed
@luca-penasa

Description

@luca-penasa

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions