strawberry-graphql 0.227.0.dev1713475585__py3-none-any.whl → 0.227.2__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/channels/handlers/base.py +7 -14
- strawberry/codegen/query_codegen.py +2 -4
- strawberry/custom_scalar.py +2 -4
- strawberry/dataloader.py +2 -4
- strawberry/directive.py +1 -2
- strawberry/django/views.py +1 -1
- strawberry/enum.py +2 -4
- strawberry/experimental/pydantic/conversion_types.py +5 -10
- strawberry/experimental/pydantic/error_type.py +1 -1
- strawberry/experimental/pydantic/object_type.py +1 -1
- strawberry/ext/mypy_plugin.py +24 -1
- strawberry/federation/enum.py +2 -4
- strawberry/federation/field.py +3 -6
- strawberry/federation/object_type.py +8 -25
- strawberry/federation/scalar.py +2 -4
- strawberry/federation/schema_directive.py +1 -1
- strawberry/field.py +3 -6
- strawberry/http/async_base_view.py +12 -24
- strawberry/http/base.py +3 -6
- strawberry/http/sync_base_view.py +13 -26
- strawberry/litestar/controller.py +2 -2
- strawberry/object_type.py +32 -23
- strawberry/parent.py +1 -2
- strawberry/printer/printer.py +3 -6
- strawberry/private.py +1 -2
- strawberry/relay/fields.py +2 -4
- strawberry/relay/types.py +12 -24
- strawberry/relay/utils.py +1 -1
- strawberry/schema/execute.py +0 -5
- strawberry/schema/schema.py +0 -11
- strawberry/schema/schema_converter.py +1 -35
- strawberry/schema_codegen/__init__.py +96 -87
- strawberry/schema_directive.py +1 -1
- strawberry/starlite/controller.py +2 -2
- strawberry/type.py +4 -12
- strawberry/types/type_resolver.py +9 -2
- strawberry/types/types.py +1 -13
- strawberry/utils/aio.py +1 -1
- strawberry/utils/typing.py +2 -4
- {strawberry_graphql-0.227.0.dev1713475585.dist-info → strawberry_graphql-0.227.2.dist-info}/METADATA +2 -1
- {strawberry_graphql-0.227.0.dev1713475585.dist-info → strawberry_graphql-0.227.2.dist-info}/RECORD +44 -47
- strawberry/schema/validation_rules/__init__.py +0 -0
- strawberry/schema/validation_rules/one_of.py +0 -80
- strawberry/schema_directives.py +0 -9
- {strawberry_graphql-0.227.0.dev1713475585.dist-info → strawberry_graphql-0.227.2.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.227.0.dev1713475585.dist-info → strawberry_graphql-0.227.2.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.227.0.dev1713475585.dist-info → strawberry_graphql-0.227.2.dist-info}/entry_points.txt +0 -0
strawberry/object_type.py
CHANGED
@@ -67,7 +67,8 @@ def _check_field_annotations(cls: Type[Any]):
|
|
67
67
|
# If the field has a type override then use that instead of using
|
68
68
|
# the class annotations or resolver annotation
|
69
69
|
if field_.type_annotation is not None:
|
70
|
-
|
70
|
+
if field_name not in cls_annotations:
|
71
|
+
cls_annotations[field_name] = field_.type_annotation.annotation
|
71
72
|
continue
|
72
73
|
|
73
74
|
# Make sure the cls has an annotation
|
@@ -85,7 +86,8 @@ def _check_field_annotations(cls: Type[Any]):
|
|
85
86
|
field_name, resolver=field_.base_resolver
|
86
87
|
)
|
87
88
|
|
88
|
-
|
89
|
+
if field_name not in cls_annotations:
|
90
|
+
cls_annotations[field_name] = field_.base_resolver.type_annotation
|
89
91
|
|
90
92
|
# TODO: Make sure the cls annotation agrees with the field's type
|
91
93
|
# >>> if cls_annotations[field_name] != field.base_resolver.type:
|
@@ -133,11 +135,13 @@ def _process_type(
|
|
133
135
|
description: Optional[str] = None,
|
134
136
|
directives: Optional[Sequence[object]] = (),
|
135
137
|
extend: bool = False,
|
138
|
+
original_type_annotations: Optional[Dict[str, Any]] = None,
|
136
139
|
) -> T:
|
137
140
|
name = name or to_camel_case(cls.__name__)
|
141
|
+
original_type_annotations = original_type_annotations or {}
|
138
142
|
|
139
143
|
interfaces = _get_interfaces(cls)
|
140
|
-
fields = _get_fields(cls)
|
144
|
+
fields = _get_fields(cls, original_type_annotations)
|
141
145
|
is_type_of = getattr(cls, "is_type_of", None)
|
142
146
|
resolve_type = getattr(cls, "resolve_type", None)
|
143
147
|
|
@@ -198,8 +202,7 @@ def type(
|
|
198
202
|
description: Optional[str] = None,
|
199
203
|
directives: Optional[Sequence[object]] = (),
|
200
204
|
extend: bool = False,
|
201
|
-
) -> T:
|
202
|
-
...
|
205
|
+
) -> T: ...
|
203
206
|
|
204
207
|
|
205
208
|
@overload
|
@@ -214,8 +217,7 @@ def type(
|
|
214
217
|
description: Optional[str] = None,
|
215
218
|
directives: Optional[Sequence[object]] = (),
|
216
219
|
extend: bool = False,
|
217
|
-
) -> Callable[[T], T]:
|
218
|
-
...
|
220
|
+
) -> Callable[[T], T]: ...
|
219
221
|
|
220
222
|
|
221
223
|
def type(
|
@@ -247,7 +249,25 @@ def type(
|
|
247
249
|
exc = ObjectIsNotClassError.type
|
248
250
|
raise exc(cls)
|
249
251
|
|
252
|
+
# when running `_wrap_dataclass` we lose some of the information about the
|
253
|
+
# the passed types, especially the type_annotation inside the StrawberryField
|
254
|
+
# this makes it impossible to customise the field type, like this:
|
255
|
+
# >>> @strawberry.type
|
256
|
+
# >>> class Query:
|
257
|
+
# >>> a: int = strawberry.field(graphql_type=str)
|
258
|
+
# so we need to extract the information before running `_wrap_dataclass`
|
259
|
+
original_type_annotations: Dict[str, Any] = {}
|
260
|
+
|
261
|
+
annotations = getattr(cls, "__annotations__", {})
|
262
|
+
|
263
|
+
for field_name in annotations:
|
264
|
+
field = getattr(cls, field_name, None)
|
265
|
+
|
266
|
+
if field and isinstance(field, StrawberryField) and field.type_annotation:
|
267
|
+
original_type_annotations[field_name] = field.type_annotation.annotation
|
268
|
+
|
250
269
|
wrapped = _wrap_dataclass(cls)
|
270
|
+
|
251
271
|
return _process_type(
|
252
272
|
wrapped,
|
253
273
|
name=name,
|
@@ -256,6 +276,7 @@ def type(
|
|
256
276
|
description=description,
|
257
277
|
directives=directives,
|
258
278
|
extend=extend,
|
279
|
+
original_type_annotations=original_type_annotations,
|
259
280
|
)
|
260
281
|
|
261
282
|
if cls is None:
|
@@ -272,11 +293,9 @@ def input(
|
|
272
293
|
cls: T,
|
273
294
|
*,
|
274
295
|
name: Optional[str] = None,
|
275
|
-
one_of: Optional[bool] = None,
|
276
296
|
description: Optional[str] = None,
|
277
297
|
directives: Optional[Sequence[object]] = (),
|
278
|
-
) -> T:
|
279
|
-
...
|
298
|
+
) -> T: ...
|
280
299
|
|
281
300
|
|
282
301
|
@overload
|
@@ -286,18 +305,15 @@ def input(
|
|
286
305
|
def input(
|
287
306
|
*,
|
288
307
|
name: Optional[str] = None,
|
289
|
-
one_of: Optional[bool] = None,
|
290
308
|
description: Optional[str] = None,
|
291
309
|
directives: Optional[Sequence[object]] = (),
|
292
|
-
) -> Callable[[T], T]:
|
293
|
-
...
|
310
|
+
) -> Callable[[T], T]: ...
|
294
311
|
|
295
312
|
|
296
313
|
def input(
|
297
314
|
cls: Optional[T] = None,
|
298
315
|
*,
|
299
316
|
name: Optional[str] = None,
|
300
|
-
one_of: Optional[bool] = None,
|
301
317
|
description: Optional[str] = None,
|
302
318
|
directives: Optional[Sequence[object]] = (),
|
303
319
|
):
|
@@ -308,11 +324,6 @@ def input(
|
|
308
324
|
>>> field_abc: str = "ABC"
|
309
325
|
"""
|
310
326
|
|
311
|
-
from strawberry.schema_directives import OneOf
|
312
|
-
|
313
|
-
if one_of:
|
314
|
-
directives = (*(directives or ()), OneOf())
|
315
|
-
|
316
327
|
return type( # type: ignore # not sure why mypy complains here
|
317
328
|
cls,
|
318
329
|
name=name,
|
@@ -332,8 +343,7 @@ def interface(
|
|
332
343
|
name: Optional[str] = None,
|
333
344
|
description: Optional[str] = None,
|
334
345
|
directives: Optional[Sequence[object]] = (),
|
335
|
-
) -> T:
|
336
|
-
...
|
346
|
+
) -> T: ...
|
337
347
|
|
338
348
|
|
339
349
|
@overload
|
@@ -345,8 +355,7 @@ def interface(
|
|
345
355
|
name: Optional[str] = None,
|
346
356
|
description: Optional[str] = None,
|
347
357
|
directives: Optional[Sequence[object]] = (),
|
348
|
-
) -> Callable[[T], T]:
|
349
|
-
...
|
358
|
+
) -> Callable[[T], T]: ...
|
350
359
|
|
351
360
|
|
352
361
|
@dataclass_transform(
|
strawberry/parent.py
CHANGED
strawberry/printer/printer.py
CHANGED
@@ -69,20 +69,17 @@ class PrintExtras:
|
|
69
69
|
|
70
70
|
|
71
71
|
@overload
|
72
|
-
def _serialize_dataclasses(value: Dict[_T, object]) -> Dict[_T, object]:
|
73
|
-
...
|
72
|
+
def _serialize_dataclasses(value: Dict[_T, object]) -> Dict[_T, object]: ...
|
74
73
|
|
75
74
|
|
76
75
|
@overload
|
77
76
|
def _serialize_dataclasses(
|
78
77
|
value: Union[List[object], Tuple[object]],
|
79
|
-
) -> List[object]:
|
80
|
-
...
|
78
|
+
) -> List[object]: ...
|
81
79
|
|
82
80
|
|
83
81
|
@overload
|
84
|
-
def _serialize_dataclasses(value: object) -> object:
|
85
|
-
...
|
82
|
+
def _serialize_dataclasses(value: object) -> object: ...
|
86
83
|
|
87
84
|
|
88
85
|
def _serialize_dataclasses(value):
|
strawberry/private.py
CHANGED
strawberry/relay/fields.py
CHANGED
@@ -331,8 +331,7 @@ def connection(
|
|
331
331
|
metadata: Optional[Mapping[Any, Any]] = None,
|
332
332
|
directives: Optional[Sequence[object]] = (),
|
333
333
|
extensions: List[FieldExtension] = (), # type: ignore
|
334
|
-
) -> Any:
|
335
|
-
...
|
334
|
+
) -> Any: ...
|
336
335
|
|
337
336
|
|
338
337
|
@overload
|
@@ -349,8 +348,7 @@ def connection(
|
|
349
348
|
metadata: Optional[Mapping[Any, Any]] = None,
|
350
349
|
directives: Optional[Sequence[object]] = (),
|
351
350
|
extensions: List[FieldExtension] = (), # type: ignore
|
352
|
-
) -> StrawberryField:
|
353
|
-
...
|
351
|
+
) -> StrawberryField: ...
|
354
352
|
|
355
353
|
|
356
354
|
def connection(
|
strawberry/relay/types.py
CHANGED
@@ -130,8 +130,7 @@ class GlobalID:
|
|
130
130
|
*,
|
131
131
|
required: Literal[True] = ...,
|
132
132
|
ensure_type: Type[_T],
|
133
|
-
) -> _T:
|
134
|
-
...
|
133
|
+
) -> _T: ...
|
135
134
|
|
136
135
|
@overload
|
137
136
|
async def resolve_node(
|
@@ -140,8 +139,7 @@ class GlobalID:
|
|
140
139
|
*,
|
141
140
|
required: Literal[True],
|
142
141
|
ensure_type: None = ...,
|
143
|
-
) -> Node:
|
144
|
-
...
|
142
|
+
) -> Node: ...
|
145
143
|
|
146
144
|
@overload
|
147
145
|
async def resolve_node(
|
@@ -150,8 +148,7 @@ class GlobalID:
|
|
150
148
|
*,
|
151
149
|
required: bool = ...,
|
152
150
|
ensure_type: None = ...,
|
153
|
-
) -> Optional[Node]:
|
154
|
-
...
|
151
|
+
) -> Optional[Node]: ...
|
155
152
|
|
156
153
|
async def resolve_node(self, info, *, required=False, ensure_type=None) -> Any:
|
157
154
|
"""Resolve the type name and node id info to the node itself.
|
@@ -235,8 +232,7 @@ class GlobalID:
|
|
235
232
|
*,
|
236
233
|
required: Literal[True] = ...,
|
237
234
|
ensure_type: Type[_T],
|
238
|
-
) -> _T:
|
239
|
-
...
|
235
|
+
) -> _T: ...
|
240
236
|
|
241
237
|
@overload
|
242
238
|
def resolve_node_sync(
|
@@ -245,8 +241,7 @@ class GlobalID:
|
|
245
241
|
*,
|
246
242
|
required: Literal[True],
|
247
243
|
ensure_type: None = ...,
|
248
|
-
) -> Node:
|
249
|
-
...
|
244
|
+
) -> Node: ...
|
250
245
|
|
251
246
|
@overload
|
252
247
|
def resolve_node_sync(
|
@@ -255,8 +250,7 @@ class GlobalID:
|
|
255
250
|
*,
|
256
251
|
required: bool = ...,
|
257
252
|
ensure_type: None = ...,
|
258
|
-
) -> Optional[Node]:
|
259
|
-
...
|
253
|
+
) -> Optional[Node]: ...
|
260
254
|
|
261
255
|
def resolve_node_sync(self, info, *, required=False, ensure_type=None) -> Any:
|
262
256
|
"""Resolve the type name and node id info to the node itself.
|
@@ -485,8 +479,7 @@ class Node:
|
|
485
479
|
info: Info,
|
486
480
|
node_ids: Iterable[str],
|
487
481
|
required: Literal[True],
|
488
|
-
) -> AwaitableOrValue[Iterable[Self]]:
|
489
|
-
...
|
482
|
+
) -> AwaitableOrValue[Iterable[Self]]: ...
|
490
483
|
|
491
484
|
@overload
|
492
485
|
@classmethod
|
@@ -496,8 +489,7 @@ class Node:
|
|
496
489
|
info: Info,
|
497
490
|
node_ids: Iterable[str],
|
498
491
|
required: Literal[False] = ...,
|
499
|
-
) -> AwaitableOrValue[Iterable[Optional[Self]]]:
|
500
|
-
...
|
492
|
+
) -> AwaitableOrValue[Iterable[Optional[Self]]]: ...
|
501
493
|
|
502
494
|
@overload
|
503
495
|
@classmethod
|
@@ -510,8 +502,7 @@ class Node:
|
|
510
502
|
) -> Union[
|
511
503
|
AwaitableOrValue[Iterable[Self]],
|
512
504
|
AwaitableOrValue[Iterable[Optional[Self]]],
|
513
|
-
]:
|
514
|
-
...
|
505
|
+
]: ...
|
515
506
|
|
516
507
|
@classmethod
|
517
508
|
def resolve_nodes(
|
@@ -555,8 +546,7 @@ class Node:
|
|
555
546
|
*,
|
556
547
|
info: Info,
|
557
548
|
required: Literal[True],
|
558
|
-
) -> AwaitableOrValue[Self]:
|
559
|
-
...
|
549
|
+
) -> AwaitableOrValue[Self]: ...
|
560
550
|
|
561
551
|
@overload
|
562
552
|
@classmethod
|
@@ -566,8 +556,7 @@ class Node:
|
|
566
556
|
*,
|
567
557
|
info: Info,
|
568
558
|
required: Literal[False] = ...,
|
569
|
-
) -> AwaitableOrValue[Optional[Self]]:
|
570
|
-
...
|
559
|
+
) -> AwaitableOrValue[Optional[Self]]: ...
|
571
560
|
|
572
561
|
@overload
|
573
562
|
@classmethod
|
@@ -577,8 +566,7 @@ class Node:
|
|
577
566
|
*,
|
578
567
|
info: Info,
|
579
568
|
required: bool,
|
580
|
-
) -> AwaitableOrValue[Optional[Self]]:
|
581
|
-
...
|
569
|
+
) -> AwaitableOrValue[Optional[Self]]: ...
|
582
570
|
|
583
571
|
@classmethod
|
584
572
|
def resolve_node(
|
strawberry/relay/utils.py
CHANGED
@@ -41,7 +41,7 @@ def to_base64(type_: Union[str, type, StrawberryObjectDefinition], node_id: Any)
|
|
41
41
|
The node id itself
|
42
42
|
|
43
43
|
Returns:
|
44
|
-
A
|
44
|
+
A GlobalID, which is a string resulting from base64 encoding <TypeName>:<NodeID>.
|
45
45
|
|
46
46
|
Raises:
|
47
47
|
ValueError:
|
strawberry/schema/execute.py
CHANGED
@@ -23,7 +23,6 @@ from graphql.validation import validate
|
|
23
23
|
|
24
24
|
from strawberry.exceptions import MissingQueryError
|
25
25
|
from strawberry.extensions.runner import SchemaExtensionsRunner
|
26
|
-
from strawberry.schema.validation_rules.one_of import OneOfInputValidationRule
|
27
26
|
from strawberry.types import ExecutionResult
|
28
27
|
|
29
28
|
from .exceptions import InvalidOperationTypeError
|
@@ -56,10 +55,6 @@ def validate_document(
|
|
56
55
|
document: DocumentNode,
|
57
56
|
validation_rules: Tuple[Type[ASTValidationRule], ...],
|
58
57
|
) -> List[GraphQLError]:
|
59
|
-
validation_rules = (
|
60
|
-
*validation_rules,
|
61
|
-
OneOfInputValidationRule,
|
62
|
-
)
|
63
58
|
return validate(
|
64
59
|
schema,
|
65
60
|
document,
|
strawberry/schema/schema.py
CHANGED
@@ -16,8 +16,6 @@ from typing import (
|
|
16
16
|
)
|
17
17
|
|
18
18
|
from graphql import (
|
19
|
-
GraphQLBoolean,
|
20
|
-
GraphQLField,
|
21
19
|
GraphQLNamedType,
|
22
20
|
GraphQLNonNull,
|
23
21
|
GraphQLSchema,
|
@@ -170,7 +168,6 @@ class Schema(BaseSchema):
|
|
170
168
|
|
171
169
|
self._warn_for_federation_directives()
|
172
170
|
self._resolve_node_ids()
|
173
|
-
self._extend_introspection()
|
174
171
|
|
175
172
|
# Validate schema early because we want developers to know about
|
176
173
|
# possible issues as soon as possible
|
@@ -378,14 +375,6 @@ class Schema(BaseSchema):
|
|
378
375
|
stacklevel=3,
|
379
376
|
)
|
380
377
|
|
381
|
-
def _extend_introspection(self):
|
382
|
-
def _resolve_is_one_of(obj: Any, info: Any) -> bool:
|
383
|
-
return obj.extensions["strawberry-definition"].is_one_of
|
384
|
-
|
385
|
-
instrospection_type = self._schema.type_map["__Type"]
|
386
|
-
instrospection_type.fields["isOneOf"] = GraphQLField(GraphQLBoolean) # type: ignore[attr-defined]
|
387
|
-
instrospection_type.fields["isOneOf"].resolve = _resolve_is_one_of # type: ignore[attr-defined]
|
388
|
-
|
389
378
|
def as_str(self) -> str:
|
390
379
|
return print_schema(self)
|
391
380
|
|
@@ -26,7 +26,6 @@ from graphql import (
|
|
26
26
|
GraphQLDirective,
|
27
27
|
GraphQLEnumType,
|
28
28
|
GraphQLEnumValue,
|
29
|
-
GraphQLError,
|
30
29
|
GraphQLField,
|
31
30
|
GraphQLInputField,
|
32
31
|
GraphQLInputObjectType,
|
@@ -102,8 +101,7 @@ class FieldConverterProtocol(Generic[FieldType], Protocol):
|
|
102
101
|
field: StrawberryField,
|
103
102
|
*,
|
104
103
|
type_definition: Optional[StrawberryObjectDefinition] = None,
|
105
|
-
) -> FieldType:
|
106
|
-
...
|
104
|
+
) -> FieldType: ...
|
107
105
|
|
108
106
|
|
109
107
|
def _get_thunk_mapping(
|
@@ -411,37 +409,6 @@ class GraphQLCoreConverter:
|
|
411
409
|
assert isinstance(graphql_object_type, GraphQLInputObjectType) # For mypy
|
412
410
|
return graphql_object_type
|
413
411
|
|
414
|
-
def check_one_of(value: dict[str, Any]) -> dict[str, Any]:
|
415
|
-
if len(value) != 1:
|
416
|
-
raise GraphQLError(
|
417
|
-
f"OneOf Input Object '{type_name}' must specify exactly one key."
|
418
|
-
)
|
419
|
-
|
420
|
-
first_key, first_value = next(iter(value.items()))
|
421
|
-
|
422
|
-
if first_value is None or first_value is UNSET:
|
423
|
-
raise GraphQLError(
|
424
|
-
f"Value for member field '{first_key}' must be non-null"
|
425
|
-
)
|
426
|
-
|
427
|
-
# We are populating all missing keys with `None`, so users
|
428
|
-
# don't have to set an explicit default for the input type
|
429
|
-
# The alternative is to tell them to use `UNSET`, but it looks
|
430
|
-
# a bit unfriendly to use
|
431
|
-
|
432
|
-
for field in type_definition.fields:
|
433
|
-
name = self.config.name_converter.from_field(field)
|
434
|
-
if name not in value:
|
435
|
-
value[name] = None
|
436
|
-
|
437
|
-
return value
|
438
|
-
|
439
|
-
out_type = (
|
440
|
-
check_one_of
|
441
|
-
if type_definition.is_input and type_definition.is_one_of
|
442
|
-
else None
|
443
|
-
)
|
444
|
-
|
445
412
|
graphql_object_type = GraphQLInputObjectType(
|
446
413
|
name=type_name,
|
447
414
|
fields=lambda: self.get_graphql_input_fields(type_definition),
|
@@ -449,7 +416,6 @@ class GraphQLCoreConverter:
|
|
449
416
|
extensions={
|
450
417
|
GraphQLCoreConverter.DEFINITION_BACKREF: type_definition,
|
451
418
|
},
|
452
|
-
out_type=out_type,
|
453
419
|
)
|
454
420
|
|
455
421
|
self.type_map[type_name] = ConcreteType(
|