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.
Files changed (182) hide show
  1. strawberry/__init__.py +17 -11
  2. strawberry/aiohttp/handlers/graphql_transport_ws_handler.py +3 -0
  3. strawberry/aiohttp/handlers/graphql_ws_handler.py +3 -0
  4. strawberry/aiohttp/test/client.py +3 -0
  5. strawberry/aiohttp/views.py +3 -0
  6. strawberry/annotation.py +19 -19
  7. strawberry/asgi/__init__.py +3 -3
  8. strawberry/asgi/handlers/graphql_transport_ws_handler.py +3 -0
  9. strawberry/asgi/handlers/graphql_ws_handler.py +3 -0
  10. strawberry/asgi/test/client.py +3 -0
  11. strawberry/chalice/views.py +12 -3
  12. strawberry/channels/handlers/__init__.py +0 -0
  13. strawberry/channels/handlers/base.py +5 -5
  14. strawberry/channels/handlers/graphql_transport_ws_handler.py +3 -0
  15. strawberry/channels/handlers/graphql_ws_handler.py +3 -0
  16. strawberry/channels/handlers/http_handler.py +5 -2
  17. strawberry/channels/handlers/ws_handler.py +4 -1
  18. strawberry/channels/router.py +9 -5
  19. strawberry/channels/testing.py +11 -4
  20. strawberry/cli/commands/upgrade/__init__.py +13 -5
  21. strawberry/cli/commands/upgrade/_fake_progress.py +2 -1
  22. strawberry/cli/commands/upgrade/_run_codemod.py +18 -1
  23. strawberry/codegen/exceptions.py +8 -0
  24. strawberry/codegen/query_codegen.py +16 -7
  25. strawberry/codegen/types.py +32 -1
  26. strawberry/codemods/update_imports.py +136 -0
  27. strawberry/dataloader.py +13 -0
  28. strawberry/directive.py +52 -4
  29. strawberry/django/context.py +4 -1
  30. strawberry/django/test/client.py +3 -0
  31. strawberry/django/views.py +3 -0
  32. strawberry/exceptions/__init__.py +5 -5
  33. strawberry/exceptions/duplicated_type_name.py +1 -1
  34. strawberry/exceptions/invalid_argument_type.py +3 -3
  35. strawberry/exceptions/invalid_union_type.py +5 -6
  36. strawberry/exceptions/missing_arguments_annotations.py +1 -1
  37. strawberry/exceptions/missing_dependencies.py +10 -2
  38. strawberry/exceptions/missing_return_annotation.py +1 -1
  39. strawberry/exceptions/permission_fail_silently_requires_optional.py +3 -3
  40. strawberry/exceptions/scalar_already_registered.py +1 -1
  41. strawberry/exceptions/unresolved_field_type.py +2 -2
  42. strawberry/exceptions/utils/source_finder.py +5 -2
  43. strawberry/experimental/pydantic/conversion.py +5 -5
  44. strawberry/experimental/pydantic/conversion_types.py +4 -2
  45. strawberry/experimental/pydantic/error_type.py +2 -2
  46. strawberry/experimental/pydantic/fields.py +2 -2
  47. strawberry/experimental/pydantic/object_type.py +11 -7
  48. strawberry/experimental/pydantic/utils.py +4 -5
  49. strawberry/ext/dataclasses/dataclasses.py +2 -1
  50. strawberry/ext/mypy_plugin.py +10 -8
  51. strawberry/extensions/add_validation_rules.py +27 -23
  52. strawberry/extensions/base_extension.py +6 -4
  53. strawberry/extensions/directives.py +4 -1
  54. strawberry/extensions/disable_validation.py +15 -12
  55. strawberry/extensions/field_extension.py +11 -5
  56. strawberry/extensions/mask_errors.py +3 -0
  57. strawberry/extensions/max_aliases.py +21 -19
  58. strawberry/extensions/max_tokens.py +14 -16
  59. strawberry/extensions/parser_cache.py +22 -19
  60. strawberry/extensions/pyinstrument.py +4 -8
  61. strawberry/extensions/query_depth_limiter.py +22 -23
  62. strawberry/extensions/runner.py +3 -0
  63. strawberry/extensions/tracing/apollo.py +3 -0
  64. strawberry/extensions/tracing/datadog.py +7 -2
  65. strawberry/extensions/tracing/opentelemetry.py +3 -0
  66. strawberry/extensions/tracing/sentry.py +3 -0
  67. strawberry/extensions/tracing/utils.py +3 -0
  68. strawberry/extensions/utils.py +3 -0
  69. strawberry/extensions/validation_cache.py +23 -20
  70. strawberry/fastapi/context.py +3 -0
  71. strawberry/fastapi/handlers/graphql_transport_ws_handler.py +3 -0
  72. strawberry/fastapi/handlers/graphql_ws_handler.py +3 -0
  73. strawberry/fastapi/router.py +3 -0
  74. strawberry/federation/argument.py +4 -1
  75. strawberry/federation/enum.py +5 -3
  76. strawberry/federation/field.py +6 -3
  77. strawberry/federation/mutation.py +2 -0
  78. strawberry/federation/object_type.py +7 -4
  79. strawberry/federation/scalar.py +43 -20
  80. strawberry/federation/schema.py +12 -9
  81. strawberry/federation/schema_directive.py +2 -2
  82. strawberry/federation/schema_directives.py +19 -1
  83. strawberry/federation/types.py +5 -2
  84. strawberry/federation/union.py +27 -8
  85. strawberry/field_extensions/input_mutation.py +5 -2
  86. strawberry/file_uploads/scalars.py +3 -1
  87. strawberry/file_uploads/utils.py +3 -0
  88. strawberry/flask/views.py +6 -0
  89. strawberry/http/__init__.py +9 -0
  90. strawberry/http/async_base_view.py +4 -3
  91. strawberry/http/base.py +3 -0
  92. strawberry/http/exceptions.py +3 -0
  93. strawberry/http/ides.py +3 -0
  94. strawberry/http/sync_base_view.py +4 -3
  95. strawberry/http/temporal_response.py +3 -0
  96. strawberry/http/types.py +3 -0
  97. strawberry/http/typevars.py +3 -0
  98. strawberry/litestar/controller.py +6 -0
  99. strawberry/litestar/handlers/__init__.py +0 -0
  100. strawberry/litestar/handlers/graphql_transport_ws_handler.py +3 -0
  101. strawberry/litestar/handlers/graphql_ws_handler.py +3 -0
  102. strawberry/parent.py +27 -21
  103. strawberry/permission.py +70 -27
  104. strawberry/printer/ast_from_value.py +4 -1
  105. strawberry/printer/printer.py +8 -5
  106. strawberry/quart/views.py +3 -0
  107. strawberry/relay/exceptions.py +7 -0
  108. strawberry/relay/fields.py +70 -45
  109. strawberry/relay/types.py +78 -78
  110. strawberry/relay/utils.py +10 -1
  111. strawberry/resolvers.py +3 -0
  112. strawberry/sanic/context.py +3 -0
  113. strawberry/sanic/utils.py +10 -8
  114. strawberry/sanic/views.py +4 -2
  115. strawberry/scalars.py +6 -2
  116. strawberry/schema/base.py +7 -4
  117. strawberry/schema/compat.py +12 -2
  118. strawberry/schema/config.py +3 -0
  119. strawberry/schema/exceptions.py +3 -0
  120. strawberry/schema/execute.py +3 -0
  121. strawberry/schema/name_converter.py +12 -9
  122. strawberry/schema/schema.py +46 -9
  123. strawberry/schema/schema_converter.py +16 -14
  124. strawberry/schema/types/base_scalars.py +3 -1
  125. strawberry/schema/types/concrete_type.py +4 -4
  126. strawberry/schema/types/scalar.py +8 -1
  127. strawberry/schema/validation_rules/one_of.py +3 -0
  128. strawberry/schema_codegen/__init__.py +3 -0
  129. strawberry/schema_directive.py +2 -2
  130. strawberry/starlite/controller.py +3 -0
  131. strawberry/starlite/handlers/__init__.py +0 -0
  132. strawberry/starlite/handlers/graphql_transport_ws_handler.py +3 -0
  133. strawberry/starlite/handlers/graphql_ws_handler.py +3 -0
  134. strawberry/subscriptions/__init__.py +6 -0
  135. strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py +5 -0
  136. strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +12 -17
  137. strawberry/subscriptions/protocols/graphql_transport_ws/types.py +21 -25
  138. strawberry/subscriptions/protocols/graphql_ws/__init__.py +14 -0
  139. strawberry/subscriptions/protocols/graphql_ws/handlers.py +8 -5
  140. strawberry/subscriptions/protocols/graphql_ws/types.py +11 -0
  141. strawberry/test/client.py +44 -29
  142. strawberry/tools/create_type.py +27 -8
  143. strawberry/tools/merge_types.py +5 -3
  144. strawberry/types/__init__.py +8 -1
  145. strawberry/{arguments.py → types/arguments.py} +44 -13
  146. strawberry/{auto.py → types/auto.py} +21 -3
  147. strawberry/types/{types.py → base.py} +234 -10
  148. strawberry/{enum.py → types/enum.py} +69 -9
  149. strawberry/types/execution.py +3 -0
  150. strawberry/{field.py → types/field.py} +46 -23
  151. strawberry/types/fields/resolver.py +2 -2
  152. strawberry/types/graphql.py +3 -0
  153. strawberry/types/info.py +50 -7
  154. strawberry/{lazy_type.py → types/lazy_type.py} +50 -0
  155. strawberry/types/mutation.py +351 -0
  156. strawberry/types/nodes.py +4 -2
  157. strawberry/{object_type.py → types/object_type.py} +108 -29
  158. strawberry/{private.py → types/private.py} +13 -6
  159. strawberry/{custom_scalar.py → types/scalar.py} +39 -23
  160. strawberry/types/type_resolver.py +21 -16
  161. strawberry/{union.py → types/union.py} +24 -9
  162. strawberry/{unset.py → types/unset.py} +20 -0
  163. strawberry/utils/aio.py +8 -0
  164. strawberry/utils/await_maybe.py +3 -0
  165. strawberry/utils/dataclasses.py +3 -0
  166. strawberry/utils/debug.py +5 -2
  167. strawberry/utils/deprecations.py +3 -0
  168. strawberry/utils/graphql_lexer.py +3 -0
  169. strawberry/utils/importer.py +3 -0
  170. strawberry/utils/inspect.py +39 -30
  171. strawberry/utils/logging.py +3 -0
  172. strawberry/utils/operation.py +3 -0
  173. strawberry/utils/str_converters.py +3 -0
  174. strawberry/utils/typing.py +33 -16
  175. {strawberry_graphql-0.235.2.dist-info → strawberry_graphql-0.236.0.dist-info}/METADATA +1 -1
  176. strawberry_graphql-0.236.0.dist-info/RECORD +255 -0
  177. strawberry/mutation.py +0 -8
  178. strawberry/type.py +0 -232
  179. strawberry_graphql-0.235.2.dist-info/RECORD +0 -252
  180. {strawberry_graphql-0.235.2.dist-info → strawberry_graphql-0.236.0.dist-info}/LICENSE +0 -0
  181. {strawberry_graphql-0.235.2.dist-info → strawberry_graphql-0.236.0.dist-info}/WHEEL +0 -0
  182. {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 .type import get_object_definition
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
- >>> @strawberry.type
238
- >>> class X:
239
- >>> field_abc: str = "ABC"
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
- >>> @strawberry.type
401
- >>> class User:
402
- >>> name: str
403
- >>> age: int
404
- >>> # should be {"name": "Lorem", "age": 25}
405
- >>> user_dict = strawberry.asdict(User(name="Lorem", age=25))
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
- Private.__doc__ = """Represents a field that won't be exposed in the GraphQL schema
13
+ """Represents a field that won't be exposed in the GraphQL schema.
14
14
 
15
15
  Example:
16
16
 
17
- >>> import strawberry
18
- >>> @strawberry.type
19
- ... class User:
20
- ... name: str
21
- ... age: strawberry.Private[int]
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"]