Skip to content

Conversation

@XChikuX
Copy link
Contributor

@XChikuX XChikuX commented Jan 26, 2026

Description

I made some custom permissions that work differently from permission_classes and 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

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Documentation

Issues Fixed or Closed by This PR

  • No issues were reported I think.

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

Summary by Sourcery

Enable propagation of field extensions to fields generated from experimental pydantic types.

Enhancements:

  • Preserve field extensions defined on experimental pydantic type fields when building the underlying Strawberry fields.

Documentation:

  • Add release notes documenting field extension support for experimental pydantic types.

Tests:

  • Add comprehensive tests covering field extensions behavior on experimental pydantic types, including chaining, context usage, custom resolvers, and async extensions.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 26, 2026

Reviewer's Guide

Enables 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

Change Details Files
Propagate field extensions from existing Strawberry fields when building experimental pydantic object types.
  • Extend pydantic dataclass field construction to copy the extensions attribute from any existing field definition.
  • Ensure default empty value for extensions is a list when no existing field is present.
strawberry/experimental/pydantic/object_type.py
Add tests verifying FieldExtension support and behaviors on pydantic-based GraphQL types.
  • Introduce several custom FieldExtension implementations for tracking, transformation, masking, context-based access, and async resolution.
  • Cover extension invocation on pydantic-backed fields, including chained extensions, fields with custom resolvers, non-auto fields, and async resolve paths.
  • Assert both data shape and side effects (e.g., call logs, masking behavior).
tests/experimental/pydantic/test_field_extensions.py
Document the new behavior and clean up example formatting in existing docs/changelog.
  • Add a patch RELEASE entry describing FieldExtension support for experimental pydantic types with concrete usage examples.
  • Tighten/inline some GraphQL execution examples and remove superfluous blank lines in various docs and changelog snippets for consistency.
RELEASE.md
CHANGELOG.md
docs/extensions/query-depth-limiter.md
docs/general/subscriptions.md
docs/guides/pagination/connections.md
docs/integrations/channels.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@botberry
Copy link
Member

botberry commented Jan 26, 2026

Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:


This release adds support for field extensions in experimental pydantic types.

Previously, when using @strawberry.experimental.pydantic.type() decorator, field extensions defined with strawberry.field(extensions=[...]) were not being propagated to the generated Strawberry fields. This meant extensions like authentication, caching, or result transformation couldn't be used with pydantic-based types.

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:

🆕 Release (next) is out! Thanks to @Seetku for the PR 👏

Get it here 👉 https://strawberry.rocks/release/(next)

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a 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 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.
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.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@XChikuX
Copy link
Contributor Author

XChikuX commented Jan 26, 2026

@patrick91 @bellini666 @DoctorJohn 1 line change that doesn't break any existing tests.
Hoping to get it reviewed soon :)

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 26, 2026

Greptile Overview

Greptile Summary

Adds field extension support to experimental pydantic types by forwarding the extensions attribute when building Strawberry fields from pydantic models. The implementation follows the established pattern used for permission_classes and directives, adding a single line (line 101) to preserve extensions from existing field definitions.

Key Changes:

  • Modified strawberry/experimental/pydantic/object_type.py:101 to include extensions=existing_field.extensions if existing_field else []
  • Added comprehensive test coverage with 7 test cases covering various scenarios (basic usage, transformations, chaining, context access, custom resolvers, and async extensions)
  • Added clear documentation in RELEASE.md with practical examples
  • Incidental formatting improvements across documentation files (simplified string expressions, removed extra blank lines)

Testing:
The test suite thoroughly validates the feature across multiple scenarios including edge cases like fields with custom resolvers and async extensions. All tests follow the custom instruction to use correct instances and values.

Confidence Score: 5/5

  • This PR is safe to merge with no risk
  • The implementation is minimal (one-line change), follows the exact same pattern as existing field properties (permission_classes, directives), has comprehensive test coverage with 7 different test cases, and includes clear documentation with examples. The change is backward-compatible and only enables a previously missing feature without modifying any existing behavior.
  • No files require special attention

Important Files Changed

Filename Overview
strawberry/experimental/pydantic/object_type.py Added extensions field forwarding to _build_dataclass_creation_fields, matching the existing pattern for permission_classes and directives
tests/experimental/pydantic/test_field_extensions.py Comprehensive test suite covering basic extensions, transformations, chaining, context access, custom resolvers, and async extensions
RELEASE.md Clear documentation with practical examples demonstrating field extension usage with pydantic types

Sequence Diagram

sequenceDiagram
    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
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a 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

Edit Code Review Agent Settings | Greptile

@codspeed-hq
Copy link

codspeed-hq bot commented Jan 26, 2026

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing XChikuX:main (3c8902c) with main (d94d6b5)

Open in CodSpeed

@patrick91
Copy link
Member

thank you! can you fix the pre-commit check? 😊

@XChikuX
Copy link
Contributor Author

XChikuX commented Jan 26, 2026

@patrick91 Done

Copy link
Member

@patrick91 patrick91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one 😊

@patrick91 patrick91 merged commit 11e7115 into strawberry-graphql:main Jan 26, 2026
83 checks passed
@XChikuX XChikuX mentioned this pull request Jan 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants