When the data type is a collection but not a dict, tuple or list, _build_value_for_collection breaks either silently or loudly. For example,
from typing import Mapping
from dacite.core import _build_value_for_collection
class MyMap(Mapping):
def __init__(self, length):
self.length = int(length)
def __getitem__(self, key):
return key**2
def __iter__(self):
return iter(range(self.length))
def __len__(self):
return self.length
# raises TypeError: int() argument ...
_build_value_for_collection(dict[int, int], MyMap(3), None)
from dacite.core import _build_value_for_collection
# returns a string '<generator object _build_value_for_collection.<locals>.<genexpr> at 0x10507e440>'
_build_value_for_collection(list[str], "ab", None)
The issue is caused by the loose data type check clauses here
|
def _build_value_for_collection(collection: Type, data: Any, config: Config) -> Any: |
|
data_type = data.__class__ |
|
if isinstance(data, Mapping) and is_subclass(collection, Mapping): |
|
item_type = extract_generic(collection, defaults=(Any, Any))[1] |
|
return data_type((key, _build_value(type_=item_type, data=value, config=config)) for key, value in data.items()) |
|
elif is_subclass(collection, tuple): |
|
if not data: |
|
return data_type() |
|
types = extract_generic(collection) |
|
if len(types) == 2 and types[1] == Ellipsis: |
|
return data_type(_build_value(type_=types[0], data=item, config=config) for item in data) |
|
return data_type( |
|
_build_value(type_=type_, data=item, config=config) for item, type_ in zip_longest(data, types) |
|
) |
|
elif isinstance(data, Collection) and is_subclass(collection, Collection): |
|
item_type = extract_generic(collection, defaults=(Any,))[0] |
|
return data_type(_build_value(type_=item_type, data=item, config=config) for item in data) |
When the data type is a collection but not a
dict,tupleorlist,_build_value_for_collectionbreaks either silently or loudly. For example,The issue is caused by the loose data type check clauses here
dacite/dacite/core.py
Lines 146 to 162 in 9898ccb