NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1727 most downloaded on PyPI
A library for creating GraphQL APIs
Last release today
30 Sep 2026
Ships fairly regularly
a new release about every 3 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
8 years old
1115 releases · first in 2019
Updates the MaskErrors extension to the new extension API, which was missed previously.
Updates the MaskErrors extension to the new extension API, which was missed previously.
Contributed by Nikolai Maas via PR #2655
Add full support for forward references, specially when using from __future__ import annotations .
Add full support for forward references, specially when using from future import annotations .
Before the following would fail on python versions older than 3.10:
from future import annotations
import strawberry
@strawberry.type
class Query :
foo: str | None
Also, this would fail in any python versions:
from future import annotations
from typing import Annotated
import strawberry
@strawberry.type
class Query :
foo: Annotated[ str , "some annotation" ]
Now both of these cases are supported. Please open an issue if you find any edge cases that are still not supported.
Contributed by Thiago Bellini Ribeiro via PR #2592
One column per quarter.
Fix interface duplication leading to schema compilation error in multiple inheritance scenarios (i.e. “Diamond Problem” inheritance)
Fix interface duplication leading to schema compilation error in multiple inheritance scenarios (i.e. “Diamond Problem” inheritance)
Thank you @mzhu22 for the thorough bug report!
Contributed by San Kilkis via PR #2647
This release introduces a breaking change to make pydantic default behavior consistent with normal strawberry types. This changes the schema generated…
This release introduces a breaking change to make pydantic default behavior consistent with normal strawberry types. This changes the schema generated for pydantic types, that are required, and have default values. Previously pydantic type with a default, would get converted to a strawberry type that is not required. This is now fixed, and the schema will now correctly show the type as required.
import pydantic
import strawberry
class UserPydantic ( pydantic . BaseModel ):
name: str = "James"
@strawberry.experimental.pydantic.type (UserPydantic, all_fields = True )
class User : ...
@strawberry.type
class Query :
a: User = strawberry.field()
@strawberry.field
def a ( self ) -> User:
return User()
The schema is now
type Query {
a: User!
}
type User {
name: String! // String! rather than String previously
}
Contributed by James Chua via PR #2623
This release covers an edge case where the following would not give a nice error.
This release covers an edge case where the following would not give a nice error.
some_field: "Union[list[str], SomeType]]"
Fixes #2591
Contributed by ניר via PR #2593
Provide close reason to ASGI websocket as specified by ASGI 2.3
Provide close reason to ASGI websocket as specified by ASGI 2.3
Contributed by Kristján Valur Jónsson via PR #2639
This release adds support for list arguments in operation directives.
This release adds support for list arguments in operation directives.
The following is now supported:
@strawberry.directive ( locations =[DirectiveLocation.FIELD])
def append_names (
value : DirectiveValue[ str ], names : List[ str ]
): # note the usage of List here
return f " { value } { ', ' .join(names) } "
Contributed by chenyijian via PR #2632
Adds support for a custom field using the approach specified in issue #2168 . Field Extensions may be used to change the way how fields work and what
Adds support for a custom field using the approach specified in issue #2168 . Field Extensions may be used to change the way how fields work and what they return. Use cases might include pagination, permissions or other behavior modifications.
from strawberry.extensions import FieldExtension
class UpperCaseExtension ( FieldExtension ):
async def resolve_async (
self ,
next : Callable[..., Awaitable[Any]],
source : Any,
info : strawberry.Info,
** kwargs ,
):
result = await next (source, info, **kwargs)
return str (result).upper()
@strawberry.type
class Query :
@strawberry.field ( extensions =[UpperCaseExtension()])
async def string ( self ) -> str :
return "This is a test!!"
query {
string
}
{
"string" : "THIS IS A TEST!!"
}
Contributed by Erik Wrede via PR #2567
Ensure that no other messages follow a “complete” or “error” message for an operation in the graphql-transport-ws protocol.
Ensure that no other messages follow a “complete” or “error” message for an operation in the graphql-transport-ws protocol.
Contributed by Kristján Valur Jónsson via PR #2600
Calling ChannelsConsumer.channel_listen multiple times will now pass along the messages being listened for to multiple callers, rather than only one o
Calling ChannelsConsumer.channel_listen multiple times will now pass along the messages being listened for to multiple callers, rather than only one of the callers, which was the old behaviour.
This resolves an issue where creating multiple GraphQL subscriptions using a single websocket connection could result in only one of those subscriptions (in a non-deterministic order) being triggered if they are listening for channel layer messages of the same type.
Contributed by James Thorniley via PR #2525
Importing Extension from strawberry.extensions will now raise a deprecation warning.
Rename Extension to SchemaExtension to pave the way for FieldExtensions. Importing Extension from strawberry.extensions will now raise a deprecation warning.
Before:
from strawberry.extensions import Extension
After:
from strawberry.extensions import SchemaExtension
Contributed by Jonathan Kim via PR #2574
This releases adds support for Mypy 1.1.1
This releases adds support for Mypy 1.1.1
Contributed by Patrick Arminio via PR #2616
This release changes how extension hooks are defined. The new style hooks are more flexible and allow to run code before and after the execution.
This release changes how extension hooks are defined. The new style hooks are more flexible and allow to run code before and after the execution.
The old style hooks are still supported but will be removed in future releases.
Before:
def on_executing_start ( self ): # Called before the execution start
...
def on_executing_end ( self ): # Called after the execution ends
...
After
def on_execute ( self ):
yield
Contributed by ניר via PR #2428
Nothing published for this version
Add a type annotation to strawberry.fastapi.BaseContext ’s __init__ method so that it can be used without mypy raising an error.
Add a type annotation to strawberry.fastapi.BaseContext ’s init method so that it can be used without mypy raising an error.
Contributed by Martin Winkel via PR #2581
Version 1.5.10 of GraphiQL disabled introspection for deprecated arguments because it wasn’t supported by all GraphQL server versions. This PR enables…
Version 1.5.10 of GraphiQL disabled introspection for deprecated arguments because it wasn’t supported by all GraphQL server versions. This PR enables it so that deprecated arguments show up again in GraphiQL.
Contributed by Jonathan Kim via PR #2575
Throw proper exceptions when Unions are created with invalid types
Throw proper exceptions when Unions are created with invalid types
Previously, using Lazy types inside of Unions would raise unexpected, unhelpful errors.
Contributed by ignormies via PR #2540
This releases adds support for Apollo Federation 2.1, 2.2 and 2.3.
This releases adds support for Apollo Federation 2.1, 2.2 and 2.3.
This includes support for @composeDirective and @interfaceObject , we expose directives for both, but we also have shortcuts, for example to use @composeDirective with a custom schema directive, you can do the following:
@strawberry.federation.schema_directive (
locations =[Location.OBJECT], name = "cacheControl" , compose = True
)
class CacheControl :
max_age: int
The compose=True makes so that this directive is included in the supergraph schema.
For @interfaceObject we introduced a new @strawberry.federation.interface_object decorator. This works like @strawberry.federation.type , but it adds, the appropriate directive, for example:
@strawberry.federation.interface_object ( keys =[ "id" ])
class SomeInterface :
id : strawberry.ID
generates the following type:
type SomeInterface @key ( fields : "id" ) @interfaceObject {
id : ID !
}
Contributed by Patrick Arminio via PR #2549
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
This release fixes a regression introduce in version 0.156.2 that would make Mypy throw an error in the following code:
This release fixes a regression introduce in version 0.156.2 that would make Mypy throw an error in the following code:
import strawberry
@strawberry.type
class Author :
name: str
@strawberry.type
class Query :
@strawberry.field
async def get_authors ( self ) -> list[Author]:
return [Author( name = "Michael Crichton" )]
Contributed by Patrick Arminio via PR #2535
This release adds support for Mypy 1.0
This release adds support for Mypy 1.0
Contributed by Patrick Arminio via PR #2516
This release updates the typing for the resolver argument in strawberry.field i to support async resolvers. This means that now you won’t get any type
This release updates the typing for the resolver argument in strawberry.field i to support async resolvers. This means that now you won’t get any type error from Pyright when using async resolver, like the following example:
import strawberry
async def get_user_age () -> int :
return 0
@strawberry.type
class User :
name: str
age: int = strawberry.field( resolver =get_user_age)
Contributed by Patrick Arminio via PR #2528
Add GraphQLWebsocketCommunicator for testing websockets on channels. i.e:
Add GraphQLWebsocketCommunicator for testing websockets on channels. i.e:
import pytest
from strawberry.channels.testing import GraphQLWebsocketCommunicator
from myapp.asgi import application
@pytest.fixture
async def gql_communicator ():
async with GraphQLWebsocketCommunicator(
application =application, path = "/graphql"
) as client:
yield client
async def test_subscribe_echo ( gql_communicator ):
async for res in gql_communicator.subscribe(
query = 'subscription { echo(message: "Hi") }'
):
assert res.data == { "echo" : "Hi" }
Contributed by ניר via PR #2458
This release adds support for specialized generic types. Before, the following code would give an error, saying that T was not provided to the generic
This release adds support for specialized generic types. Before, the following code would give an error, saying that T was not provided to the generic type:
@strawberry.type
class Foo (Generic[T]):
some_var: T
@strawberry.type
class IntFoo (Foo[ int ]): ...
@strawberry.type
class Query :
int_foo: IntFoo
Also, because the type is already specialized, Int won’t get inserted to its name, meaning it will be exported to the schema with a type name of IntFoo and not IntIntFoo .
For example, this query:
@strawberry.type
class Query :
int_foo: IntFoo
str_foo: Foo[ str ]
Will generate a schema like this:
type IntFoo {
someVar : Int !
}
type StrFoo {
someVar : String !
}
type Query {
intFoo : IntFoo !
strfoo : StrFoo !
}
Contributed by Thiago Bellini Ribeiro via PR #2517
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fix file not found error when exporting schema with lazy types from CLI #2469
Fix file not found error when exporting schema with lazy types from CLI #2469
Contributed by San Kilkis via PR #2512
Fix missing custom resolve_reference for using pydantic with federation
Fix missing custom resolve_reference for using pydantic with federation
i.e:
import typing
from pydantic import BaseModel
import strawberry
from strawberry.federation.schema_directives import Key
class ProductInDb ( BaseModel ):
upc: str
name: str
@strawberry.experimental.pydantic.type (
model =ProductInDb, directives =[Key( fields = "upc" , resolvable = True )]
)
class Product :
upc: str
name: str
@ classmethod
def resolve_reference ( cls , upc ):
return Product( upc =upc, name = "" )
Contributed by filwaline via PR #2503
This release fixes a bug in subscriptions using the graphql-transport-ws protocol where the conversion of the NextMessage object to a dictionary took
This release fixes a bug in subscriptions using the graphql-transport-ws protocol where the conversion of the NextMessage object to a dictionary took an unnecessary amount of time leading to an increase in CPU usage.
Contributed by rjwills28 via PR #2481
A link to the changelog has been added to the package metadata, so it shows up on PyPI.
A link to the changelog has been added to the package metadata, so it shows up on PyPI.
Contributed by Tom Most via PR #2490
This release adds a new utility function to convert a Strawberry object to a dictionary.
This release adds a new utility function to convert a Strawberry object to a dictionary.
You can use strawberry.asdict(...) function to convert a Strawberry object to a dictionary:
@strawberry.type
class User :
name: str
age: int
user_dict = strawberry.asdict(User( name = "Lorem" , age = 25 ))
Note: This function uses the dataclasses.asdict function under the hood, so you can safely replace dataclasses.asdict with strawberry.asdict in your code. This will make it easier to update your code to newer versions of Strawberry if we decide to change the implementation.
Contributed by Haze Lee via PR #2417
Fix DuplicatedTypeName exception being raised on generics declared using strawberry.lazy . Previously the following would raise:
Fix DuplicatedTypeName exception being raised on generics declared using strawberry.lazy . Previously the following would raise:
issue_2397.py
from typing import Annotated, Generic, TypeVar
import strawberry
T = TypeVar( "T" )
@strawberry.type
class Item :
name: str
@strawberry.type
class Edge (Generic[T]):
node: T
@strawberry.type
class Query :
edges_normal: Edge[Item]
edges_lazy: Edge[Annotated[ "Item" , strawberry.lazy( "issue_2397" )]]
if name == "main" :
schema = strawberry.Schema( query =Query)
Contributed by pre-commit-ci via PR #2462
Support constrained float field types in Pydantic models.
Support constrained float field types in Pydantic models.
i.e.
import pydantic
class Model ( pydantic . BaseModel ):
field: pydantic.confloat( le = 100.0 )
equivalent_field: float = pydantic.Field( le = 100.0 )
Contributed by Etienne Wodey via PR #2455
This change allows clients to define connectionParams when making Subscription requests similar to the way Apollo-Server does it.
This change allows clients to define connectionParams when making Subscription requests similar to the way Apollo-Server does it.
With Apollo-Client (React) as an example, define a Websocket Link:
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
const wsLink = new GraphQLWsLink(createClient({
url: 'ws://localhost:4000/subscriptions',
connectionParams: {
authToken: user.authToken,
},
}));
and the JSON passed to connectionParams here will appear within Strawberry’s context as the connection_params attribute when accessing info.context within a Subscription resolver.
Contributed by Tommy Smith via PR #2380
This release adds support for updating (or adding) the query document inside an extension’s on_request_start method.
This release adds support for updating (or adding) the query document inside an extension’s on_request_start method.
This can be useful for implementing persisted queries. The old behavior of returning a 400 error if no query is present in the request is still supported.
Example usage:
from strawberry.extensions import Extension
def get_doc_id ( request ) -> str :
"""Implement this to get the document ID using your framework's request object"""
...
def load_persisted_query ( doc_id : str ) -> str :
"""Implement this load a query by document ID. For example, from a database."""
...
class PersistedQuery ( Extension ):
def on_request_start ( self ):
request = self .execution_context.context.request
doc_id = get_doc_id(request)
self .execution_context.query = load_persisted_query(doc_id)
Contributed by James Thorniley via PR #2431
This release adds support for FastAPI 0.89.0
This release adds support for FastAPI 0.89.0
Contributed by Patrick Arminio via PR #2440
This release fixes @strawberry.experimental.pydantic.type and adds support for the metadata attribute on fields.
This release fixes @strawberry.experimental.pydantic.type and adds support for the metadata attribute on fields.
Example:
@strawberry.experimental.pydantic.type ( model =User)
class UserType :
private: strawberry.auto = strawberry.field( metadata ={ "admin_only" : True })
public: strawberry.auto
Contributed by Huy Z via PR #2415
This release fixes an issue that prevented using generic that had a field of type enum. The following works now:
This release fixes an issue that prevented using generic that had a field of type enum. The following works now:
@strawberry.enum
class EstimatedValueEnum ( Enum ):
test = "test"
testtest = "testtest"
@strawberry.type
class EstimatedValue (Generic[T]):
value: T
type : EstimatedValueEnum
@strawberry.type
class Query :
@strawberry.field
def estimated_value ( self ) -> Optional[EstimatedValue[ int ]]:
return EstimatedValue( value = 1 , type =EstimatedValueEnum.test)
Contributed by Patrick Arminio via PR #2411
This PR adds a new graphql_type parameter to strawberry.field that allows you to explicitly set the field type. This parameter will take preference ov
This PR adds a new graphql_type parameter to strawberry.field that allows you to explicitly set the field type. This parameter will take preference over the resolver return type and the class field type.
For example:
@strawberry.type
class Query :
a: float = strawberry.field( graphql_type = str )
b = strawberry.field( graphql_type = int )
@strawberry.field ( graphql_type = float )
def c ( self ) -> str :
return "3.4"
schema = strawberry.Schema(Query)
str (schema) == """
type Query {
a: String!
b: Int!
c: Float!
}
"""
Contributed by Jonathan Kim via PR #2313
Fixed field resolvers with nested generic return types (e.g. list , Optional , Union etc) raising TypeErrors. This means resolver factory methods can
Fixed field resolvers with nested generic return types (e.g. list , Optional , Union etc) raising TypeErrors. This means resolver factory methods can now be correctly type hinted.
For example the below would previously error unless you ommited all the type hints on resolver_factory and actual_resolver functions.
from typing import Callable, Optional, Type, TypeVar
import strawberry
@strawberry.type
class Cat :
name: str
T = TypeVar( "T" )
def resolver_factory ( type_ : Type[T]) -> Callable[[], Optional[T]]:
def actual_resolver () -> Optional[T]:
...
return actual_resolver
@strawberry.type
class Query :
cat: Cat = strawberry.field(resolver_factory(Cat))
schema = strawberry.Schema( query =Query)
Contributed by Tim OSullivan via PR #1900
This release implements the ability to use custom caching for dataloaders. It also allows to provide a cache_key_fn to the dataloader. This function i
This release implements the ability to use custom caching for dataloaders. It also allows to provide a cache_key_fn to the dataloader. This function is used to generate the cache key for the dataloader. This is useful when you want to use a custom hashing function for the cache key.
Contributed by Aman Choudhary via PR #2394
This release fixes support for generics in arguments, see the following example:
This release fixes support for generics in arguments, see the following example:
T = TypeVar( "T" )
@strawberry.type
class Node (Generic[T]):
@strawberry.field
def data ( self , arg : T) -> T: # arg is also generic
return arg
Contributed by A. Coady via PR #2316
This release improves the performance of rich exceptions on custom scalars by changing how frames are fetched from the call stack. Before the change,
This release improves the performance of rich exceptions on custom scalars by changing how frames are fetched from the call stack. Before the change, custom scalars were using a CPU intensive call to the inspect module to fetch frame info which could lead to serious CPU spikes.
Contributed by Paulo Amaral via PR #2390
This release does some internal refactoring of the HTTP views, hopefully it doesn’t affect anyone. It mostly changes the status codes returned in case
This release does some internal refactoring of the HTTP views, hopefully it doesn’t affect anyone. It mostly changes the status codes returned in case of errors (e.g. bad JSON, missing queries and so on).
It also improves the testing, and adds an entirely new test suite for the HTTP views, this means in future we’ll be able to keep all the HTTP views in sync feature-wise.
Contributed by Patrick Arminio via PR #1840
This release changes the get_context , get_root_value and process_result methods of the Flask async view to be async functions. This allows you to use
This release changes the get_context , get_root_value and process_result methods of the Flask async view to be async functions. This allows you to use async code in these methods.
Contributed by Patrick Arminio via PR #2388
It also deprecates json_encoder and json_dumps_params in the Django and Sanic views, encode_json should be used instead.
This release introduces a encode_json method on all the HTTP integrations. This method allows to customize the encoding of the JSON response. By default we use json.dumps but you can override this method to use a different encoder.
It also deprecates json_encoder and json_dumps_params in the Django and Sanic views, encode_json should be used instead.
Contributed by Patrick Arminio via PR #2272
This release updates the Sanic integration and includes some breaking changes. You might need to update your code if you are customizing get_context o…
This release updates the Sanic integration and includes some breaking changes. You might need to update your code if you are customizing get_context or process_result
This release introduced improved errors! Now, when you have a syntax error in your code, you’ll get a nice error message with a line number and a poin
This release introduced improved errors! Now, when you have a syntax error in your code, you’ll get a nice error message with a line number and a pointer to the exact location of the error. ✨
This is a huge improvement over the previous behavior, which was providing a stack trace with no clear indication of where the error was. 🙈
You can enable rich errors by installing Strawberry with the cli extra:
Terminal window
pip install "strawberry-graphql[cli]"
Contributed by Patrick Arminio via PR #2027
Nothing published for this version
Nothing published for this version
Nothing published for this version
This release fixes an issue with type duplication of generics.
This release fixes an issue with type duplication of generics.
You can now use a lazy type with a generic even if the original type was already used with that generic in the schema.
Example:
@strawberry.type
class Query :
regular: Edge[User]
lazy: Edge[Annotated[ "User" , strawberry.lazy( ".user" )]]
Contributed by Dmitry Semenov via PR #2381
Generic types are now allowed in the schema’s extra types.
Generic types are now allowed in the schema’s extra types.
T = TypeVar( "T" )
@strawberry.type
class Node (Generic[T]):
field: T
@strawberry.type
class Query :
name: str
schema = strawberry.Schema(Query, types =[Node[ int ]])
Contributed by A. Coady via PR #2294
Your coding agent can read these notes before it upgrades. Set up the MCP server →