-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support recursive dataclasses #5760
Conversation
please review |
pydantic/_internal/_dataclasses.py
Outdated
if _parent_namespace_depth > 0: | ||
frame_parent_ns = _typing_extra.parent_frame_namespace(parent_depth=_parent_namespace_depth) or {} | ||
# cls_parent_ns = cls.__pydantic_parent_namespace__ or {} | ||
# cls.__pydantic_parent_namespace__ = {**cls_parent_ns, **frame_parent_ns} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we want to store the original namespace on the dataclasses like we do for BaseModel.
This helps in the scenario where rebuilds are necessary when importing from a separate module and there was a ForwardRef to a type in the module in which the class was originally defined.
This may also be necessary when parametrizing generic cyclically-recursive dataclasses outside the module in which they were defined.
I've left these lines present and commented as a reminder to decide about this. I'm okay either way.
Note: related, it may also be a good idea to make the _types_namespace
argument here and/or on BaseModel "public". (For context: It currently has the leading _
because we wanted to discourage its usage because picking up references from the current namespace should generally work, but we still included the argument in BaseModel.model_rebuild
to make it possible to more explicitly control what ForwardRefs evaluate to if you know what you are doing.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty neutral / would defer to you on it.
My preference is "simple wins", so I think I'd prefer not to store the namespace, but don't really mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a chance to speak with Adrian about this briefly, and I think we agreed it would be nice to keep the behavior as similar as possible between BaseModel
and pydantic dataclass
.
I do see your point about keeping things simple, but I also vaguely recall that I had added that __pydantic_parent_namespace__
in the BaseModel
case for the purpose of dealing with recursive generics.
Before proceeding to merge this branch, I'm going to try to work on top of this branch and get recursive generic dataclasses working. If it becomes clear that I will need the __pydantic_parent_namespace__
thing to get that to behave nicely, it might make this a moot point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, given there is a lot of complexity related to generic dataclasses and how exactly we should handle them, and not handling it properly is not a regression from v1 (as it wasn't handled properly there), my new plan is to not fiddle with the parent namespace, and also not support generic dataclasses in v2 (but perhaps in v2.1, or maybe sooner if we happen to get it all working in time.. but the pressure is off.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
otherwise LGTM.
pydantic/_internal/_dataclasses.py
Outdated
if _parent_namespace_depth > 0: | ||
frame_parent_ns = _typing_extra.parent_frame_namespace(parent_depth=_parent_namespace_depth) or {} | ||
# cls_parent_ns = cls.__pydantic_parent_namespace__ or {} | ||
# cls.__pydantic_parent_namespace__ = {**cls_parent_ns, **frame_parent_ns} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty neutral / would defer to you on it.
My preference is "simple wins", so I think I'd prefer not to store the namespace, but don't really mind.
Deploying with Cloudflare Pages
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conflicts, otherwise LGTM.
Merge when passing.
please update. |
Closes #5721. This is also a precursor to work on generic dataclasses.
I'll open the PR now, but I think there's a variety of things to establish some consensus on before merging:
model-not-fully-defined
and (analogous)dataclass-not-fully-defined
usage errors?model-not-fully-defined
and replaced it with a commonclass-not-fully-defined
error, but would be happy to revert this.dataclass-not-fully-defined
an acceptable name?model-not-fully-defined
considering it's largely similar and we have a docs section for each usage error code?BaseModel.__pydantic_model_complete__
toBaseModel.__pydantic_complete__
and used the same property on pydantic dataclasses. Any objections?BaseModel.model_rebuild
method. I have exported an analogous function calledpydantic.dataclasses.rebuild_dataclass
.pydantic._internal._dataclasses
and re-exported inpydantic.dataclasses
. Is this acceptable?__pydantic_dataclass_rebuild__
or similar to pydantic dataclasses — is that still the case? If so, what should the name of that method be?)I'll be happy to make any requested changes.
Selected Reviewer: @samuelcolvin