feat: add flag to support for UNSET tristate when using pydantic#4051
feat: add flag to support for UNSET tristate when using pydantic#4051thorroed wants to merge 4 commits intostrawberry-graphql:mainfrom
Conversation
Reviewer's GuideIntroduce a flag to control whether Pydantic defaults are materialized for GraphQL inputs, enabling true tri-state semantics by preserving UNSET values when opted out. File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Hi, thanks for contributing to Strawberry 🍓! We noticed that this PR is missing a So as soon as this PR is merged, a release will be made 🚀. Here's an example of Release type: patch
Description of the changes, ideally with some examples, if adding a new feature.Release type can be one of patch, minor or major. We use semver, so make sure to pick the appropriate type. If in doubt feel free to ask :) Here's the tweet text: |
Greptile OverviewGreptile SummaryThis PR adds a Key Changes:
Behavior:
Confidence Score: 4/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant Client as GraphQL Client
participant Schema as Strawberry Schema
participant Input as UpdateUserInput
participant Pydantic as UserModel (Pydantic)
Note over Client,Pydantic: use_pydantic_default=False flow
Client->>Schema: mutation { updateUser(userData: {name: "John"}) }
Schema->>Input: Create UpdateUserInput(name="John")
alt Field Construction (use_pydantic_default=False)
Note over Input: interests field gets UNSET<br/>via _default_unset() factory
Input->>Input: name = "John"
Input->>Input: interests = UNSET
end
Input->>Input: Check field with `is UNSET`
alt Converting to Pydantic (to_pydantic)
Input->>Pydantic: to_pydantic()
Note over Input,Pydantic: Skip UNSET fields when<br/>use_pydantic_default=False
Input->>Pydantic: model(name="John")
Note over Pydantic: Pydantic applies default_factory<br/>interests=[]
end
Pydantic-->>Client: Updated user data
Note over Client,Pydantic: use_pydantic_default=True (default) flow
Client->>Schema: mutation { updateUser(userData: {name: "Alice"}) }
Schema->>Input: Create UpdateUserInput(name="Alice")
alt Field Construction (use_pydantic_default=True)
Note over Input: interests field gets Pydantic default<br/>via get_default_factory_for_field()
Input->>Input: name = "Alice"
Input->>Input: interests = []
end
Input->>Pydantic: to_pydantic()
Input->>Pydantic: model(name="Alice", interests=[])
Pydantic-->>Client: Updated user data
|
bellini666
left a comment
There was a problem hiding this comment.
Thanks :)
Can we have a test for this?
| # local helper to satisfy E731 (no lambda assignment) | ||
| def _default_unset() -> object: | ||
| return UNSET | ||
|
|
||
| # for inputs with use_pydantic_default, default_factory should be used | ||
| if is_input and not use_pydantic_default: | ||
| default_factory = _default_unset |
There was a problem hiding this comment.
thought: We have UnsetType, which is UNSET's class, and it overrides __new__ to make sure it is always a singleton. Maybe we can also override __call__ to return itself, so we could just do default_factory = UNSET?
/cc @patrick91
…ntics; make UnsetType a callable singleton for default_factory; update docs.
for more information, see https://pre-commit.ci
|
Does our intention of soft-deprecating cc @patrick91 |
@bellini666 Would the preferred pattern here be to make this work with |
|
@ppease I think I'd recommend Maybe in future 😊 Also I'd love to with you about our plans for the first party integration |
👍 Sounds good.
@patrick91 Happy to talk about first party integration for pydantic with you all. What's the easiest way to connect? |
|
@ppease probably email (in my github profile) or discord 😊 |
pydantic inputs (strawberry.auto): honor UNSET / allow opt-out of Pydantic defaults.
Pydantic defaults can mask omitted input fields in GraphQL. This opt-out preserves strict input semantics while keeping current behavior as default.
Fixes #4042
Example code:
Output of example code above:
Summary by Sourcery
Introduce use_pydantic_default flag to preserve true tri-state input semantics for Pydantic-backed GraphQL inputs.
New Features:
Bug Fixes:
Enhancements:
Documentation: