Skip to content

Commit d9bc9ce

Browse files
committed
fix: fix Maybe with future annotations
Fix #4004
1 parent 513c7cc commit d9bc9ce

File tree

5 files changed

+83
-33
lines changed

5 files changed

+83
-33
lines changed

RELEASE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Release type: patch
2+
3+
This release fixes the usage of `strawnerry.Maybe` inside modules using `from __future__ import annotations`

poetry.lock

Lines changed: 2 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ dev = [
8888
"pyinstrument (>=4.0.0)",
8989
"pytest (>=7.2,<8.0)",
9090
"pytest-asyncio (>=0.20.3)",
91-
"pytest-codspeed (>=3.0.0)",
9291
"pytest-cov (>=4.0.0,<5.0.0)",
9392
"pytest-emoji (>=0.2.0,<0.3.0)",
9493
"pytest-mock (>=3.10,<4.0)",

strawberry/types/maybe.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import re
12
import typing
23
from typing import TYPE_CHECKING, Any, Generic, TypeAlias, TypeVar, Union
34

@@ -36,7 +37,16 @@ def __bool__(self) -> bool:
3637
class Maybe(Generic[T]): ...
3738

3839

40+
_maybe_re = re.compile(r"^(?:strawberry\.)?Maybe\[(.+)\]$")
41+
42+
3943
def _annotation_is_maybe(annotation: Any) -> bool:
44+
if isinstance(annotation, str):
45+
# Ideally we would try to evaluate the annotation, but the args inside
46+
# may still not be available, as the module is still being constructed.
47+
# Checking for the pattern should be good enough for now.
48+
return _maybe_re.match(annotation) is not None
49+
4050
return (orig := typing.get_origin(annotation)) and orig is Maybe
4151

4252

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from __future__ import annotations
2+
3+
from textwrap import dedent
4+
5+
import strawberry
6+
from strawberry import Maybe
7+
8+
9+
def test_maybe_annotation_from_strawberry():
10+
global MyInput
11+
try:
12+
13+
@strawberry.input
14+
class MyInput:
15+
my_value: strawberry.Maybe[str]
16+
17+
@strawberry.type
18+
class Query:
19+
@strawberry.field
20+
def test(self, my_input: MyInput) -> str:
21+
return "OK"
22+
23+
schema = strawberry.Schema(query=Query)
24+
expected_schema = dedent("""
25+
input MyInput {
26+
myValue: String
27+
}
28+
29+
type Query {
30+
test(myInput: MyInput!): String!
31+
}
32+
""").strip()
33+
assert str(schema) == expected_schema
34+
35+
assert MyInput()
36+
finally:
37+
del MyInput
38+
39+
40+
def test_maybe_annotation_directly():
41+
global MyInput
42+
try:
43+
44+
@strawberry.input
45+
class MyInput:
46+
my_value: Maybe[str]
47+
48+
@strawberry.type
49+
class Query:
50+
@strawberry.field
51+
def test(self, my_input: MyInput) -> str:
52+
return "OK"
53+
54+
schema = strawberry.Schema(query=Query)
55+
expected_schema = dedent("""
56+
input MyInput {
57+
myValue: String
58+
}
59+
60+
type Query {
61+
test(myInput: MyInput!): String!
62+
}
63+
""").strip()
64+
assert str(schema) == expected_schema
65+
66+
assert MyInput()
67+
finally:
68+
del MyInput

0 commit comments

Comments
 (0)