cyclic references break when using class_schema
noirbee opened this issue · comments
v8.5.4 sadly broke recursive / cyclic schema support:
import dataclasses
from typing import List
from marshmallow_dataclass import class_schema
@dataclasses.dataclass
class Tree:
name: str
children: List["Tree"]
class_schema(Tree)
[…]
File "/home/nnoirbent/src/marshmallow_dataclass/marshmallow_dataclass/__init__.py", line 393, in _internal_class_schema
attributes.update(
File "/home/nnoirbent/src/marshmallow_dataclass/marshmallow_dataclass/__init__.py", line 396, in <genexpr>
field_for_schema(
File "/home/nnoirbent/src/marshmallow_dataclass/marshmallow_dataclass/__init__.py", line 686, in field_for_schema
generic_field = _field_for_generic_type(typ, base_schema, typ_frame, **metadata)
File "/home/nnoirbent/src/marshmallow_dataclass/marshmallow_dataclass/__init__.py", line 494, in _field_for_generic_type
child_type = field_for_schema(
File "/home/nnoirbent/src/marshmallow_dataclass/marshmallow_dataclass/__init__.py", line 718, in field_for_schema
or _internal_class_schema(typ, base_schema, typ_frame)
File "/home/nnoirbent/src/marshmallow_dataclass/marshmallow_dataclass/__init__.py", line 385, in _internal_class_schema
for k, v in inspect.getmembers(clazz)
File "/usr/lib/python3.10/inspect.py", line 447, in getmembers
if isclass(object):
File "/usr/lib/python3.10/inspect.py", line 197, in isclass
return isinstance(object, type)
RecursionError: maximum recursion depth exceeded while calling a Python object
This is due to how marshmallow_dataclass now uses typing.get_type_hints()
for better handling of forward references, since fac0b6d
Unfortunately the recursion guard from lazy_class_attribute
only works when modifying the target class, i.e. with @marshmallow_dataclass.dataclass
or @add_schema
(which is triggered by this line:
I'm not sure what's the best way to tackle this: adding a dict[class, forward_value]
of "seen" classes to the various functions/helpers to avoid recursion ?
Yes, that should work
Just ran into this as well. Interestingly though using from dataclasses import dataclass
:
from dataclasses import dataclass
from typing import List
from marshmallow_dataclass import class_schema
@dataclass
class Tree:
name: str
children: List["Tree"]
print(class_schema(Tree))
breaks with maximum recursion depth
however from marshmallow_dataclass import dataclass
doesn't:
from marshmallow_dataclass import dataclass
from typing import List
from marshmallow_dataclass import class_schema
@dataclass
class Tree:
name: str
children: List["Tree"]
print(class_schema(Tree))
works fine with output of:
<class 'marshmallow.schema.Tree'>
Process finished with exit code 0
Another option is just to update everything to use from marshmallow_dataclass import dataclass
instead of from dataclasses import dataclass
?
@AleksanderPawlak , you may want to have a look