dacite
dacite copied to clipboard
Return value of custom type hook is discarded when decoding generic type in union
Describe the bug
Return value of custom type hook is discarded when decoding generic type in union.
To Reproduce
In the following example, a generic dataclass Foo[T] is defined and used as a field in another dataclass Bar. In the example, only the type Foo[int] is actually used and for that type, a custom type hook is defined that decodes a value from a JSON int:
from typing import TypeVar, Generic, Union
from dataclasses import dataclass
import dacite
T = TypeVar('T')
@dataclass
class Foo(Generic[T]):
value: T
@dataclass
class Bar:
foo: Union[Foo[int], str]
def _read_int_foo(data):
assert isinstance(data, int)
result = Foo(data)
print(f'_read_int_foo: {data} -> {result}')
return result
_dacite_type_hooks = {
Foo[int]: _read_int_foo}
dacite_config = dacite.Config(type_hooks=_dacite_type_hooks, check_types=False)
data = {
'foo': 123
}
print(dacite.from_dict(Bar, data, dacite_config))
Running this prints the following:
_read_int_foo: 123 -> Foo(value=123)
Bar(foo=123)
I.e. the field foo has been set to the original int value from the data instead of the value returned by _read_int_foo(). This only happens when check_types is set to False (otherwise a UnionMatchError is raised).
Expected behavior
IMHO, the returned value should be used:
_read_int_foo: 123 -> Foo(value=123)
Bar(foo=Foo(value=123))
Environment
$ pip list
Package Version
---------- -------
dacite 1.8.0
pip 23.0.1
setuptools 67.3.2
$ python -V
Python 3.8.16