-
Notifications
You must be signed in to change notification settings - Fork 163
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Description
I've encountered this issue when writing tests for my project with pytest.
The test is contained in one function and I've added a file to test the behavior of from __future__ import annotations
All my nested dataclass_json field tests failed (when a field of one dataclass_json is another dataclass_json) on .from_dict
for the example below I've got this traceback :
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[1], line 17
15 class_with_inner = MyClass(InnerClass('asdf', 2))
16 return MyClass.from_dict(class_with_inner.to_dict())
---> 17 print(do_something())
Cell In[1], line 16, in do_something()
13 my_inner_inst: InnerClass
15 class_with_inner = MyClass(InnerClass('asdf', 2))
---> 16 return MyClass.from_dict(class_with_inner.to_dict())
File /data/.venv-temp/lib/python3.11/site-packages/dataclasses_json/api.py:70, in DataClassJsonMixin.from_dict(cls, kvs, infer_missing)
65 @classmethod
66 def from_dict(cls: Type[A],
67 kvs: Json,
68 *,
69 infer_missing=False) -> A:
---> 70 return _decode_dataclass(cls, kvs, infer_missing)
File /data/.venv-temp/lib/python3.11/site-packages/dataclasses_json/core.py:178, in _decode_dataclass(cls, kvs, infer_missing)
175 kvs = _handle_undefined_parameters_safe(cls, kvs, usage="from")
177 init_kwargs = {}
--> 178 types = get_type_hints(cls)
179 for field in fields(cls):
180 # The field should be skipped from being added
181 # to init_kwargs as it's not intended as a constructor argument.
182 if not field.init:
File /usr/lib/python3.11/typing.py:2336, in get_type_hints(obj, globalns, localns, include_extras)
2334 if isinstance(value, str):
2335 value = ForwardRef(value, is_argument=False, is_class=True)
-> 2336 value = _eval_type(value, base_globals, base_locals)
2337 hints[name] = value
2338 return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()}
File /usr/lib/python3.11/typing.py:371, in _eval_type(t, globalns, localns, recursive_guard)
364 """Evaluate all forward references in the given type t.
365
366 For use of globalns and localns see the docstring for get_type_hints().
367 recursive_guard is used to prevent infinite recursion with a recursive
368 ForwardRef.
369 """
370 if isinstance(t, ForwardRef):
--> 371 return t._evaluate(globalns, localns, recursive_guard)
372 if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)):
373 if isinstance(t, GenericAlias):
File /usr/lib/python3.11/typing.py:877, in ForwardRef._evaluate(self, globalns, localns, recursive_guard)
872 if self.__forward_module__ is not None:
873 globalns = getattr(
874 sys.modules.get(self.__forward_module__, None), '__dict__', globalns
875 )
876 type_ = _type_check(
--> 877 eval(self.__forward_code__, globalns, localns),
878 "Forward references must evaluate to types.",
879 is_argument=self.__forward_is_argument__,
880 allow_special_forms=self.__forward_is_class__,
881 )
882 self.__forward_value__ = _eval_type(
883 type_, globalns, localns, recursive_guard | {self.__forward_arg__}
884 )
885 self.__forward_evaluated__ = True
File <string>:1
NameError: name 'InnerClass' is not defined
Workaround : moving the inner dataclass definition out of the function code block.
Code snippet that reproduces the issue
from __future__ import annotations
from dataclasses import dataclass
from dataclasses_json import DataClassJsonMixin
def do_something() -> MyClass:
@dataclass
class InnerClass(DataClassJsonMixin):
my_str: str
my_int: int
@dataclass
class MyClass(DataClassJsonMixin):
my_inner_inst: InnerClass
class_with_inner = MyClass(InnerClass('asdf', 2))
return MyClass.from_dict(class_with_inner.to_dict())
print(do_something())
Describe the results you expected
MyClass(my_inner_inst=InnerClass(my_str='asdf', my_int=2))
Python version you are using
3.11.4
Environment description
asttokens==2.4.1
dataclasses-json==0.6.7
decorator==5.1.1
executing==2.1.0
ipython==8.27.0
jedi==0.19.1
marshmallow==3.22.0
matplotlib-inline==0.1.7
mypy-extensions==1.0.0
packaging==24.1
parso==0.8.4
pexpect==4.9.0
prompt_toolkit==3.0.48
ptyprocess==0.7.0
pure_eval==0.2.3
Pygments==2.18.0
six==1.16.0
stack-data==0.6.3
traitlets==5.14.3
typing-inspect==0.9.0
typing_extensions==4.12.2
wcwidth==0.2.13
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working