Skip to content

Commit 0d880b7

Browse files
nrbnlulupre-commit-ci[bot]patrick91
authored
Add support for using raw Python enum types in schema (#3639)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
1 parent 596461b commit 0d880b7

File tree

10 files changed

+94
-129
lines changed

10 files changed

+94
-129
lines changed

.alexrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
"special",
1313
"primitive",
1414
"invalid",
15-
"crash",
15+
"crash"
1616
]
1717
}

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
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.6.8
3+
rev: v0.6.9
44
hooks:
55
- id: ruff-format
66
exclude: ^tests/\w+/snapshots/
@@ -20,7 +20,7 @@ repos:
2020
files: '^docs/.*\.mdx?$'
2121

2222
- repo: https://github.com/pre-commit/pre-commit-hooks
23-
rev: v4.6.0
23+
rev: v5.0.0
2424
hooks:
2525
- id: trailing-whitespace
2626
- id: check-merge-conflict
@@ -31,7 +31,7 @@ repos:
3131
args: ["--branch", "main"]
3232

3333
- repo: https://github.com/adamchainz/blacken-docs
34-
rev: 1.18.0
34+
rev: 1.19.0
3535
hooks:
3636
- id: blacken-docs
3737
args: [--skip-errors]

RELEASE.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Release type: patch
2+
3+
This release adds support for using raw Python enum types in your schema
4+
(enums that are not decorated with `@strawberry.enum`)
5+
6+
This is useful if you have enum types from other places in your code
7+
that you want to use in strawberry.
8+
i.e
9+
```py
10+
# somewhere.py
11+
from enum import Enum
12+
13+
14+
class AnimalKind(Enum):
15+
AXOLOTL, CAPYBARA = range(2)
16+
17+
18+
# gql/animals
19+
from somewhere import AnimalKind
20+
21+
22+
@strawberry.type
23+
class AnimalType:
24+
kind: AnimalKind
25+
```

docs/errors/not-a-strawberry-enum.md

Lines changed: 0 additions & 62 deletions
This file was deleted.

docs/general/subscriptions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ const subscriber = client.subscribe({query: ...}).subscribe({...})
269269
subscriber.unsubscribe();
270270
```
271271

272-
Strawberry can easily capture when a subscriber unsubscribes using an
272+
Strawberry can capture when a subscriber unsubscribes using an
273273
`asyncio.CancelledError` exception.
274274

275275
```python

docs/types/enums.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ class IceCreamFlavour(Enum):
4242
CHOCOLATE = "chocolate"
4343
```
4444

45+
<Note>
46+
47+
In some cases you already have an enum defined elsewhere in your code. You can
48+
safely use it in your schema and strawberry will generate a default graphql
49+
implementation of it.
50+
51+
The only drawback is that it is not currently possible to configure it
52+
(documentation / renaming or using `strawberry.enum_value` on it).
53+
54+
</Note>
55+
4556
Let's see how we can use Enums in our schema.
4657

4758
```python

strawberry/annotation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
)
2121
from typing_extensions import Annotated, Self, get_args, get_origin
2222

23-
from strawberry.exceptions.not_a_strawberry_enum import NotAStrawberryEnumError
2423
from strawberry.types.base import (
2524
StrawberryList,
2625
StrawberryObjectDefinition,
@@ -30,6 +29,7 @@
3029
has_object_definition,
3130
)
3231
from strawberry.types.enum import EnumDefinition
32+
from strawberry.types.enum import enum as strawberry_enum
3333
from strawberry.types.lazy_type import LazyType
3434
from strawberry.types.private import is_private
3535
from strawberry.types.scalar import ScalarDefinition
@@ -187,7 +187,7 @@ def create_enum(self, evaled_type: Any) -> EnumDefinition:
187187
try:
188188
return evaled_type._enum_definition
189189
except AttributeError:
190-
raise NotAStrawberryEnumError(evaled_type)
190+
return strawberry_enum(evaled_type)._enum_definition
191191

192192
def create_list(self, evaled_type: Any) -> StrawberryList:
193193
item_type, *_ = get_args(evaled_type)

strawberry/exceptions/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from .missing_dependencies import MissingOptionalDependenciesError
1616
from .missing_field_annotation import MissingFieldAnnotationError
1717
from .missing_return_annotation import MissingReturnAnnotationError
18-
from .not_a_strawberry_enum import NotAStrawberryEnumError
1918
from .object_is_not_a_class import ObjectIsNotClassError
2019
from .object_is_not_an_enum import ObjectIsNotAnEnumError
2120
from .private_strawberry_field import PrivateStrawberryFieldError
@@ -174,7 +173,6 @@ class StrawberryGraphQLError(GraphQLError):
174173
"UnresolvedFieldTypeError",
175174
"PrivateStrawberryFieldError",
176175
"MultipleStrawberryArgumentsError",
177-
"NotAStrawberryEnumError",
178176
"ScalarAlreadyRegisteredError",
179177
"WrongNumberOfResultsReturned",
180178
"FieldWithResolverAndDefaultValueError",

strawberry/exceptions/not_a_strawberry_enum.py

Lines changed: 0 additions & 38 deletions
This file was deleted.

tests/enums/test_enum.py

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import strawberry
66
from strawberry.exceptions import ObjectIsNotAnEnumError
7-
from strawberry.exceptions.not_a_strawberry_enum import NotAStrawberryEnumError
7+
from strawberry.types.base import get_object_definition
88
from strawberry.types.enum import EnumDefinition
99

1010

@@ -120,25 +120,6 @@ class IceCreamFlavour(Enum):
120120
assert definition.values[2].description is None
121121

122122

123-
@pytest.mark.raises_strawberry_exception(
124-
NotAStrawberryEnumError, match='Enum "IceCreamFlavour" is not a Strawberry enum'
125-
)
126-
def test_raises_error_when_using_enum_not_decorated():
127-
class IceCreamFlavour(Enum):
128-
VANILLA = strawberry.enum_value("vanilla")
129-
STRAWBERRY = strawberry.enum_value(
130-
"strawberry",
131-
description="Our favourite",
132-
)
133-
CHOCOLATE = "chocolate"
134-
135-
@strawberry.type
136-
class Query:
137-
flavour: IceCreamFlavour
138-
139-
strawberry.Schema(query=Query)
140-
141-
142123
def test_can_use_enum_values():
143124
@strawberry.enum
144125
class TestEnum(Enum):
@@ -169,3 +150,53 @@ class TestEnum(IntEnum):
169150
assert TestEnum.D.value == 4
170151

171152
assert [x.value for x in TestEnum.__members__.values()] == [1, 2, 3, 4]
153+
154+
155+
def test_default_enum_implementation() -> None:
156+
class Foo(Enum):
157+
BAR = "bar"
158+
BAZ = "baz"
159+
160+
@strawberry.type
161+
class Query:
162+
@strawberry.field
163+
def foo(self, foo: Foo) -> Foo:
164+
return foo
165+
166+
schema = strawberry.Schema(Query)
167+
res = schema.execute_sync("{ foo(foo: BAR) }")
168+
assert not res.errors
169+
assert res.data
170+
assert res.data["foo"] == "BAR"
171+
172+
173+
def test_default_enum_reuse() -> None:
174+
class Foo(Enum):
175+
BAR = "bar"
176+
BAZ = "baz"
177+
178+
@strawberry.type
179+
class SomeType:
180+
foo: Foo
181+
bar: Foo
182+
183+
definition = get_object_definition(SomeType, strict=True)
184+
assert definition.fields[1].type is definition.fields[1].type
185+
186+
187+
def test_default_enum_with_enum_value() -> None:
188+
class Foo(Enum):
189+
BAR = "bar"
190+
BAZ = strawberry.enum_value("baz")
191+
192+
@strawberry.type
193+
class Query:
194+
@strawberry.field
195+
def foo(self, foo: Foo) -> str:
196+
return foo.value
197+
198+
schema = strawberry.Schema(Query)
199+
res = schema.execute_sync("{ foo(foo: BAZ) }")
200+
assert not res.errors
201+
assert res.data
202+
assert res.data["foo"] == "baz"

0 commit comments

Comments
 (0)