Skip to content

Commit 9fc011d

Browse files
committed
Merge branch 'main' into feature/314
2 parents 5de6b7c + 50a8347 commit 9fc011d

File tree

96 files changed

+2532
-693
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+2532
-693
lines changed

.pre-commit-config.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.9.7
3+
rev: v0.11.8
44
hooks:
55
- id: ruff-format
66
exclude: ^tests/\w+/snapshots/
@@ -36,3 +36,8 @@ repos:
3636
- id: blacken-docs
3737
args: [--skip-errors]
3838
files: '\.(rst|md|markdown|py|mdx)$'
39+
40+
- repo: https://github.com/ComPWA/taplo-pre-commit
41+
rev: v0.9.3
42+
hooks:
43+
- id: taplo-format

CHANGELOG.md

Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,338 @@
11
CHANGELOG
22
=========
33

4+
0.268.0 - 2025-05-10
5+
--------------------
6+
7+
This release renames the generated type from `GlobalID` to `ID` in the GraphQL
8+
schema.
9+
10+
This means that when using `relay.Node`, like in this example:
11+
12+
```python
13+
@strawberry.type
14+
class Fruit(relay.Node):
15+
code: relay.NodeID[int]
16+
name: str
17+
```
18+
19+
You'd create a GraphQL type that looks like this:
20+
21+
```graphql
22+
type Fruit implements Node {
23+
id: ID!
24+
name: String!
25+
}
26+
```
27+
28+
while previously you'd get this:
29+
30+
```graphql
31+
type Fruit implements Node {
32+
id: GlobalID!
33+
name: String!
34+
}
35+
```
36+
37+
The runtime behaviour is still the same, so if you want to use `GlobalID` in
38+
Python code, you can still do so, for example:
39+
40+
```python
41+
@strawberry.type
42+
class Mutation:
43+
@strawberry.mutation
44+
@staticmethod
45+
async def update_fruit_weight(id: relay.GlobalID, weight: float) -> Fruit:
46+
# while `id` is a GraphQL `ID` type, here is still an instance of `relay.GlobalID`
47+
fruit = await id.resolve_node(info, ensure_type=Fruit)
48+
fruit.weight = weight
49+
return fruit
50+
```
51+
52+
If you want to revert this change, and keep `GlobalID` in the schema, you can
53+
use the following configuration:
54+
55+
```python
56+
schema = strawberry.Schema(
57+
query=Query, config=StrawberryConfig(relay_use_legacy_global_id=True)
58+
)
59+
```
60+
61+
Contributed by [Patrick Arminio](https://github.com/patrick91) via [PR #3853](https://github.com/strawberry-graphql/strawberry/pull/3853/)
62+
63+
64+
0.267.0 - 2025-05-10
65+
--------------------
66+
67+
This release adds support to use `strawberry.Parent` with future annotations.
68+
69+
For example, the following code will now work as intended:
70+
71+
```python
72+
from __future__ import annotations
73+
74+
75+
def get_full_name(user: strawberry.Parent[User]) -> str:
76+
return f"{user.first_name} {user.last_name}"
77+
78+
79+
@strawberry.type
80+
class User:
81+
first_name: str
82+
last_name: str
83+
full_name: str = strawberry.field(resolver=get_full_name)
84+
85+
86+
@strawberry.type
87+
class Query:
88+
@strawberry.field
89+
def user(self) -> User:
90+
return User(first_name="John", last_name="Doe")
91+
92+
93+
schema = strawberry.Schema(query=Query)
94+
```
95+
96+
Or even when not using future annotations, but delaying the evaluation of `User`, like:
97+
98+
99+
```python
100+
# Note the User being delayed by passing it as a string
101+
def get_full_name(user: strawberry.Parent["User"]) -> str:
102+
return f"{user.first_name} {user.last_name}"
103+
104+
105+
@strawberry.type
106+
class User:
107+
first_name: str
108+
last_name: str
109+
full_name: str = strawberry.field(resolver=get_full_name)
110+
111+
112+
@strawberry.type
113+
class Query:
114+
@strawberry.field
115+
def user(self) -> User:
116+
return User(first_name="John", last_name="Doe")
117+
118+
119+
schema = strawberry.Schema(query=Query)
120+
```
121+
122+
Contributed by [Thiago Bellini Ribeiro](https://github.com/bellini666) via [PR #3851](https://github.com/strawberry-graphql/strawberry/pull/3851/)
123+
124+
125+
0.266.1 - 2025-05-06
126+
--------------------
127+
128+
This release adds a new (preferable) way to handle optional updates. Up until
129+
now when you wanted to inffer if an input value was null or absent you'd use
130+
`strawberry.UNSET` which is a bit cumbersome and error prone.
131+
132+
Now you can use `strawberry.Maybe` to identify if a
133+
value was provided or not.
134+
135+
e.g.
136+
137+
```python
138+
import strawberry
139+
140+
141+
@strawberry.type
142+
class User:
143+
name: str
144+
phone: str | None
145+
146+
147+
@strawberry.input
148+
class UpdateUserInput:
149+
name: str
150+
phone: strawberry.Maybe[str]
151+
152+
153+
@strawberry.type
154+
class Mutation:
155+
def update_user(self, input: UpdateUserInput) -> None:
156+
reveal_type(input.phone) # strawberry.Some[str | None] | None
157+
158+
if input.phone:
159+
reveal_type(input.phone.value) # str | None
160+
161+
update_user_phone(input.phone.value)
162+
```
163+
164+
Or, if you can use pattern matching:
165+
166+
```python
167+
@strawberry.type
168+
class Mutation:
169+
def update_user(self, input: UpdateUserInput) -> None:
170+
match input.phone:
171+
case strawberry.Some(value=value):
172+
update_user_phone(input.phone.value)
173+
```
174+
175+
You can also use `strawberry.Maybe` as a field argument like so
176+
177+
```python
178+
import strawberry
179+
180+
181+
@strawberry.field
182+
def filter_users(self, phone: strawberry.Maybe[str] = None) -> list[User]:
183+
if phone:
184+
return filter_users_by_phone(phone.value)
185+
186+
return get_all_users()
187+
```
188+
189+
Contributed by [ניר](https://github.com/nrbnlulu) via [PR #3791](https://github.com/strawberry-graphql/strawberry/pull/3791/)
190+
191+
192+
0.266.0 - 2025-04-19
193+
--------------------
194+
195+
This release adds support for custom names in enum values using the `name` parameter in `strawberry.enum_value`.
196+
197+
This allows you to specify a different name for an enum value in the GraphQL schema while keeping the original Python enum member name. For example:
198+
199+
```python
200+
@strawberry.enum
201+
class IceCreamFlavour(Enum):
202+
VANILLA = "vanilla"
203+
CHOCOLATE_COOKIE = strawberry.enum_value("chocolate", name="chocolateCookie")
204+
```
205+
206+
This will produce a GraphQL schema with the custom name:
207+
208+
```graphql
209+
enum IceCreamFlavour {
210+
VANILLA
211+
chocolateCookie
212+
}
213+
```
214+
215+
Contributed by [Patrick Arminio](https://github.com/patrick91) via [PR #3841](https://github.com/strawberry-graphql/strawberry/pull/3841/)
216+
217+
218+
0.265.1 - 2025-04-15
219+
--------------------
220+
221+
Fix bug where files would be converted into io.BytesIO when using the sanic GraphQLView
222+
instead of using the sanic File type
223+
224+
Contributed by [Maypher](https://github.com/Maypher) via [PR #3751](https://github.com/strawberry-graphql/strawberry/pull/3751/)
225+
226+
227+
0.265.0 - 2025-04-15
228+
--------------------
229+
230+
This release adds support for using strawberry.union with generics, like in this
231+
example:
232+
233+
```python
234+
@strawberry.type
235+
class ObjectQueries[T]:
236+
@strawberry.field
237+
def by_id(
238+
self, id: strawberry.ID
239+
) -> Union[T, Annotated[NotFoundError, strawberry.union("ByIdResult")]]: ...
240+
241+
242+
@strawberry.type
243+
class Query:
244+
@strawberry.field
245+
def some_type_queries(self, id: strawberry.ID) -> ObjectQueries[SomeType]: ...
246+
```
247+
248+
which, now, creates a correct union type named `SomeTypeByIdResult`
249+
250+
Contributed by [Jacob Allen](https://github.com/enoua5) via [PR #3515](https://github.com/strawberry-graphql/strawberry/pull/3515/)
251+
252+
253+
0.264.1 - 2025-04-15
254+
--------------------
255+
256+
Change pydantic conversion to not load field data unless requested
257+
258+
Contributed by [Mark Moes](https://github.com/Mark90) via [PR #3812](https://github.com/strawberry-graphql/strawberry/pull/3812/)
259+
260+
261+
0.264.0 - 2025-04-12
262+
--------------------
263+
264+
This releases improves support for `relay.Edge` subclasses.
265+
266+
`resolve_edge` now accepts `**kwargs`, so custom fields can be added to your edge classes without wholly
267+
replacing `resolve_edge`:
268+
```python
269+
@strawberry.type(name="Edge", description="An edge in a connection.")
270+
class CustomEdge(relay.Edge[NodeType]):
271+
index: int
272+
273+
@classmethod
274+
def resolve_edge(cls, node: NodeType, *, cursor: Any = None, **kwargs: Any) -> Self:
275+
assert isinstance(cursor, int)
276+
return super().resolve_edge(node, cursor=cursor, index=cursor, **kwargs)
277+
```
278+
279+
You can also specify a custom cursor prefix, in case you want to implement a different
280+
kind of cursor than a plain `ListConnection`:
281+
```python
282+
@strawberry.type(name="Edge", description="An edge in a connection.")
283+
class CustomEdge(relay.Edge[NodeType]):
284+
CURSOR_PREFIX: ClassVar[str] = "mycursor"
285+
```
286+
287+
Contributed by [Take Weiland](https://github.com/diesieben07) via [PR #3836](https://github.com/strawberry-graphql/strawberry/pull/3836/)
288+
289+
290+
0.263.2 - 2025-04-05
291+
--------------------
292+
293+
This release contains a few improvements to how `AsyncGenerators` are handled by
294+
strawberry codebase, ensuring they get properly closed in case of unexpected
295+
errors.
296+
297+
Contributed by [Thiago Bellini Ribeiro](https://github.com/bellini666) via [PR #3834](https://github.com/strawberry-graphql/strawberry/pull/3834/)
298+
299+
300+
0.263.1 - 2025-04-04
301+
--------------------
302+
303+
This releases add support for passing in a custom `TracerProvider` to the `OpenTelemetryExtension`.
304+
305+
Contributed by [Chase Dorsey](https://github.com/cdorsey) via [PR #3830](https://github.com/strawberry-graphql/strawberry/pull/3830/)
306+
307+
308+
0.263.0 - 2025-04-01
309+
--------------------
310+
311+
Adds the ability to include pydantic computed fields when using pydantic.type decorator.
312+
313+
Example:
314+
```python
315+
class UserModel(pydantic.BaseModel):
316+
age: int
317+
318+
@computed_field
319+
@property
320+
def next_age(self) -> int:
321+
return self.age + 1
322+
323+
324+
@strawberry.experimental.pydantic.type(
325+
UserModel, all_fields=True, include_computed=True
326+
)
327+
class User:
328+
pass
329+
```
330+
331+
Will allow `nextAge` to be requested from a user entity.
332+
333+
Contributed by [Tyler Nisonoff](https://github.com/tylernisonoff) via [PR #3798](https://github.com/strawberry-graphql/strawberry/pull/3798/)
334+
335+
4336
0.262.6 - 2025-03-28
5337
--------------------
6338

docs/breaking-changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ title: List of breaking changes and deprecations
44

55
# List of breaking changes and deprecations
66

7+
- [Version 0.268.0 - 10 May 2025](./breaking-changes/0.268.0.md)
78
- [Version 0.249.0 - 18 November 2024](./breaking-changes/0.249.0.md)
89
- [Version 0.243.0 - 25 September 2024](./breaking-changes/0.243.0.md)
910
- [Version 0.240.0 - 10 September 2024](./breaking-changes/0.240.0.md)

0 commit comments

Comments
 (0)