konradhalas / dacite

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

Behaviour when deserializing tuples #73

Closed larsrinn closed 4 years ago

larsrinn commented 4 years ago

...and probably also for sets, etc.

First of all, thank you for comments and changes after my last issue #61. I clearly understand the reasoning behind that.

Now I'm running into issues related to that. When trying to deserialize a dictionary that has a list but the dataclass requires tuples, I can't get the casting to work. I think the code speaks for itsself:

from dataclasses import dataclass
import typing

from dacite import from_dict, Config

TupleOfInts = typing.Tuple[int]

@dataclass
class Dataclass:
    values: TupleOfInts

from_dict(
    data_class=Dataclass,
    data={"values": [1,2,3]},
    config=Config(
        cast=[
            typing.Tuple, # I'd expect either of these to work
            tuple,
        ]
    )
)
dacite.exceptions.WrongTypeError: wrong type for field "values" - should be "typing.Tuple[int]" instead of "list"

I expected dacite to cast the list to a tuple and then confirm the actual values are ints. So I thought: Maybe I have to add the TupleOfInts to the cast parameter explicitly (which I'd prefer to avoid) but then I get another error:

  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 671, in __call__
    raise TypeError(f"Type {self._name} cannot be instantiated; "
TypeError: Type Tuple cannot be instantiated; use tuple() instead

btw: My editor complains when passing in a set as parameter for cast. Without having looked at the implementation, it seems the type hint List is more restrictive than necessary and Iterable will do the job, too.

konradhalas commented 4 years ago

@larsrinn thank you for reporting this issue :)

Should be fixed via https://github.com/konradhalas/dacite/commit/cb3229a8006167e301fa4010458521abc9421bf5.