Skip to content

Convereter.structure use_alias not working with Union types #706

@SimplyKnownAsG

Description

@SimplyKnownAsG

I'm using cattrs==25.3.0, and I'm trying to use a Union with subtypes that have aliases. I cannot get either the use_alias input in Converter nor the make_dict_structure_fn method [mentioned here] to correctly resolve non-conflicting union types while still using the alias. Union types without aliases work just fine. Lists (and presumably dict values) of some type with use_alias also work.

Is there another way this can/should be configured to make it work as I had expected? Is my expectation correct?

from attrs import define, field, has
from cattrs import Converter, gen


@define
class Cat:
    cat_name: str = field(alias="catName")

@define
class Dog:
    dog_name: str = field(alias="dogName")

@define
class Apartment:
    pet: Cat | Dog


c0 = Converter()
c1 = Converter(use_alias=True)
c2 = Converter()
c2.register_structure_hook_factory(
    has,
    lambda cl: gen.make_dict_structure_fn(cl, c2, _cattrs_use_alias=True)
)

def structure(data, cls):
    print("")

    for (c, prefix) in (
                (c0, "default     "),
                (c1, "use_alias   "),
                (c2, "hook_factory")
            ):
        result = None
        try:
            result = c.structure(data, cls)
        except Exception as ex:
            result = type(ex)

        print(f"{prefix} structure({data}, {cls.__name__}) == {result}")

snake_dog = dict(dog_name="snake")
camelDog = dict(dogName="camel")

snake_cat = dict(cat_name="snake")
camelCat = dict(catName="camel")

structure(dict(pet=snake_dog), Apartment)
structure(dict(pet=camelCat), Apartment)

with output below. I expected use_alias and hook_factory to work with camelCat.

default      structure({'pet': {'dog_name': 'snake'}}, Apartment) == Apartment(pet=Dog(dog_name='snake'))
use_alias    structure({'pet': {'dog_name': 'snake'}}, Apartment) == <class 'cattrs.errors.ClassValidationError'>
hook_factory structure({'pet': {'dog_name': 'snake'}}, Apartment) == <class 'cattrs.errors.ClassValidationError'>

default      structure({'pet': {'catName': 'camel'}}, Apartment) == <class 'cattrs.errors.ClassValidationError'>
use_alias    structure({'pet': {'catName': 'camel'}}, Apartment) == <class 'cattrs.errors.ClassValidationError'>
hook_factory structure({'pet': {'catName': 'camel'}}, Apartment) == <class 'cattrs.errors.ClassValidationError'>

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions