strawberry-graphql 0.235.2__py3-none-any.whl → 0.236.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- strawberry/__init__.py +17 -11
- strawberry/aiohttp/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/aiohttp/handlers/graphql_ws_handler.py +3 -0
- strawberry/aiohttp/test/client.py +3 -0
- strawberry/aiohttp/views.py +3 -0
- strawberry/annotation.py +19 -19
- strawberry/asgi/__init__.py +3 -3
- strawberry/asgi/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/asgi/handlers/graphql_ws_handler.py +3 -0
- strawberry/asgi/test/client.py +3 -0
- strawberry/chalice/views.py +12 -3
- strawberry/channels/handlers/__init__.py +0 -0
- strawberry/channels/handlers/base.py +5 -5
- strawberry/channels/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/channels/handlers/graphql_ws_handler.py +3 -0
- strawberry/channels/handlers/http_handler.py +5 -2
- strawberry/channels/handlers/ws_handler.py +4 -1
- strawberry/channels/router.py +9 -5
- strawberry/channels/testing.py +11 -4
- strawberry/cli/commands/upgrade/__init__.py +13 -5
- strawberry/cli/commands/upgrade/_fake_progress.py +2 -1
- strawberry/cli/commands/upgrade/_run_codemod.py +18 -1
- strawberry/codegen/exceptions.py +8 -0
- strawberry/codegen/query_codegen.py +16 -7
- strawberry/codegen/types.py +32 -1
- strawberry/codemods/update_imports.py +136 -0
- strawberry/dataloader.py +13 -0
- strawberry/directive.py +52 -4
- strawberry/django/context.py +4 -1
- strawberry/django/test/client.py +3 -0
- strawberry/django/views.py +3 -0
- strawberry/exceptions/__init__.py +5 -5
- strawberry/exceptions/duplicated_type_name.py +1 -1
- strawberry/exceptions/invalid_argument_type.py +3 -3
- strawberry/exceptions/invalid_union_type.py +5 -6
- strawberry/exceptions/missing_arguments_annotations.py +1 -1
- strawberry/exceptions/missing_dependencies.py +10 -2
- strawberry/exceptions/missing_return_annotation.py +1 -1
- strawberry/exceptions/permission_fail_silently_requires_optional.py +3 -3
- strawberry/exceptions/scalar_already_registered.py +1 -1
- strawberry/exceptions/unresolved_field_type.py +2 -2
- strawberry/exceptions/utils/source_finder.py +5 -2
- strawberry/experimental/pydantic/conversion.py +5 -5
- strawberry/experimental/pydantic/conversion_types.py +4 -2
- strawberry/experimental/pydantic/error_type.py +2 -2
- strawberry/experimental/pydantic/fields.py +2 -2
- strawberry/experimental/pydantic/object_type.py +11 -7
- strawberry/experimental/pydantic/utils.py +4 -5
- strawberry/ext/dataclasses/dataclasses.py +2 -1
- strawberry/ext/mypy_plugin.py +10 -8
- strawberry/extensions/add_validation_rules.py +27 -23
- strawberry/extensions/base_extension.py +6 -4
- strawberry/extensions/directives.py +4 -1
- strawberry/extensions/disable_validation.py +15 -12
- strawberry/extensions/field_extension.py +11 -5
- strawberry/extensions/mask_errors.py +3 -0
- strawberry/extensions/max_aliases.py +21 -19
- strawberry/extensions/max_tokens.py +14 -16
- strawberry/extensions/parser_cache.py +22 -19
- strawberry/extensions/pyinstrument.py +4 -8
- strawberry/extensions/query_depth_limiter.py +22 -23
- strawberry/extensions/runner.py +3 -0
- strawberry/extensions/tracing/apollo.py +3 -0
- strawberry/extensions/tracing/datadog.py +7 -2
- strawberry/extensions/tracing/opentelemetry.py +3 -0
- strawberry/extensions/tracing/sentry.py +3 -0
- strawberry/extensions/tracing/utils.py +3 -0
- strawberry/extensions/utils.py +3 -0
- strawberry/extensions/validation_cache.py +23 -20
- strawberry/fastapi/context.py +3 -0
- strawberry/fastapi/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/fastapi/handlers/graphql_ws_handler.py +3 -0
- strawberry/fastapi/router.py +3 -0
- strawberry/federation/argument.py +4 -1
- strawberry/federation/enum.py +5 -3
- strawberry/federation/field.py +6 -3
- strawberry/federation/mutation.py +2 -0
- strawberry/federation/object_type.py +7 -4
- strawberry/federation/scalar.py +43 -20
- strawberry/federation/schema.py +12 -9
- strawberry/federation/schema_directive.py +2 -2
- strawberry/federation/schema_directives.py +19 -1
- strawberry/federation/types.py +5 -2
- strawberry/federation/union.py +27 -8
- strawberry/field_extensions/input_mutation.py +5 -2
- strawberry/file_uploads/scalars.py +3 -1
- strawberry/file_uploads/utils.py +3 -0
- strawberry/flask/views.py +6 -0
- strawberry/http/__init__.py +9 -0
- strawberry/http/async_base_view.py +4 -3
- strawberry/http/base.py +3 -0
- strawberry/http/exceptions.py +3 -0
- strawberry/http/ides.py +3 -0
- strawberry/http/sync_base_view.py +4 -3
- strawberry/http/temporal_response.py +3 -0
- strawberry/http/types.py +3 -0
- strawberry/http/typevars.py +3 -0
- strawberry/litestar/controller.py +6 -0
- strawberry/litestar/handlers/__init__.py +0 -0
- strawberry/litestar/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/litestar/handlers/graphql_ws_handler.py +3 -0
- strawberry/parent.py +27 -21
- strawberry/permission.py +70 -27
- strawberry/printer/ast_from_value.py +4 -1
- strawberry/printer/printer.py +8 -5
- strawberry/quart/views.py +3 -0
- strawberry/relay/exceptions.py +7 -0
- strawberry/relay/fields.py +70 -45
- strawberry/relay/types.py +78 -78
- strawberry/relay/utils.py +10 -1
- strawberry/resolvers.py +3 -0
- strawberry/sanic/context.py +3 -0
- strawberry/sanic/utils.py +10 -8
- strawberry/sanic/views.py +4 -2
- strawberry/scalars.py +6 -2
- strawberry/schema/base.py +7 -4
- strawberry/schema/compat.py +12 -2
- strawberry/schema/config.py +3 -0
- strawberry/schema/exceptions.py +3 -0
- strawberry/schema/execute.py +3 -0
- strawberry/schema/name_converter.py +12 -9
- strawberry/schema/schema.py +46 -9
- strawberry/schema/schema_converter.py +16 -14
- strawberry/schema/types/base_scalars.py +3 -1
- strawberry/schema/types/concrete_type.py +4 -4
- strawberry/schema/types/scalar.py +8 -1
- strawberry/schema/validation_rules/one_of.py +3 -0
- strawberry/schema_codegen/__init__.py +3 -0
- strawberry/schema_directive.py +2 -2
- strawberry/starlite/controller.py +3 -0
- strawberry/starlite/handlers/__init__.py +0 -0
- strawberry/starlite/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/starlite/handlers/graphql_ws_handler.py +3 -0
- strawberry/subscriptions/__init__.py +6 -0
- strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py +5 -0
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +12 -17
- strawberry/subscriptions/protocols/graphql_transport_ws/types.py +21 -25
- strawberry/subscriptions/protocols/graphql_ws/__init__.py +14 -0
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +8 -5
- strawberry/subscriptions/protocols/graphql_ws/types.py +11 -0
- strawberry/test/client.py +44 -29
- strawberry/tools/create_type.py +27 -8
- strawberry/tools/merge_types.py +5 -3
- strawberry/types/__init__.py +8 -1
- strawberry/{arguments.py → types/arguments.py} +44 -13
- strawberry/{auto.py → types/auto.py} +21 -3
- strawberry/types/{types.py → base.py} +234 -10
- strawberry/{enum.py → types/enum.py} +69 -9
- strawberry/types/execution.py +3 -0
- strawberry/{field.py → types/field.py} +46 -23
- strawberry/types/fields/resolver.py +2 -2
- strawberry/types/graphql.py +3 -0
- strawberry/types/info.py +50 -7
- strawberry/{lazy_type.py → types/lazy_type.py} +50 -0
- strawberry/types/mutation.py +351 -0
- strawberry/types/nodes.py +4 -2
- strawberry/{object_type.py → types/object_type.py} +108 -29
- strawberry/{private.py → types/private.py} +13 -6
- strawberry/{custom_scalar.py → types/scalar.py} +39 -23
- strawberry/types/type_resolver.py +21 -16
- strawberry/{union.py → types/union.py} +24 -9
- strawberry/{unset.py → types/unset.py} +20 -0
- strawberry/utils/aio.py +8 -0
- strawberry/utils/await_maybe.py +3 -0
- strawberry/utils/dataclasses.py +3 -0
- strawberry/utils/debug.py +5 -2
- strawberry/utils/deprecations.py +3 -0
- strawberry/utils/graphql_lexer.py +3 -0
- strawberry/utils/importer.py +3 -0
- strawberry/utils/inspect.py +39 -30
- strawberry/utils/logging.py +3 -0
- strawberry/utils/operation.py +3 -0
- strawberry/utils/str_converters.py +3 -0
- strawberry/utils/typing.py +33 -16
- {strawberry_graphql-0.235.2.dist-info → strawberry_graphql-0.236.0.dist-info}/METADATA +1 -1
- strawberry_graphql-0.236.0.dist-info/RECORD +255 -0
- strawberry/mutation.py +0 -8
- strawberry/type.py +0 -232
- strawberry_graphql-0.235.2.dist-info/RECORD +0 -252
- {strawberry_graphql-0.235.2.dist-info → strawberry_graphql-0.236.0.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.235.2.dist-info → strawberry_graphql-0.236.0.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.235.2.dist-info → strawberry_graphql-0.236.0.dist-info}/entry_points.txt +0 -0
@@ -25,6 +25,14 @@ Module = TypeVar("Module")
|
|
25
25
|
|
26
26
|
@dataclass(frozen=True)
|
27
27
|
class LazyType(Generic[TypeName, Module]):
|
28
|
+
"""A class that represents a type that will be resolved at runtime.
|
29
|
+
|
30
|
+
This is useful when you have circular dependencies between types.
|
31
|
+
|
32
|
+
This class is not meant to be used directly, instead use the `strawberry.lazy`
|
33
|
+
function.
|
34
|
+
"""
|
35
|
+
|
28
36
|
type_name: str
|
29
37
|
module: str
|
30
38
|
package: Optional[str] = None
|
@@ -81,6 +89,14 @@ class LazyType(Generic[TypeName, Module]):
|
|
81
89
|
|
82
90
|
|
83
91
|
class StrawberryLazyReference:
|
92
|
+
"""A class that represents a lazy reference to a type in another module.
|
93
|
+
|
94
|
+
This is useful when you have circular dependencies between types.
|
95
|
+
|
96
|
+
This class is not meant to be used directly, instead use the `strawberry.lazy`
|
97
|
+
function.
|
98
|
+
"""
|
99
|
+
|
84
100
|
def __init__(self, module: str) -> None:
|
85
101
|
self.module = module
|
86
102
|
self.package = None
|
@@ -105,4 +121,38 @@ class StrawberryLazyReference:
|
|
105
121
|
|
106
122
|
|
107
123
|
def lazy(module_path: str) -> StrawberryLazyReference:
|
124
|
+
"""Creates a lazy reference to a type in another module.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
module_path: The path to the module containing the type, supports relative paths
|
128
|
+
starting with `.`
|
129
|
+
|
130
|
+
Returns:
|
131
|
+
A `StrawberryLazyReference` object that can be used to reference a type in another
|
132
|
+
module.
|
133
|
+
|
134
|
+
This is useful when you have circular dependencies between types.
|
135
|
+
|
136
|
+
For example, assuming you have a `Post` type that has a field `author` that
|
137
|
+
references a `User` type (which also has a field `posts` that references a list of
|
138
|
+
`Post`), you can use `strawberry.lazy` to avoid the circular dependency:
|
139
|
+
|
140
|
+
```python
|
141
|
+
from typing import TYPE_CHECKING, Annotated
|
142
|
+
|
143
|
+
import strawberry
|
144
|
+
|
145
|
+
if TYPE_CHECKING:
|
146
|
+
from .users import User
|
147
|
+
|
148
|
+
|
149
|
+
@strawberry.type
|
150
|
+
class Post:
|
151
|
+
title: str
|
152
|
+
author: Annotated["User", strawberry.lazy(".users")]
|
153
|
+
```
|
154
|
+
"""
|
108
155
|
return StrawberryLazyReference(module_path)
|
156
|
+
|
157
|
+
|
158
|
+
__all__ = ["LazyType", "StrawberryLazyReference", "lazy"]
|
@@ -0,0 +1,351 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import dataclasses
|
4
|
+
from typing import (
|
5
|
+
TYPE_CHECKING,
|
6
|
+
Any,
|
7
|
+
Callable,
|
8
|
+
List,
|
9
|
+
Mapping,
|
10
|
+
Optional,
|
11
|
+
Sequence,
|
12
|
+
Type,
|
13
|
+
Union,
|
14
|
+
overload,
|
15
|
+
)
|
16
|
+
from typing_extensions import Literal
|
17
|
+
|
18
|
+
from strawberry.types.field import (
|
19
|
+
_RESOLVER_TYPE,
|
20
|
+
_RESOLVER_TYPE_ASYNC,
|
21
|
+
_RESOLVER_TYPE_SYNC,
|
22
|
+
StrawberryField,
|
23
|
+
T,
|
24
|
+
field,
|
25
|
+
)
|
26
|
+
|
27
|
+
if TYPE_CHECKING:
|
28
|
+
from typing_extensions import Literal
|
29
|
+
|
30
|
+
from strawberry.extensions.field_extension import FieldExtension
|
31
|
+
from strawberry.permission import BasePermission
|
32
|
+
|
33
|
+
# NOTE: we are separating the sync and async resolvers because using both
|
34
|
+
# in the same function will cause mypy to raise an error. Not sure if it is a bug
|
35
|
+
|
36
|
+
|
37
|
+
@overload
|
38
|
+
def mutation(
|
39
|
+
*,
|
40
|
+
resolver: _RESOLVER_TYPE_ASYNC[T],
|
41
|
+
name: Optional[str] = None,
|
42
|
+
description: Optional[str] = None,
|
43
|
+
init: Literal[False] = False,
|
44
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
45
|
+
deprecation_reason: Optional[str] = None,
|
46
|
+
default: Any = dataclasses.MISSING,
|
47
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
48
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
49
|
+
directives: Optional[Sequence[object]] = (),
|
50
|
+
extensions: Optional[List[FieldExtension]] = None,
|
51
|
+
graphql_type: Optional[Any] = None,
|
52
|
+
) -> T: ...
|
53
|
+
|
54
|
+
|
55
|
+
@overload
|
56
|
+
def mutation(
|
57
|
+
*,
|
58
|
+
resolver: _RESOLVER_TYPE_SYNC[T],
|
59
|
+
name: Optional[str] = None,
|
60
|
+
description: Optional[str] = None,
|
61
|
+
init: Literal[False] = False,
|
62
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
63
|
+
deprecation_reason: Optional[str] = None,
|
64
|
+
default: Any = dataclasses.MISSING,
|
65
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
66
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
67
|
+
directives: Optional[Sequence[object]] = (),
|
68
|
+
extensions: Optional[List[FieldExtension]] = None,
|
69
|
+
graphql_type: Optional[Any] = None,
|
70
|
+
) -> T: ...
|
71
|
+
|
72
|
+
|
73
|
+
@overload
|
74
|
+
def mutation(
|
75
|
+
*,
|
76
|
+
name: Optional[str] = None,
|
77
|
+
description: Optional[str] = None,
|
78
|
+
init: Literal[True] = True,
|
79
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
80
|
+
deprecation_reason: Optional[str] = None,
|
81
|
+
default: Any = dataclasses.MISSING,
|
82
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
83
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
84
|
+
directives: Optional[Sequence[object]] = (),
|
85
|
+
extensions: Optional[List[FieldExtension]] = None,
|
86
|
+
graphql_type: Optional[Any] = None,
|
87
|
+
) -> Any: ...
|
88
|
+
|
89
|
+
|
90
|
+
@overload
|
91
|
+
def mutation(
|
92
|
+
resolver: _RESOLVER_TYPE_ASYNC[T],
|
93
|
+
*,
|
94
|
+
name: Optional[str] = None,
|
95
|
+
description: Optional[str] = None,
|
96
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
97
|
+
deprecation_reason: Optional[str] = None,
|
98
|
+
default: Any = dataclasses.MISSING,
|
99
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
100
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
101
|
+
directives: Optional[Sequence[object]] = (),
|
102
|
+
extensions: Optional[List[FieldExtension]] = None,
|
103
|
+
graphql_type: Optional[Any] = None,
|
104
|
+
) -> StrawberryField: ...
|
105
|
+
|
106
|
+
|
107
|
+
@overload
|
108
|
+
def mutation(
|
109
|
+
resolver: _RESOLVER_TYPE_SYNC[T],
|
110
|
+
*,
|
111
|
+
name: Optional[str] = None,
|
112
|
+
description: Optional[str] = None,
|
113
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
114
|
+
deprecation_reason: Optional[str] = None,
|
115
|
+
default: Any = dataclasses.MISSING,
|
116
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
117
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
118
|
+
directives: Optional[Sequence[object]] = (),
|
119
|
+
extensions: Optional[List[FieldExtension]] = None,
|
120
|
+
graphql_type: Optional[Any] = None,
|
121
|
+
) -> StrawberryField: ...
|
122
|
+
|
123
|
+
|
124
|
+
def mutation(
|
125
|
+
resolver: Optional[_RESOLVER_TYPE[Any]] = None,
|
126
|
+
*,
|
127
|
+
name: Optional[str] = None,
|
128
|
+
description: Optional[str] = None,
|
129
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
130
|
+
deprecation_reason: Optional[str] = None,
|
131
|
+
default: Any = dataclasses.MISSING,
|
132
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
133
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
134
|
+
directives: Optional[Sequence[object]] = (),
|
135
|
+
extensions: Optional[List[FieldExtension]] = None,
|
136
|
+
graphql_type: Optional[Any] = None,
|
137
|
+
# This init parameter is used by PyRight to determine whether this field
|
138
|
+
# is added in the constructor or not. It is not used to change
|
139
|
+
# any behavior at the moment.
|
140
|
+
init: Literal[True, False, None] = None,
|
141
|
+
) -> Any:
|
142
|
+
"""Annotates a method or property as a GraphQL mutation.
|
143
|
+
|
144
|
+
Args:
|
145
|
+
resolver: The resolver for the field. It can be a sync or async function.
|
146
|
+
name: The GraphQL name of the field.
|
147
|
+
description: The GraphQL description of the field.
|
148
|
+
permission_classes: The permission classes required to access the field.
|
149
|
+
deprecation_reason: The deprecation reason for the field.
|
150
|
+
default: The default value for the field.
|
151
|
+
default_factory: The default factory for the field.
|
152
|
+
metadata: The metadata for the field.
|
153
|
+
directives: The directives for the field.
|
154
|
+
extensions: The extensions for the field.
|
155
|
+
graphql_type: The GraphQL type for the field, useful when you want to use a
|
156
|
+
different type in the resolver than the one in the schema.
|
157
|
+
init: This parameter is used by PyRight to determine whether this field is
|
158
|
+
added in the constructor or not. It is not used to change any behavior at
|
159
|
+
the moment.
|
160
|
+
|
161
|
+
Returns:
|
162
|
+
The field object.
|
163
|
+
|
164
|
+
This is normally used inside a type declaration:
|
165
|
+
|
166
|
+
```python
|
167
|
+
import strawberry
|
168
|
+
|
169
|
+
|
170
|
+
@strawberry.type
|
171
|
+
class Mutation:
|
172
|
+
@strawberry.mutation
|
173
|
+
def create_post(self, title: str, content: str) -> Post: ...
|
174
|
+
```
|
175
|
+
|
176
|
+
It can be used both as decorator and as a normal function.
|
177
|
+
"""
|
178
|
+
return field(
|
179
|
+
resolver=resolver, # type: ignore
|
180
|
+
name=name,
|
181
|
+
description=description,
|
182
|
+
permission_classes=permission_classes,
|
183
|
+
deprecation_reason=deprecation_reason,
|
184
|
+
default=default,
|
185
|
+
default_factory=default_factory,
|
186
|
+
metadata=metadata,
|
187
|
+
directives=directives,
|
188
|
+
extensions=extensions,
|
189
|
+
graphql_type=graphql_type,
|
190
|
+
)
|
191
|
+
|
192
|
+
|
193
|
+
# NOTE: we are separating the sync and async resolvers because using both
|
194
|
+
# in the same function will cause mypy to raise an error. Not sure if it is a bug
|
195
|
+
|
196
|
+
|
197
|
+
@overload
|
198
|
+
def subscription(
|
199
|
+
*,
|
200
|
+
resolver: _RESOLVER_TYPE_ASYNC[T],
|
201
|
+
name: Optional[str] = None,
|
202
|
+
description: Optional[str] = None,
|
203
|
+
init: Literal[False] = False,
|
204
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
205
|
+
deprecation_reason: Optional[str] = None,
|
206
|
+
default: Any = dataclasses.MISSING,
|
207
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
208
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
209
|
+
directives: Optional[Sequence[object]] = (),
|
210
|
+
extensions: Optional[List[FieldExtension]] = None,
|
211
|
+
graphql_type: Optional[Any] = None,
|
212
|
+
) -> T: ...
|
213
|
+
|
214
|
+
|
215
|
+
@overload
|
216
|
+
def subscription(
|
217
|
+
*,
|
218
|
+
resolver: _RESOLVER_TYPE_SYNC[T],
|
219
|
+
name: Optional[str] = None,
|
220
|
+
description: Optional[str] = None,
|
221
|
+
init: Literal[False] = False,
|
222
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
223
|
+
deprecation_reason: Optional[str] = None,
|
224
|
+
default: Any = dataclasses.MISSING,
|
225
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
226
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
227
|
+
directives: Optional[Sequence[object]] = (),
|
228
|
+
extensions: Optional[List[FieldExtension]] = None,
|
229
|
+
graphql_type: Optional[Any] = None,
|
230
|
+
) -> T: ...
|
231
|
+
|
232
|
+
|
233
|
+
@overload
|
234
|
+
def subscription(
|
235
|
+
*,
|
236
|
+
name: Optional[str] = None,
|
237
|
+
description: Optional[str] = None,
|
238
|
+
init: Literal[True] = True,
|
239
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
240
|
+
deprecation_reason: Optional[str] = None,
|
241
|
+
default: Any = dataclasses.MISSING,
|
242
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
243
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
244
|
+
directives: Optional[Sequence[object]] = (),
|
245
|
+
extensions: Optional[List[FieldExtension]] = None,
|
246
|
+
graphql_type: Optional[Any] = None,
|
247
|
+
) -> Any: ...
|
248
|
+
|
249
|
+
|
250
|
+
@overload
|
251
|
+
def subscription(
|
252
|
+
resolver: _RESOLVER_TYPE_ASYNC[T],
|
253
|
+
*,
|
254
|
+
name: Optional[str] = None,
|
255
|
+
description: Optional[str] = None,
|
256
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
257
|
+
deprecation_reason: Optional[str] = None,
|
258
|
+
default: Any = dataclasses.MISSING,
|
259
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
260
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
261
|
+
directives: Optional[Sequence[object]] = (),
|
262
|
+
extensions: Optional[List[FieldExtension]] = None,
|
263
|
+
graphql_type: Optional[Any] = None,
|
264
|
+
) -> StrawberryField: ...
|
265
|
+
|
266
|
+
|
267
|
+
@overload
|
268
|
+
def subscription(
|
269
|
+
resolver: _RESOLVER_TYPE_SYNC[T],
|
270
|
+
*,
|
271
|
+
name: Optional[str] = None,
|
272
|
+
description: Optional[str] = None,
|
273
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
274
|
+
deprecation_reason: Optional[str] = None,
|
275
|
+
default: Any = dataclasses.MISSING,
|
276
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
277
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
278
|
+
directives: Optional[Sequence[object]] = (),
|
279
|
+
extensions: Optional[List[FieldExtension]] = None,
|
280
|
+
graphql_type: Optional[Any] = None,
|
281
|
+
) -> StrawberryField: ...
|
282
|
+
|
283
|
+
|
284
|
+
def subscription(
|
285
|
+
resolver: Optional[_RESOLVER_TYPE[Any]] = None,
|
286
|
+
*,
|
287
|
+
name: Optional[str] = None,
|
288
|
+
description: Optional[str] = None,
|
289
|
+
permission_classes: Optional[List[Type[BasePermission]]] = None,
|
290
|
+
deprecation_reason: Optional[str] = None,
|
291
|
+
default: Any = dataclasses.MISSING,
|
292
|
+
default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
|
293
|
+
metadata: Optional[Mapping[Any, Any]] = None,
|
294
|
+
directives: Optional[Sequence[object]] = (),
|
295
|
+
extensions: Optional[List[FieldExtension]] = None,
|
296
|
+
graphql_type: Optional[Any] = None,
|
297
|
+
init: Literal[True, False, None] = None,
|
298
|
+
) -> Any:
|
299
|
+
"""Annotates a method or property as a GraphQL subscription.
|
300
|
+
|
301
|
+
Args:
|
302
|
+
resolver: The resolver for the field.
|
303
|
+
name: The GraphQL name of the field.
|
304
|
+
description: The GraphQL description of the field.
|
305
|
+
permission_classes: The permission classes required to access the field.
|
306
|
+
deprecation_reason: The deprecation reason for the field.
|
307
|
+
default: The default value for the field.
|
308
|
+
default_factory: The default factory for the field.
|
309
|
+
metadata: The metadata for the field.
|
310
|
+
directives: The directives for the field.
|
311
|
+
extensions: The extensions for the field.
|
312
|
+
graphql_type: The GraphQL type for the field, useful when you want to use a
|
313
|
+
different type in the resolver than the one in the schema.
|
314
|
+
init: This parameter is used by PyRight to determine whether this field is
|
315
|
+
added in the constructor or not. It is not used to change any behavior at
|
316
|
+
the moment.
|
317
|
+
|
318
|
+
Returns:
|
319
|
+
The field for the subscription.
|
320
|
+
|
321
|
+
This is normally used inside a type declaration:
|
322
|
+
|
323
|
+
```python
|
324
|
+
import strawberry
|
325
|
+
|
326
|
+
|
327
|
+
@strawberry.type
|
328
|
+
class Subscription:
|
329
|
+
@strawberry.subscription
|
330
|
+
def post_created(self, title: str, content: str) -> Post: ...
|
331
|
+
```
|
332
|
+
|
333
|
+
it can be used both as decorator and as a normal function.
|
334
|
+
"""
|
335
|
+
return field(
|
336
|
+
resolver=resolver, # type: ignore
|
337
|
+
name=name,
|
338
|
+
description=description,
|
339
|
+
is_subscription=True,
|
340
|
+
permission_classes=permission_classes,
|
341
|
+
deprecation_reason=deprecation_reason,
|
342
|
+
default=default,
|
343
|
+
default_factory=default_factory,
|
344
|
+
metadata=metadata,
|
345
|
+
directives=directives,
|
346
|
+
extensions=extensions,
|
347
|
+
graphql_type=graphql_type,
|
348
|
+
)
|
349
|
+
|
350
|
+
|
351
|
+
__all__ = ["mutation", "subscription"]
|
strawberry/types/nodes.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
"""
|
2
|
-
Abstraction layer for graphql-core field nodes.
|
1
|
+
"""Abstraction layer for graphql-core field nodes.
|
3
2
|
|
4
3
|
Call `convert_sections` on a list of GraphQL `FieldNode`s,
|
5
4
|
such as in `info.field_nodes`.
|
@@ -151,3 +150,6 @@ class SelectedField:
|
|
151
150
|
info, getattr(node.selection_set, "selections", [])
|
152
151
|
),
|
153
152
|
)
|
153
|
+
|
154
|
+
|
155
|
+
__all__ = ["convert_selections", "FragmentSpread", "InlineFragment", "SelectedField"]
|
@@ -16,20 +16,19 @@ from typing import (
|
|
16
16
|
)
|
17
17
|
from typing_extensions import dataclass_transform
|
18
18
|
|
19
|
-
from .exceptions import (
|
19
|
+
from strawberry.exceptions import (
|
20
20
|
MissingFieldAnnotationError,
|
21
21
|
MissingReturnAnnotationError,
|
22
22
|
ObjectIsNotClassError,
|
23
23
|
)
|
24
|
+
from strawberry.types.base import get_object_definition
|
25
|
+
from strawberry.utils.dataclasses import add_custom_init_fn
|
26
|
+
from strawberry.utils.deprecations import DEPRECATION_MESSAGES, DeprecatedDescriptor
|
27
|
+
from strawberry.utils.str_converters import to_camel_case
|
28
|
+
|
29
|
+
from .base import StrawberryObjectDefinition
|
24
30
|
from .field import StrawberryField, field
|
25
|
-
from .
|
26
|
-
from .types.type_resolver import _get_fields
|
27
|
-
from .types.types import (
|
28
|
-
StrawberryObjectDefinition,
|
29
|
-
)
|
30
|
-
from .utils.dataclasses import add_custom_init_fn
|
31
|
-
from .utils.deprecations import DEPRECATION_MESSAGES, DeprecatedDescriptor
|
32
|
-
from .utils.str_converters import to_camel_case
|
31
|
+
from .type_resolver import _get_fields
|
33
32
|
|
34
33
|
T = TypeVar("T", bound=Type)
|
35
34
|
|
@@ -103,9 +102,7 @@ def _check_field_annotations(cls: Type[Any]) -> None:
|
|
103
102
|
|
104
103
|
|
105
104
|
def _wrap_dataclass(cls: Type[T]) -> Type[T]:
|
106
|
-
"""Wrap a strawberry.type class with a dataclass and check for any issues
|
107
|
-
before doing so"""
|
108
|
-
|
105
|
+
"""Wrap a strawberry.type class with a dataclass and check for any issues before doing so."""
|
109
106
|
# Ensure all Fields have been properly type-annotated
|
110
107
|
_check_field_annotations(cls)
|
111
108
|
|
@@ -232,11 +229,36 @@ def type(
|
|
232
229
|
) -> Union[T, Callable[[T], T]]:
|
233
230
|
"""Annotates a class as a GraphQL type.
|
234
231
|
|
232
|
+
Similar to `dataclasses.dataclass`, but with additional functionality for
|
233
|
+
defining GraphQL types.
|
234
|
+
|
235
|
+
Args:
|
236
|
+
cls: The class we want to create a GraphQL type from.
|
237
|
+
name: The name of the GraphQL type.
|
238
|
+
is_input: Whether the class is an input type. Used internally, use `@strawerry.input` instead of passing this flag.
|
239
|
+
is_interface: Whether the class is an interface. Used internally, use `@strawerry.interface` instead of passing this flag.
|
240
|
+
description: The description of the GraphQL type.
|
241
|
+
directives: The directives of the GraphQL type.
|
242
|
+
extend: Whether the class is extending an existing type.
|
243
|
+
|
244
|
+
Returns:
|
245
|
+
The class.
|
246
|
+
|
235
247
|
Example usage:
|
236
248
|
|
237
|
-
|
238
|
-
|
239
|
-
|
249
|
+
```python
|
250
|
+
@strawberry.type
|
251
|
+
class User:
|
252
|
+
name: str = "A name"
|
253
|
+
```
|
254
|
+
|
255
|
+
You can also pass parameters to the decorator:
|
256
|
+
|
257
|
+
```python
|
258
|
+
@strawberry.type(name="UserType", description="A user type")
|
259
|
+
class MyUser:
|
260
|
+
name: str = "A name"
|
261
|
+
```
|
240
262
|
"""
|
241
263
|
|
242
264
|
def wrap(cls: T) -> T:
|
@@ -321,12 +343,35 @@ def input(
|
|
321
343
|
directives: Optional[Sequence[object]] = (),
|
322
344
|
):
|
323
345
|
"""Annotates a class as a GraphQL Input type.
|
346
|
+
|
347
|
+
Similar to `@strawberry.type`, but for input types.
|
348
|
+
|
349
|
+
Args:
|
350
|
+
cls: The class we want to create a GraphQL input type from.
|
351
|
+
name: The name of the GraphQL input type.
|
352
|
+
description: The description of the GraphQL input type.
|
353
|
+
directives: The directives of the GraphQL input type.
|
354
|
+
one_of: Whether the input type is a `oneOf` type.
|
355
|
+
|
356
|
+
Returns:
|
357
|
+
The class.
|
358
|
+
|
324
359
|
Example usage:
|
325
|
-
>>> @strawberry.input
|
326
|
-
>>> class X:
|
327
|
-
>>> field_abc: str = "ABC"
|
328
|
-
"""
|
329
360
|
|
361
|
+
```python
|
362
|
+
@strawberry.input
|
363
|
+
class UserInput:
|
364
|
+
name: str
|
365
|
+
```
|
366
|
+
|
367
|
+
You can also pass parameters to the decorator:
|
368
|
+
|
369
|
+
```python
|
370
|
+
@strawberry.input(name="UserInputType", description="A user input type")
|
371
|
+
class MyUserInput:
|
372
|
+
name: str
|
373
|
+
```
|
374
|
+
"""
|
330
375
|
from strawberry.schema_directives import OneOf
|
331
376
|
|
332
377
|
if one_of:
|
@@ -377,12 +422,34 @@ def interface(
|
|
377
422
|
directives: Optional[Sequence[object]] = (),
|
378
423
|
):
|
379
424
|
"""Annotates a class as a GraphQL Interface.
|
425
|
+
|
426
|
+
Similar to `@strawberry.type`, but for interfaces.
|
427
|
+
|
428
|
+
Args:
|
429
|
+
cls: The class we want to create a GraphQL interface from.
|
430
|
+
name: The name of the GraphQL interface.
|
431
|
+
description: The description of the GraphQL interface.
|
432
|
+
directives: The directives of the GraphQL interface.
|
433
|
+
|
434
|
+
Returns:
|
435
|
+
The class.
|
436
|
+
|
380
437
|
Example usage:
|
381
|
-
>>> @strawberry.interface
|
382
|
-
>>> class X:
|
383
|
-
>>> field_abc: str
|
384
|
-
"""
|
385
438
|
|
439
|
+
```python
|
440
|
+
@strawberry.interface
|
441
|
+
class Node:
|
442
|
+
id: str
|
443
|
+
```
|
444
|
+
|
445
|
+
You can also pass parameters to the decorator:
|
446
|
+
|
447
|
+
```python
|
448
|
+
@strawberry.interface(name="NodeType", description="A node type")
|
449
|
+
class MyNode:
|
450
|
+
id: str
|
451
|
+
```
|
452
|
+
"""
|
386
453
|
return type( # type: ignore # not sure why mypy complains here
|
387
454
|
cls,
|
388
455
|
name=name,
|
@@ -394,15 +461,27 @@ def interface(
|
|
394
461
|
|
395
462
|
def asdict(obj: Any) -> Dict[str, object]:
|
396
463
|
"""Convert a strawberry object into a dictionary.
|
464
|
+
|
397
465
|
This wraps the dataclasses.asdict function to strawberry.
|
398
466
|
|
467
|
+
Args:
|
468
|
+
obj: The object to convert into a dictionary.
|
469
|
+
|
470
|
+
Returns:
|
471
|
+
A dictionary representation of the object.
|
472
|
+
|
399
473
|
Example usage:
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
474
|
+
|
475
|
+
```python
|
476
|
+
@strawberry.type
|
477
|
+
class User:
|
478
|
+
name: str
|
479
|
+
age: int
|
480
|
+
|
481
|
+
|
482
|
+
strawberry.asdict(User(name="Lorem", age=25))
|
483
|
+
# {"name": "Lorem", "age": 25}
|
484
|
+
```
|
406
485
|
"""
|
407
486
|
return dataclasses.asdict(obj)
|
408
487
|
|
@@ -10,17 +10,24 @@ class StrawberryPrivate: ...
|
|
10
10
|
T = TypeVar("T")
|
11
11
|
|
12
12
|
Private = Annotated[T, StrawberryPrivate()]
|
13
|
-
|
13
|
+
"""Represents a field that won't be exposed in the GraphQL schema.
|
14
14
|
|
15
15
|
Example:
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
```python
|
18
|
+
import strawberry
|
19
|
+
|
20
|
+
|
21
|
+
@strawberry.type
|
22
|
+
class User:
|
23
|
+
name: str
|
24
|
+
age: strawberry.Private[int]
|
25
|
+
```
|
22
26
|
"""
|
23
27
|
|
24
28
|
|
25
29
|
def is_private(type_: object) -> bool:
|
26
30
|
return type_has_annotation(type_, StrawberryPrivate)
|
31
|
+
|
32
|
+
|
33
|
+
__all__ = ["Private", "is_private"]
|