konradhalas / dacite

Simple creation of data classes from dictionaries.
MIT License
1.72k stars 107 forks source link

Type_hooks not applied to InitVar fields #158

Closed adbancroft closed 1 year ago

adbancroft commented 3 years ago

I'm using the type_hook option as a factory to handle base/derived classes.

It works correctly with 'regular' fields, but fails for InitVar fields:

from dataclasses import dataclass, InitVar
from typing import Dict, Any
from dacite import from_dict, Config

@dataclass
class Variable(ABC):
    name:str

@dataclass
class IntVariable(Variable):
    value:int

@dataclass
class StrVariable(Variable):
    value:str

def variable_factory(tuple):
    class_map = {
        'IntVariable' : IntVariable,
        'StrVariable' : StrVariable
    }
    return from_dict(data_class=class_map[tuple[0]], data=tuple[1])

@dataclass
class MyDictContainer:
    name:str
    vars:Dict[Any, Variable]

data = {
    'name': 'foo',
    'vars': {
        1: ('IntVariable', {'name':'aa', 'value':1}),
        2: ('StrVariable', {'name':'bb', 'value':'zz'}),
    }
}
d = from_dict(data_class=MyDictContainer, data=data, config=Config(type_hooks={Variable: variable_factory}))
print(d)
# MyDictContainer(name='foo', vars={1: IntVariable(name='aa', value=1), 2: StrVariable(name='bb', value='zz')})
# :-)

@dataclass
class MyDictContainerInitVar:
    name:str
    vars:InitVar[Dict[Any, Variable]]

d = from_dict(data_class=MyDictContainerInitVar, data=data, config=Config(type_hooks={Variable: variable_factory}))
# WrongTypeError
# :-(
adbancroft commented 3 years ago

Might be related to InitVar instances never comparing equal?

a = InitVar[str]
b = InitVar[str]

print(a==b)
# False