Cyclic references break when using `class_schema` in a class decorator
thejcannon opened this issue · comments
Not unlike #188, however the calling code is in a class decorator trying to do interesting things on top of the schema
Version: 8.5.10
import dataclasses
from typing import List
from marshmallow_dataclass import class_schema
def class_dec(cls):
class_schema(cls)
return cls
@class_dec
@dataclasses.dataclass
class Tree:
name: str
children: List["Tree"]
The above leads to NameError: name 'Tree' is not defined
Workaround is to manually stamp out the decorator:
@dataclasses.dataclass
class Tree:
name: str
children: List["Tree"]
Tree = class_dec(Tree)
The issue is that, when class_dec
calls class_schema
, Tree
is not yet accessible via the global (module) namespace. That doesn't happen until just after the class decorators are applied.
I suppose we could special-case the self-referential case: have class_schema look a the name of the class, so that self-type-references would work.
That seems pretty hacky though, and it still wouldn't fix the case where forward type references are involved, e.g.:
@class_dec
@dataclasses.dataclass
class Tree:
name: str
children: "Children"
@dataclass
class Children:
trees: List[Tree]
I'm thinking the is probably not fixable (or not worth fixing). The solution, in your case, might be to have the class decorator defer its call to class_schema
as long as possible. (Hopefully, until after the module is fully loaded.)
(The marshmallow_dataclass.dataclass
decorator does essentially this, by using a LazyClassAttribute descriptor to defer the computation of the dataclass' .Schema
attribute.)
Closing. (Feel free to reopen, if you can come up with a clean way to fix this.)