python-attrs / cattrs

Composable custom class converters for attrs, dataclasses and friends.
https://catt.rs
MIT License
799 stars 110 forks source link

Union disambiguation fails when using `to_camel` structuring/unstructuring hook factories #233

Open mmaarouf1 opened 2 years ago

mmaarouf1 commented 2 years ago

Description

Consider the following:


@define
class A:
    first_field: int
    second_field: int

@define
class B:
    first_field: int
    third_Field: int

Using the hook factories described here to structure/unstructure camelCase attributes:

converter = Converter()

def to_camel_case(snake_str: str) -> str:
....
converter.register_structure_hook_factory(
    has, to_camel_case_structure
)

Then the following behavior is observed:

camel_case_dict = {
    "thirdField": 2,
    "firstField": 1
}

The following works:

 converter.structure(camel_case_dict, Union[A, B])
 converter.structure(camel_case_dict, Union[B, A])

However, if we structure using Union[B, A] first, then cattrs tries to structure the input as A instead of B:

 converter.structure(camel_case_dict, Union[B, A])
o = {'firstField': 1, 'thirdField': 2}
_ = (<class 'test.input_config.test_output_config.A'>,)

    def structure_A(o, *_):
      res = {
        'first_field': structure_first_field(o['firstField'], type_first_field),
>       'second_field': structure_second_field(o['secondField'], type_second_field),
        }
E     KeyError: 'secondField'
Tinche commented 2 years ago

Hello,

thanks, this might be tricky to support with the current architeture but I'll keep it in mind!