You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
Exception is thrown in dacite when using from_dict in certain scenarios on dataclass with <type> | None field, eg str | None
To Reproduce
import dataclasses
import dacite
import typing
@dataclasses.dataclass
class OptionalDataclass:
text1: typing.Optional[str]
@dataclasses.dataclass
class UnionDataclass:
text2: str | None
if __name__ == '__main__':
d1 = {"text1": None}
# In order to reproduce this bug:
# 1. this needs to be called first
dacite.from_dict(OptionalDataclass, d1)
# 2. this field has to be non None
d2 = {"text2": "abc"}
# 3. config with cast needs to be provided
# (content of cast array does not matter, as it only is necessary to trigger
# for cast_type in config.cast
# in dacite/core.py)
c = dacite.Config(cast=[int])
# then below fails
res = dacite.from_dict(UnionDataclass, d2, config=c)
# without either of 1-3 from above steps, final from_dict will work as expected
Root cause is caching of dacite.types.is_generic_collection and dacite.types.is_generic - caching mechanism interprets both Optional[str] and str | None as the same value, so it returns wrong value when we first call it with Optional[str], and then call it with str | None. This means first call of from_dict with OptionalDataclass pollutes the cache and breaks the behaviour for from_dict with UnionDataclass. Note that running only dacite.from_dict(UnionDataclass, d2, config=c) (without preceding call) works as expected.
To prove this, below are even simpler reproduction steps that throw exception:
if __name__ == '__main__':
is_generic(typing.Optional[str])
is_generic_collection(str | None)
Below works just fine:
if __name__ == '__main__':
is_generic_collection(str | None)
thus cache pollutes scope of dacite
Removing @cache from is_generic_collection, is_generic and extract_origin_collection fixes the issue in both cases
Expected behavior
Dacite transforms the data without error
Environment
Python version: 3.10
dacite version: 1.8.1
Workaround
Downgrade is an option - [email protected] works correctly
The text was updated successfully, but these errors were encountered:
If I might, I would like to start a conversation about caching - as there seems to have been (and are, and might be more) some issues that appeared because of caching, have you considered reverting those changes completely and dropping caching altogether? Would the performance hit be significant enough that you would rather keep the caching?
Asking as I do not know the historical context (maybe there was a need for performance boost)
Describe the bug
Exception is thrown in dacite when using
from_dict
in certain scenarios on dataclass with<type> | None
field, egstr | None
To Reproduce
Stack trace:
Root cause is caching of
dacite.types.is_generic_collection
anddacite.types.is_generic
- caching mechanism interprets bothOptional[str]
andstr | None
as the same value, so it returns wrong value when we first call it withOptional[str]
, and then call it withstr | None
. This means first call offrom_dict
withOptionalDataclass
pollutes the cache and breaks the behaviour forfrom_dict
withUnionDataclass
. Note that running onlydacite.from_dict(UnionDataclass, d2, config=c)
(without preceding call) works as expected.To prove this, below are even simpler reproduction steps that throw exception:
Below works just fine:
thus cache pollutes scope of dacite
Removing
@cache
fromis_generic_collection
,is_generic
andextract_origin_collection
fixes the issue in both casesExpected behavior
Dacite transforms the data without error
Environment
dacite
version: 1.8.1Workaround
Downgrade is an option - [email protected] works correctly
The text was updated successfully, but these errors were encountered: