konradhalas / dacite

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

dacite.from_dict: `NamedTuple` type hook does not work with `cast=[tuple]` (regression from v1.7.0) #253

Open idanmiara opened 7 months ago

idanmiara commented 7 months ago

Describe the bug dacite.from_dict fails for a class containing a NamedTuple if you also set cast=[tuple] in your Config

To Reproduce The following code runs fine with dacite==1.7.0 but fails on dacite==1.8.1. If you omit cast=[tuple] from the Config it also works on 1.8.1

from dataclasses import dataclass
from typing import NamedTuple

import dacite

class Point(NamedTuple):
    x: float
    y: float

    @staticmethod
    def from_dict(data: dict[str, float]) -> 'Point':
        return Point(data['x'], data['y'])

@dataclass
class Model:
    point: Point

type_hooks = {Point: lambda x: Point.from_dict(x)}
pd0 = dict(y=1.1, x=2.2)
d = {
    'point': pd0,
}
config = dacite.Config(type_hooks=type_hooks, cast=[tuple])
model1 = dacite.from_dict(Model, d, config=config)
model2 = Model(point=Point(**pd0))
assert model1 == model2
Traceback (most recent call last):
  File "/Users/idan.miara/Library/Application Support/JetBrains/PyCharm2023.2/scratches/scratch_161.py", line 27, in <module>
    model1 = dacite.from_dict(Model, d, config=config)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/idan.miara/.pyenv/versions/dacite/lib/python3.11/site-packages/dacite/core.py", line 64, in from_dict
    value = _build_value(type_=field_type, data=field_data, config=config)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/idan.miara/.pyenv/versions/dacite/lib/python3.11/site-packages/dacite/core.py", line 105, in _build_value
    data = type_(data)
           ^^^^^^^^^^^
TypeError: Point.__new__() missing 1 required positional argument: 'y'

Expected behavior

The code above should work fine as it did with 1.7.0

Environment