konradhalas / dacite

Simple creation of data classes from dictionaries.
MIT License
1.76k stars 106 forks source link

Type hooks are not called for Union cases #82

Closed kwvanderlinde closed 4 years ago

kwvanderlinde commented 4 years ago

Here is a simple example:

#!/usr/bin/env python3
import dacite
from dataclasses import dataclass
from typing import Union

@dataclass
class A:
    a: int

@dataclass
class B:
    b: str

@dataclass
class Top:
    field: Union[A, B]

result = dacite.from_dict(
    data_class=Top,
    data={
        'field': {
            'b': '52'
        }
    },
    config=dacite.Config(
        type_hooks={
            B: lambda d: B(b='Hello!')
        }
    ))
print(result)

If you run this today, it will print:

Top(field=B(b='52'))

Notice that the B instance returned by the type hook is ignored (indeed the type hook is never called). I would expect the code to actually print:

Top(field=B(b='Hello!'))

This is inconsistent with the non-Union case. I.e., if we use a simpler version of Top, the type hook is used:

@dataclass
class Top:
    field: B

Of course, a Union with a single argument is identical to just using the argument, so this also works:

@dataclass
class Top:
    field: Union[B]

But once we add a second argument to the Union, no more type hooks are used.

konradhalas commented 4 years ago

@kwvanderlinde thank you for reporting - you have right, it's a bug. I will try to fix it in the next release :)