Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8159,7 +8159,6 @@ from typing import Generic, Sequence, TypeVar

import strawberry


T = TypeVar("T")


Expand Down Expand Up @@ -10125,7 +10124,6 @@ from strawberry.asgi import GraphQL
from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL
from api.schema import schema


app = GraphQL(schema, subscription_protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL])
```

Expand Down Expand Up @@ -10735,7 +10733,6 @@ import strawberry
from strawberry.schema import default_validation_rules
from strawberry.tools import depth_limit_validator


# Add the depth limit validator to the list of default validation rules
validation_rules = default_validation_rules + [depth_limit_validator(3)]

Expand Down Expand Up @@ -12289,7 +12286,6 @@ from opentelemetry.sdk.trace.export import (
import strawberry
from strawberry.extensions.tracing import OpenTelemetryExtension


trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
SimpleExportSpanProcessor(ConsoleSpanExporter())
Expand Down
66 changes: 66 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
Release type: patch

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:**

```python
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:**

```python
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()])
```
3 changes: 0 additions & 3 deletions docs/general/subscriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ from strawberry.aiohttp.views import GraphQLView
from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
from api.schema import schema


view = GraphQLView(
schema, subscription_protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL]
)
Expand All @@ -348,7 +347,6 @@ from strawberry.asgi import GraphQL
from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
from api.schema import schema


app = GraphQL(
schema,
subscription_protocols=[
Expand All @@ -374,7 +372,6 @@ django_asgi_app = get_asgi_application()
# for the schema.
from mysite.graphql import schema


application = GraphQLProtocolTypeRouter(
schema,
django_application=django_asgi_app,
Expand Down
3 changes: 0 additions & 3 deletions docs/guides/pagination/connections.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ from typing import Generic, TypeVar

import strawberry


GenericType = TypeVar("GenericType")


Expand All @@ -116,7 +115,6 @@ from typing import Generic, TypeVar

import strawberry


GenericType = TypeVar("GenericType")


Expand Down Expand Up @@ -167,7 +165,6 @@ from typing import Generic, TypeVar

import strawberry


GenericType = TypeVar("GenericType")


Expand Down
2 changes: 0 additions & 2 deletions docs/integrations/channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@ django_asgi_app = get_asgi_application()
# for the schema.
from mysite.graphql import schema


application = GraphQLProtocolTypeRouter(
schema,
django_application=django_asgi_app,
Expand Down Expand Up @@ -273,7 +272,6 @@ django_asgi_app = get_asgi_application()
from chat import routing
from mysite.graphql import schema


gql_http_consumer = AuthMiddlewareStack(GraphQLHTTPConsumer.as_asgi(schema=schema))
gql_ws_consumer = GraphQLWSConsumer.as_asgi(schema=schema)

Expand Down
1 change: 1 addition & 0 deletions strawberry/experimental/pydantic/object_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def _build_dataclass_creation_fields(
existing_field.permission_classes if existing_field else []
),
directives=existing_field.directives if existing_field else (),
extensions=existing_field.extensions if existing_field else [],
metadata=existing_field.metadata if existing_field else {},
)

Expand Down
Loading
Loading