-
-
Notifications
You must be signed in to change notification settings - Fork 607
feat: Enable FieldExtension support for experimental pydantic types #4171
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
Conversation
Reviewer's GuideEnables propagation of Strawberry FieldExtension instances onto fields generated by the experimental pydantic.type integration, adds comprehensive tests for extension behavior on pydantic-based object types (including async and chained extensions), and updates docs/changelog snippets mostly for formatting consistency plus a new RELEASE entry describing the change. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
for more information, see https://pre-commit.ci
|
Thanks for adding the Here's a preview of the changelog: This release adds support for field extensions in experimental pydantic types. Previously, when using This fix ensures that extensions are properly preserved when converting pydantic fields to Strawberry fields, enabling the full power of field extensions across the pydantic integration. Examples: Permission-based field masking: from pydantic import BaseModel
from typing import Optional
import strawberry
from strawberry.experimental.pydantic import type as pyd_type
from strawberry.extensions.field_extension import FieldExtension
class PermissionExtension(FieldExtension):
def resolve(self, next_, source, info, **kwargs):
# Check permission, return None if denied
if not check_field_access(info.context.user, info.field_name, source.id):
return None
return next_(source, info, **kwargs)
class UserModel(BaseModel):
id: int
fname: str
email: str
phone: str
perm_ext = PermissionExtension()
@pyd_type(model=UserModel)
class UserGQL:
# Public fields - just use auto
id: strawberry.auto
fname: strawberry.auto
# Protected fields - attach extension
email: Optional[str] = strawberry.field(extensions=[perm_ext])
phone: Optional[str] = strawberry.field(extensions=[perm_ext])Basic transformation extension: class UpperCaseExtension(FieldExtension):
def resolve(self, next_, source, info, **kwargs):
result = next_(source, info, **kwargs)
return str(result).upper()
class ProductModel(BaseModel):
name: str
@pyd_type(model=ProductModel)
class Product:
name: str = strawberry.field(extensions=[UpperCaseExtension()])Here's the tweet text: |
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.
Hey - I've left some high level feedback:
- In
_build_dataclass_creation_fields, consider using the same default container type forextensionsas elsewhere inFieldDefinition(e.g.,()likedirectives) instead of[]to keep types and immutability consistent with the rest of the field configuration.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `_build_dataclass_creation_fields`, consider using the same default container type for `extensions` as elsewhere in `FieldDefinition` (e.g., `()` like `directives`) instead of `[]` to keep types and immutability consistent with the rest of the field configuration.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
@patrick91 @bellini666 @DoctorJohn 1 line change that doesn't break any existing tests. |
Greptile OverviewGreptile SummaryAdds field extension support to experimental pydantic types by forwarding the Key Changes:
Testing: Confidence Score: 5/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User as GraphQL Query
participant Schema as Strawberry Schema
participant Type as Pydantic Type Decorator
participant Builder as _build_dataclass_creation_fields
participant Field as StrawberryField
participant Ext as FieldExtension
participant Resolver as Field Resolver
User->>Schema: Execute Query
Note over Type,Builder: Pydantic Type Setup (during decoration)
Type->>Builder: Build fields for pydantic model
Builder->>Builder: Check if existing_field exists
alt Has custom resolver
Builder->>Field: Use existing field (with extensions)
else No custom resolver
Builder->>Field: Create new StrawberryField
Note over Builder,Field: Copy extensions from existing_field
Builder->>Field: Set extensions=existing_field.extensions
end
Note over Schema,Resolver: Query Execution
Schema->>Resolver: Resolve field
Resolver->>Ext: Call extension.resolve()
Ext->>Ext: Execute extension logic
Ext->>Resolver: Call next_(source, info, **kwargs)
Resolver->>Resolver: Get field value from pydantic model
Resolver->>Ext: Return value
Ext->>Ext: Transform/validate result
Ext->>Schema: Return final value
Schema->>User: Return query result
|
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.
No files reviewed, no comments
|
thank you! can you fix the pre-commit check? 😊 |
|
@patrick91 Done |
patrick91
left a comment
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.
Nice one 😊

Description
I made some custom permissions that work differently from
permission_classesand I noticed the experimental pydantic support did not forward the extensions from the existing fields.This change attempts to allow that. Code examples have been added in RELEASE.md
Types of Changes
Issues Fixed or Closed by This PR
Checklist
Summary by Sourcery
Enable propagation of field extensions to fields generated from experimental pydantic types.
Enhancements:
Documentation:
Tests: