Skip to content
Draft
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
1 change: 1 addition & 0 deletions docs/breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ title: List of breaking changes and deprecations

# List of breaking changes and deprecations

- [Version 0.285.0 - Deprecate StrawberryConfig Class - 30 October 2025](./breaking-changes/0.285.0.md)
- [Version 0.279.0 - 19 August 2025](./breaking-changes/0.279.0.md)
- [Version 0.278.1 - 5 August 2025](./breaking-changes/0.278.1.md)
- [Version 0.268.0 - 10 May 2025](./breaking-changes/0.268.0.md)
Expand Down
57 changes: 57 additions & 0 deletions docs/breaking-changes/0.285.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: 0.285.0 Deprecations
slug: breaking-changes/0.285.0
---

# v0.285.0 Deprecations

In this release, we've simplified the schema configuration API by migrating from
a class-based approach to a dictionary-based approach.

## What Changed

The `StrawberryConfig` class syntax is now **deprecated** and will show a
`DeprecationWarning`. The class will be removed in a future release.

Instead of instantiating a config class, you should now pass a plain Python
dictionary to the `config` parameter when creating a schema.

## Migration

Convert the class instantiation to a dictionary:

**Before (deprecated):**

```python
from strawberry.schema.config import StrawberryConfig

schema = strawberry.Schema(
query=Query,
config=StrawberryConfig(
auto_camel_case=True,
relay_max_results=50,
),
)
```

**After (recommended):**

```python
schema = strawberry.Schema(
query=Query,
config={
"auto_camel_case": True,
"relay_max_results": 50,
},
)
```

The old syntax will continue to work but will show this warning:

```
DeprecationWarning: Using StrawberryConfig as a class is deprecated as of v0.285.0.
Use dictionary syntax instead: config={'auto_camel_case': True}.
```

For more information, see the
[Schema Configurations](../types/schema-configurations.md) documentation.
18 changes: 6 additions & 12 deletions docs/guides/query-batching.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,14 @@ and how to integrate it into your application with an example using FastAPI.

## Enabling Query Batching

To enable query batching in Strawberry, you need to configure the
`StrawberryConfig` when defining your GraphQL schema. The batching configuration
is provided as a typed dictionary. Batching is disabled by default, if no
configuration is provided.
To enable query batching in Strawberry, you need to configure the schema config
when defining your GraphQL schema. The batching configuration is provided as a
dictionary. Batching is disabled by default, if no configuration is provided.

### Basic Configuration

```python
from strawberry.schema.config import StrawberryConfig

config = StrawberryConfig(batching_config={"max_operations": 10})
config = {"batching_config": {"max_operations": 10}}
```

### Configuring Maximum Operations
Expand All @@ -35,9 +32,7 @@ To set a limit on the number of operations in a batch request, use the
`max_operations` key:

```python
from strawberry.schema.config import StrawberryConfig

config = StrawberryConfig(batching_config={"max_operations": 5})
config = {"batching_config": {"max_operations": 5}}
```

When batching is enabled, the server can handle a list of operations
Expand All @@ -52,7 +47,6 @@ Below is an example of how to enable query batching in a FastAPI application:
import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
from strawberry.schema.config import StrawberryConfig


@strawberry.type
Expand All @@ -64,7 +58,7 @@ class Query:

schema = strawberry.Schema(
Query,
config=StrawberryConfig(batching_config={"max_operations": 5}),
config={"batching_config": {"max_operations": 5}},
)

graphql_app = GraphQLRouter(schema)
Expand Down
3 changes: 1 addition & 2 deletions docs/types/defer-and-stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ incremental execution in your schema configuration:

```python
import strawberry
from strawberry.schema.config import StrawberryConfig


@strawberry.type
Expand All @@ -41,7 +40,7 @@ class Query:


schema = strawberry.Schema(
query=Query, config=StrawberryConfig(enable_experimental_incremental_execution=True)
query=Query, config={"enable_experimental_incremental_execution": True}
)
```

Expand Down
38 changes: 19 additions & 19 deletions docs/types/schema-configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,22 @@ title: Schema Configurations

# Schema Configurations

Strawberry allows to customise how the schema is generated by passing
configurations.
Strawberry allows you to customise how the schema is generated by passing
configuration options as a dictionary.

To customise the schema you can create an instance of `StrawberryConfig`, as
shown in the example below:
To customise the schema, you can pass a configuration dictionary to the `config`
parameter, as shown in the example below:

```python
import strawberry

from strawberry.schema.config import StrawberryConfig


@strawberry.type
class Query:
example_field: str


schema = strawberry.Schema(query=Query, config=StrawberryConfig(auto_camel_case=False))
schema = strawberry.Schema(query=Query, config={"auto_camel_case": False})
```

In this case we are disabling the auto camel casing feature, so your output
Expand All @@ -33,6 +31,14 @@ type Query {
}
```

<Note>

**Upgrading from v0.284.0 or earlier?** See the
[v0.285.0 breaking changes](../breaking-changes/0.285.0.md) for migration
instructions if you were using the old `StrawberryConfig` class syntax.

</Note>

## Available configurations

Here's a list of the available configurations:
Expand All @@ -44,7 +50,7 @@ like `example_field` will be converted to `exampleField`. You can disable this
feature by setting `auto_camel_case` to `False`.

```python
schema = strawberry.Schema(query=Query, config=StrawberryConfig(auto_camel_case=False))
schema = strawberry.Schema(query=Query, config={"auto_camel_case": False})
```

### default_resolver
Expand All @@ -58,8 +64,6 @@ resolver.
```python
import strawberry

from strawberry.schema.config import StrawberryConfig


def custom_resolver(obj, field):
try:
Expand All @@ -80,9 +84,7 @@ class Query:
return {"name": "Patrick"}


schema = strawberry.Schema(
query=Query, config=StrawberryConfig(default_resolver=custom_resolver)
)
schema = strawberry.Schema(query=Query, config={"default_resolver": custom_resolver})
```

### relay_max_results
Expand All @@ -91,7 +93,7 @@ By default Strawberry's max limit for relay connections is 100. You can
customise this by setting the `relay_max_results` configuration.

```python
schema = strawberry.Schema(query=Query, config=StrawberryConfig(relay_max_results=50))
schema = strawberry.Schema(query=Query, config={"relay_max_results": 50})
```

### disable_field_suggestions
Expand All @@ -101,9 +103,7 @@ schema. You can disable this feature by setting `disable_field_suggestions` to
`True`.

```python
schema = strawberry.Schema(
query=Query, config=StrawberryConfig(disable_field_suggestions=True)
)
schema = strawberry.Schema(query=Query, config={"disable_field_suggestions": True})
```

### info_class
Expand All @@ -123,7 +123,7 @@ class CustomInfo(Info):
return self.context["response"].headers


schema = strawberry.Schema(query=Query, config=StrawberryConfig(info_class=CustomInfo))
schema = strawberry.Schema(query=Query, config={"info_class": CustomInfo})
```

### enable_experimental_incremental_execution
Expand All @@ -142,7 +142,7 @@ response to be delivered incrementally.

```python
schema = strawberry.Schema(
query=Query, config=StrawberryConfig(enable_experimental_incremental_execution=True)
query=Query, config={"enable_experimental_incremental_execution": True}
)
```

Expand Down
2 changes: 2 additions & 0 deletions strawberry/codemods/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from .annotated_unions import ConvertUnionToAnnotatedUnion
from .config_to_dict import ConvertStrawberryConfigToDict
from .maybe_optional import ConvertMaybeToOptional
from .update_imports import UpdateImportsCodemod

__all__ = [
"ConvertMaybeToOptional",
"ConvertStrawberryConfigToDict",
"ConvertUnionToAnnotatedUnion",
"UpdateImportsCodemod",
]
89 changes: 89 additions & 0 deletions strawberry/codemods/config_to_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from __future__ import annotations

import libcst as cst
import libcst.matchers as m
from libcst.codemod import VisitorBasedCodemodCommand


class ConvertStrawberryConfigToDict(VisitorBasedCodemodCommand):
"""Convert StrawberryConfig() instantiation to dict syntax.

This codemod converts the deprecated class-based StrawberryConfig() syntax
to the new dictionary syntax.

Examples:
# Before:
config = StrawberryConfig()
config = StrawberryConfig(auto_camel_case=True)

# After:
config = {}
config = {"auto_camel_case": True}
"""

DESCRIPTION: str = (
"Converts StrawberryConfig() class instantiation to dictionary syntax"
)

def leave_Call( # noqa: N802
self, original_node: cst.Call, updated_node: cst.Call
) -> cst.BaseExpression:
# Check if this is a StrawberryConfig() call
if not self._is_strawberry_config_call(original_node):
return updated_node

# If no arguments, convert to empty dict {}
if not original_node.args:
return cst.Dict([])

# Convert arguments to dict entries
dict_elements = []
for arg in original_node.args:
# Only handle keyword arguments
if arg.keyword is None:
# Positional arguments not supported, skip this conversion
return updated_node

# Create dict key (string literal from keyword name)
key = cst.SimpleString(f'"{arg.keyword.value}"')

# Create dict value (the argument value)
dict_elements.append(
cst.DictElement(
key=key,
value=arg.value,
)
)

# Return dictionary literal
return cst.Dict(elements=dict_elements)

def _is_strawberry_config_call(self, node: cst.Call) -> bool:
"""Check if this is a call to StrawberryConfig."""
# Check for direct StrawberryConfig() call
if m.matches(node.func, m.Name("StrawberryConfig")):
return True

# Check for strawberry.schema.config.StrawberryConfig()
if m.matches(
node.func,
m.Attribute(
value=m.Attribute(
value=m.Attribute(
value=m.Name("strawberry"),
attr=m.Name("schema"),
),
attr=m.Name("config"),
),
attr=m.Name("StrawberryConfig"),
),
):
return True

# Check for config.StrawberryConfig()
return m.matches(
node.func,
m.Attribute(
attr=m.Name("StrawberryConfig"),
),
)
2 changes: 1 addition & 1 deletion strawberry/extensions/directives.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def process_directive(
field_name=info.field_name,
type_name=info.parent_type.name,
)
arguments[info_parameter.name] = schema.config.info_class(
arguments[info_parameter.name] = schema.config["info_class"](
_raw_info=info, _field=field
)
if value_parameter:
Expand Down
4 changes: 2 additions & 2 deletions strawberry/federation/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def _add_link_for_composed_directive(
return

import_url = directive.compose_options.import_url
name = self.config.name_converter.from_directive(directive)
name = self.config["name_converter"].from_directive(directive)

# import url is required by Apollo Federation, this might change in
# future to be optional, so for now, when it is not passed we
Expand Down Expand Up @@ -290,7 +290,7 @@ def _add_compose_directives(self) -> list["ComposeDirective"]:
)

if is_federation_schema_directive and definition.compose_options:
name = self.config.name_converter.from_directive(definition)
name = self.config["name_converter"].from_directive(definition)

compose_directives.append(
ComposeDirective(
Expand Down
4 changes: 2 additions & 2 deletions strawberry/http/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ def _is_multipart_subscriptions(
def _validate_batch_request(
self, request_data: list[GraphQLRequestData], protocol: str
) -> None:
if self.schema.config.batching_config is None:
if self.schema.config["batching_config"] is None:
raise HTTPException(400, "Batching is not enabled")

if protocol == "multipart-subscription":
raise HTTPException(
400, "Batching is not supported for multipart subscriptions"
)

if len(request_data) > self.schema.config.batching_config["max_operations"]:
if len(request_data) > self.schema.config["batching_config"]["max_operations"]:
raise HTTPException(400, "Too many operations")


Expand Down
Loading
Loading