strawberry-graphql 0.275.7__py3-none-any.whl → 0.284.3__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.
Potentially problematic release.
This version of strawberry-graphql might be problematic. Click here for more details.
- strawberry/__init__.py +2 -0
- strawberry/aiohttp/test/client.py +8 -15
- strawberry/aiohttp/views.py +15 -64
- strawberry/annotation.py +70 -25
- strawberry/asgi/__init__.py +22 -56
- strawberry/asgi/test/client.py +6 -6
- strawberry/chalice/views.py +13 -79
- strawberry/channels/handlers/base.py +7 -8
- strawberry/channels/handlers/http_handler.py +50 -32
- strawberry/channels/handlers/ws_handler.py +12 -14
- strawberry/channels/router.py +3 -4
- strawberry/channels/testing.py +7 -9
- strawberry/cli/__init__.py +7 -6
- strawberry/cli/commands/codegen.py +7 -7
- strawberry/cli/commands/dev.py +72 -0
- strawberry/cli/commands/schema_codegen.py +1 -2
- strawberry/cli/commands/server.py +3 -44
- strawberry/cli/commands/upgrade/__init__.py +3 -3
- strawberry/cli/commands/upgrade/_run_codemod.py +2 -2
- strawberry/cli/constants.py +1 -2
- strawberry/cli/{debug_server.py → dev_server.py} +3 -7
- strawberry/codegen/plugins/print_operation.py +2 -2
- strawberry/codegen/plugins/python.py +2 -2
- strawberry/codegen/query_codegen.py +20 -30
- strawberry/codegen/types.py +32 -32
- strawberry/codemods/__init__.py +9 -0
- strawberry/codemods/annotated_unions.py +2 -2
- strawberry/codemods/maybe_optional.py +118 -0
- strawberry/dataloader.py +28 -24
- strawberry/directive.py +6 -7
- strawberry/django/test/client.py +3 -3
- strawberry/django/views.py +21 -91
- strawberry/exceptions/__init__.py +4 -4
- strawberry/exceptions/conflicting_arguments.py +2 -2
- strawberry/exceptions/duplicated_type_name.py +4 -4
- strawberry/exceptions/exception.py +3 -3
- strawberry/exceptions/handler.py +8 -7
- strawberry/exceptions/invalid_argument_type.py +2 -2
- strawberry/exceptions/invalid_superclass_interface.py +2 -2
- strawberry/exceptions/invalid_union_type.py +4 -4
- strawberry/exceptions/missing_arguments_annotations.py +2 -2
- strawberry/exceptions/missing_dependencies.py +2 -4
- strawberry/exceptions/missing_field_annotation.py +2 -2
- strawberry/exceptions/missing_return_annotation.py +2 -2
- strawberry/exceptions/object_is_not_a_class.py +2 -2
- strawberry/exceptions/object_is_not_an_enum.py +2 -2
- strawberry/exceptions/permission_fail_silently_requires_optional.py +2 -2
- strawberry/exceptions/private_strawberry_field.py +2 -2
- strawberry/exceptions/scalar_already_registered.py +2 -2
- strawberry/exceptions/syntax.py +3 -3
- strawberry/exceptions/unresolved_field_type.py +2 -2
- strawberry/exceptions/utils/source_finder.py +25 -25
- strawberry/experimental/pydantic/_compat.py +8 -7
- strawberry/experimental/pydantic/conversion.py +2 -2
- strawberry/experimental/pydantic/conversion_types.py +2 -2
- strawberry/experimental/pydantic/error_type.py +10 -12
- strawberry/experimental/pydantic/fields.py +9 -15
- strawberry/experimental/pydantic/object_type.py +17 -25
- strawberry/experimental/pydantic/utils.py +1 -2
- strawberry/ext/mypy_plugin.py +12 -14
- strawberry/extensions/base_extension.py +2 -1
- strawberry/extensions/context.py +13 -18
- strawberry/extensions/directives.py +9 -3
- strawberry/extensions/field_extension.py +4 -4
- strawberry/extensions/mask_errors.py +24 -13
- strawberry/extensions/max_aliases.py +1 -3
- strawberry/extensions/parser_cache.py +1 -2
- strawberry/extensions/query_depth_limiter.py +18 -14
- strawberry/extensions/runner.py +2 -2
- strawberry/extensions/tracing/apollo.py +3 -3
- strawberry/extensions/tracing/datadog.py +3 -3
- strawberry/extensions/tracing/opentelemetry.py +6 -8
- strawberry/extensions/tracing/utils.py +3 -1
- strawberry/extensions/utils.py +2 -2
- strawberry/extensions/validation_cache.py +2 -3
- strawberry/fastapi/context.py +6 -6
- strawberry/fastapi/router.py +43 -42
- strawberry/federation/argument.py +4 -5
- strawberry/federation/enum.py +18 -21
- strawberry/federation/field.py +94 -97
- strawberry/federation/object_type.py +56 -58
- strawberry/federation/scalar.py +27 -35
- strawberry/federation/schema.py +15 -16
- strawberry/federation/schema_directive.py +7 -6
- strawberry/federation/schema_directives.py +11 -11
- strawberry/federation/union.py +4 -4
- strawberry/flask/views.py +16 -85
- strawberry/http/__init__.py +30 -20
- strawberry/http/async_base_view.py +208 -89
- strawberry/http/base.py +28 -11
- strawberry/http/exceptions.py +5 -7
- strawberry/http/ides.py +2 -3
- strawberry/http/sync_base_view.py +115 -69
- strawberry/http/types.py +3 -3
- strawberry/litestar/controller.py +43 -77
- strawberry/permission.py +4 -6
- strawberry/printer/ast_from_value.py +3 -5
- strawberry/printer/printer.py +18 -15
- strawberry/quart/views.py +16 -48
- strawberry/relay/exceptions.py +4 -4
- strawberry/relay/fields.py +33 -32
- strawberry/relay/types.py +32 -35
- strawberry/relay/utils.py +11 -23
- strawberry/resolvers.py +2 -1
- strawberry/sanic/context.py +1 -0
- strawberry/sanic/utils.py +3 -3
- strawberry/sanic/views.py +15 -54
- strawberry/scalars.py +2 -2
- strawberry/schema/_graphql_core.py +55 -0
- strawberry/schema/base.py +32 -33
- strawberry/schema/compat.py +9 -9
- strawberry/schema/config.py +10 -1
- strawberry/schema/exceptions.py +1 -3
- strawberry/schema/name_converter.py +9 -8
- strawberry/schema/schema.py +133 -100
- strawberry/schema/schema_converter.py +96 -58
- strawberry/schema/types/base_scalars.py +1 -1
- strawberry/schema/types/concrete_type.py +5 -5
- strawberry/schema/validation_rules/maybe_null.py +136 -0
- strawberry/schema_codegen/__init__.py +3 -3
- strawberry/schema_directive.py +7 -6
- strawberry/static/graphiql.html +5 -5
- strawberry/streamable.py +35 -0
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +5 -16
- strawberry/subscriptions/protocols/graphql_transport_ws/types.py +20 -20
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +5 -12
- strawberry/subscriptions/protocols/graphql_ws/types.py +14 -14
- strawberry/test/client.py +18 -18
- strawberry/tools/create_type.py +2 -3
- strawberry/types/arguments.py +41 -28
- strawberry/types/auto.py +3 -4
- strawberry/types/base.py +25 -27
- strawberry/types/enum.py +22 -25
- strawberry/types/execution.py +21 -16
- strawberry/types/field.py +109 -130
- strawberry/types/fields/resolver.py +19 -21
- strawberry/types/info.py +5 -11
- strawberry/types/lazy_type.py +2 -3
- strawberry/types/maybe.py +12 -3
- strawberry/types/mutation.py +115 -118
- strawberry/types/nodes.py +2 -2
- strawberry/types/object_type.py +43 -63
- strawberry/types/scalar.py +37 -43
- strawberry/types/union.py +12 -14
- strawberry/utils/aio.py +12 -9
- strawberry/utils/await_maybe.py +3 -3
- strawberry/utils/deprecations.py +2 -2
- strawberry/utils/importer.py +1 -2
- strawberry/utils/inspect.py +4 -6
- strawberry/utils/logging.py +2 -2
- strawberry/utils/operation.py +4 -4
- strawberry/utils/typing.py +18 -83
- {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/METADATA +14 -8
- strawberry_graphql-0.284.3.dist-info/RECORD +243 -0
- {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/WHEEL +1 -1
- strawberry/utils/dataclasses.py +0 -37
- strawberry/utils/debug.py +0 -46
- strawberry/utils/graphql_lexer.py +0 -35
- strawberry_graphql-0.275.7.dist-info/RECORD +0 -241
- {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/entry_points.txt +0 -0
- {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info/licenses}/LICENSE +0 -0
strawberry/schema/schema.py
CHANGED
|
@@ -2,20 +2,16 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
4
|
from asyncio import ensure_future
|
|
5
|
-
from collections.abc import AsyncGenerator, AsyncIterator, Awaitable, Iterable
|
|
5
|
+
from collections.abc import AsyncGenerator, AsyncIterator, Awaitable, Callable, Iterable
|
|
6
6
|
from functools import cached_property, lru_cache
|
|
7
7
|
from inspect import isawaitable
|
|
8
8
|
from typing import (
|
|
9
9
|
TYPE_CHECKING,
|
|
10
10
|
Any,
|
|
11
|
-
Callable,
|
|
12
11
|
NamedTuple,
|
|
13
|
-
Optional,
|
|
14
|
-
Union,
|
|
15
12
|
cast,
|
|
16
13
|
)
|
|
17
14
|
|
|
18
|
-
from graphql import ExecutionContext as GraphQLExecutionContext
|
|
19
15
|
from graphql import ExecutionResult as GraphQLExecutionResult
|
|
20
16
|
from graphql import (
|
|
21
17
|
ExecutionResult as OriginalExecutionResult,
|
|
@@ -36,7 +32,6 @@ from graphql import (
|
|
|
36
32
|
parse,
|
|
37
33
|
validate_schema,
|
|
38
34
|
)
|
|
39
|
-
from graphql.execution import execute, subscribe
|
|
40
35
|
from graphql.execution.middleware import MiddlewareManager
|
|
41
36
|
from graphql.type.directives import specified_directives
|
|
42
37
|
from graphql.validation import validate
|
|
@@ -52,6 +47,7 @@ from strawberry.extensions.directives import (
|
|
|
52
47
|
from strawberry.extensions.runner import SchemaExtensionsRunner
|
|
53
48
|
from strawberry.printer import print_schema
|
|
54
49
|
from strawberry.schema.schema_converter import GraphQLCoreConverter
|
|
50
|
+
from strawberry.schema.validation_rules.maybe_null import MaybeNullValidationRule
|
|
55
51
|
from strawberry.schema.validation_rules.one_of import OneOfInputValidationRule
|
|
56
52
|
from strawberry.types.base import (
|
|
57
53
|
StrawberryObjectDefinition,
|
|
@@ -69,15 +65,23 @@ from strawberry.utils.aio import aclosing
|
|
|
69
65
|
from strawberry.utils.await_maybe import await_maybe
|
|
70
66
|
|
|
71
67
|
from . import compat
|
|
68
|
+
from ._graphql_core import (
|
|
69
|
+
GraphQLExecutionContext,
|
|
70
|
+
GraphQLIncrementalExecutionResults,
|
|
71
|
+
ResultType,
|
|
72
|
+
execute,
|
|
73
|
+
experimental_execute_incrementally,
|
|
74
|
+
incremental_execution_directives,
|
|
75
|
+
subscribe,
|
|
76
|
+
)
|
|
72
77
|
from .base import BaseSchema
|
|
73
78
|
from .config import StrawberryConfig
|
|
74
79
|
from .exceptions import CannotGetOperationTypeError, InvalidOperationTypeError
|
|
75
80
|
|
|
76
81
|
if TYPE_CHECKING:
|
|
77
82
|
from collections.abc import Iterable, Mapping
|
|
78
|
-
from
|
|
83
|
+
from typing import TypeAlias
|
|
79
84
|
|
|
80
|
-
from graphql.execution.collect_fields import FieldGroup # type: ignore
|
|
81
85
|
from graphql.language import DocumentNode
|
|
82
86
|
from graphql.pyutils import Path
|
|
83
87
|
from graphql.type import GraphQLResolveInfo
|
|
@@ -91,13 +95,13 @@ if TYPE_CHECKING:
|
|
|
91
95
|
from strawberry.types.union import StrawberryUnion
|
|
92
96
|
|
|
93
97
|
SubscriptionResult: TypeAlias = AsyncGenerator[
|
|
94
|
-
|
|
98
|
+
PreExecutionError | ExecutionResult, None
|
|
95
99
|
]
|
|
96
100
|
|
|
97
|
-
OriginSubscriptionResult =
|
|
98
|
-
OriginalExecutionResult
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
OriginSubscriptionResult: TypeAlias = (
|
|
102
|
+
OriginalExecutionResult | AsyncIterator[OriginalExecutionResult]
|
|
103
|
+
)
|
|
104
|
+
|
|
101
105
|
|
|
102
106
|
DEFAULT_ALLOWED_OPERATION_TYPES = {
|
|
103
107
|
OperationType.QUERY,
|
|
@@ -105,7 +109,7 @@ DEFAULT_ALLOWED_OPERATION_TYPES = {
|
|
|
105
109
|
OperationType.SUBSCRIPTION,
|
|
106
110
|
}
|
|
107
111
|
ProcessErrors: TypeAlias = (
|
|
108
|
-
"Callable[[list[GraphQLError],
|
|
112
|
+
"Callable[[list[GraphQLError], ExecutionContext | None], None]"
|
|
109
113
|
)
|
|
110
114
|
|
|
111
115
|
|
|
@@ -117,6 +121,7 @@ def validate_document(
|
|
|
117
121
|
) -> list[GraphQLError]:
|
|
118
122
|
validation_rules = (
|
|
119
123
|
*validation_rules,
|
|
124
|
+
MaybeNullValidationRule,
|
|
120
125
|
OneOfInputValidationRule,
|
|
121
126
|
)
|
|
122
127
|
return validate(
|
|
@@ -129,16 +134,19 @@ def validate_document(
|
|
|
129
134
|
def _run_validation(execution_context: ExecutionContext) -> None:
|
|
130
135
|
# Check if there are any validation rules or if validation has
|
|
131
136
|
# already been run by an extension
|
|
132
|
-
if
|
|
137
|
+
if (
|
|
138
|
+
len(execution_context.validation_rules) > 0
|
|
139
|
+
and execution_context.pre_execution_errors is None
|
|
140
|
+
):
|
|
133
141
|
assert execution_context.graphql_document
|
|
134
|
-
execution_context.
|
|
142
|
+
execution_context.pre_execution_errors = validate_document(
|
|
135
143
|
execution_context.schema._schema,
|
|
136
144
|
execution_context.graphql_document,
|
|
137
145
|
execution_context.validation_rules,
|
|
138
146
|
)
|
|
139
147
|
|
|
140
148
|
|
|
141
|
-
def _coerce_error(error:
|
|
149
|
+
def _coerce_error(error: GraphQLError | Exception) -> GraphQLError:
|
|
142
150
|
if isinstance(error, GraphQLError):
|
|
143
151
|
return error
|
|
144
152
|
return GraphQLError(str(error), original_error=error)
|
|
@@ -168,17 +176,18 @@ class StrawberryGraphQLCoreExecutionContext(GraphQLExecutionContext):
|
|
|
168
176
|
|
|
169
177
|
self.operation_extensions = operation_extensions
|
|
170
178
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
+
if IS_GQL_33:
|
|
180
|
+
|
|
181
|
+
def build_resolve_info(
|
|
182
|
+
self,
|
|
183
|
+
field_def: GraphQLField,
|
|
184
|
+
field_nodes: list[FieldNode],
|
|
185
|
+
parent_type: GraphQLObjectType,
|
|
186
|
+
path: Path,
|
|
187
|
+
) -> GraphQLResolveInfo:
|
|
179
188
|
return _OperationContextAwareGraphQLResolveInfo( # type: ignore
|
|
180
|
-
|
|
181
|
-
|
|
189
|
+
field_nodes[0].name.value,
|
|
190
|
+
field_nodes,
|
|
182
191
|
field_def.type,
|
|
183
192
|
parent_type,
|
|
184
193
|
path,
|
|
@@ -192,13 +201,6 @@ class StrawberryGraphQLCoreExecutionContext(GraphQLExecutionContext):
|
|
|
192
201
|
self.operation_extensions,
|
|
193
202
|
)
|
|
194
203
|
|
|
195
|
-
return super().build_resolve_info(
|
|
196
|
-
field_def,
|
|
197
|
-
field_group,
|
|
198
|
-
parent_type,
|
|
199
|
-
path,
|
|
200
|
-
)
|
|
201
|
-
|
|
202
204
|
|
|
203
205
|
class Schema(BaseSchema):
|
|
204
206
|
def __init__(
|
|
@@ -206,16 +208,16 @@ class Schema(BaseSchema):
|
|
|
206
208
|
# TODO: can we make sure we only allow to pass
|
|
207
209
|
# something that has been decorated?
|
|
208
210
|
query: type,
|
|
209
|
-
mutation:
|
|
210
|
-
subscription:
|
|
211
|
+
mutation: type | None = None,
|
|
212
|
+
subscription: type | None = None,
|
|
211
213
|
directives: Iterable[StrawberryDirective] = (),
|
|
212
|
-
types: Iterable[
|
|
213
|
-
extensions: Iterable[
|
|
214
|
-
execution_context_class:
|
|
215
|
-
config:
|
|
216
|
-
scalar_overrides:
|
|
217
|
-
Mapping[object,
|
|
218
|
-
|
|
214
|
+
types: Iterable[type | StrawberryType] = (),
|
|
215
|
+
extensions: Iterable[type[SchemaExtension] | SchemaExtension] = (),
|
|
216
|
+
execution_context_class: type[GraphQLExecutionContext] | None = None,
|
|
217
|
+
config: StrawberryConfig | None = None,
|
|
218
|
+
scalar_overrides: (
|
|
219
|
+
Mapping[object, type | ScalarWrapper | ScalarDefinition] | None
|
|
220
|
+
) = None,
|
|
219
221
|
schema_directives: Iterable[object] = (),
|
|
220
222
|
) -> None:
|
|
221
223
|
"""Default Schema to be used in a Strawberry application.
|
|
@@ -321,11 +323,16 @@ class Schema(BaseSchema):
|
|
|
321
323
|
graphql_types.append(graphql_type)
|
|
322
324
|
|
|
323
325
|
try:
|
|
326
|
+
directives = specified_directives + tuple(graphql_directives) # type: ignore
|
|
327
|
+
|
|
328
|
+
if self.config.enable_experimental_incremental_execution:
|
|
329
|
+
directives = tuple(directives) + tuple(incremental_execution_directives)
|
|
330
|
+
|
|
324
331
|
self._schema = GraphQLSchema(
|
|
325
332
|
query=query_type,
|
|
326
333
|
mutation=mutation_type,
|
|
327
334
|
subscription=subscription_type if subscription else None,
|
|
328
|
-
directives=
|
|
335
|
+
directives=directives, # type: ignore
|
|
329
336
|
types=graphql_types,
|
|
330
337
|
extensions={
|
|
331
338
|
GraphQLCoreConverter.DEFINITION_BACKREF: self,
|
|
@@ -387,7 +394,7 @@ class Schema(BaseSchema):
|
|
|
387
394
|
)
|
|
388
395
|
|
|
389
396
|
def _get_custom_context_kwargs(
|
|
390
|
-
self, operation_extensions:
|
|
397
|
+
self, operation_extensions: dict[str, Any] | None = None
|
|
391
398
|
) -> dict[str, Any]:
|
|
392
399
|
if not IS_GQL_33:
|
|
393
400
|
return {}
|
|
@@ -406,13 +413,13 @@ class Schema(BaseSchema):
|
|
|
406
413
|
|
|
407
414
|
def _create_execution_context(
|
|
408
415
|
self,
|
|
409
|
-
query:
|
|
416
|
+
query: str | None,
|
|
410
417
|
allowed_operation_types: Iterable[OperationType],
|
|
411
|
-
variable_values:
|
|
412
|
-
context_value:
|
|
413
|
-
root_value:
|
|
414
|
-
operation_name:
|
|
415
|
-
operation_extensions:
|
|
418
|
+
variable_values: dict[str, Any] | None = None,
|
|
419
|
+
context_value: Any | None = None,
|
|
420
|
+
root_value: Any | None = None,
|
|
421
|
+
operation_name: str | None = None,
|
|
422
|
+
operation_extensions: dict[str, Any] | None = None,
|
|
416
423
|
) -> ExecutionContext:
|
|
417
424
|
return ExecutionContext(
|
|
418
425
|
query=query,
|
|
@@ -428,14 +435,13 @@ class Schema(BaseSchema):
|
|
|
428
435
|
@lru_cache
|
|
429
436
|
def get_type_by_name(
|
|
430
437
|
self, name: str
|
|
431
|
-
) ->
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
]:
|
|
438
|
+
) -> (
|
|
439
|
+
StrawberryObjectDefinition
|
|
440
|
+
| ScalarDefinition
|
|
441
|
+
| EnumDefinition
|
|
442
|
+
| StrawberryUnion
|
|
443
|
+
| None
|
|
444
|
+
):
|
|
439
445
|
# TODO: respect auto_camel_case
|
|
440
446
|
if name in self.schema_converter.type_map:
|
|
441
447
|
return self.schema_converter.type_map[name].definition
|
|
@@ -444,7 +450,7 @@ class Schema(BaseSchema):
|
|
|
444
450
|
|
|
445
451
|
def get_field_for_type(
|
|
446
452
|
self, field_name: str, type_name: str
|
|
447
|
-
) ->
|
|
453
|
+
) -> StrawberryField | None:
|
|
448
454
|
type_ = self.get_type_by_name(type_name)
|
|
449
455
|
|
|
450
456
|
if not type_:
|
|
@@ -462,7 +468,7 @@ class Schema(BaseSchema):
|
|
|
462
468
|
)
|
|
463
469
|
|
|
464
470
|
@lru_cache
|
|
465
|
-
def get_directive_by_name(self, graphql_name: str) ->
|
|
471
|
+
def get_directive_by_name(self, graphql_name: str) -> StrawberryDirective | None:
|
|
466
472
|
return next(
|
|
467
473
|
(
|
|
468
474
|
directive
|
|
@@ -479,7 +485,7 @@ class Schema(BaseSchema):
|
|
|
479
485
|
|
|
480
486
|
async def _parse_and_validate_async(
|
|
481
487
|
self, context: ExecutionContext, extensions_runner: SchemaExtensionsRunner
|
|
482
|
-
) ->
|
|
488
|
+
) -> PreExecutionError | None:
|
|
483
489
|
if not context.query:
|
|
484
490
|
raise MissingQueryError
|
|
485
491
|
|
|
@@ -489,12 +495,12 @@ class Schema(BaseSchema):
|
|
|
489
495
|
context.graphql_document = parse(context.query)
|
|
490
496
|
|
|
491
497
|
except GraphQLError as error:
|
|
492
|
-
context.
|
|
498
|
+
context.pre_execution_errors = [error]
|
|
493
499
|
return PreExecutionError(data=None, errors=[error])
|
|
494
500
|
|
|
495
501
|
except Exception as error: # noqa: BLE001
|
|
496
502
|
error = GraphQLError(str(error), original_error=error)
|
|
497
|
-
context.
|
|
503
|
+
context.pre_execution_errors = [error]
|
|
498
504
|
return PreExecutionError(data=None, errors=[error])
|
|
499
505
|
|
|
500
506
|
try:
|
|
@@ -507,10 +513,10 @@ class Schema(BaseSchema):
|
|
|
507
513
|
|
|
508
514
|
async with extensions_runner.validation():
|
|
509
515
|
_run_validation(context)
|
|
510
|
-
if context.
|
|
516
|
+
if context.pre_execution_errors:
|
|
511
517
|
return PreExecutionError(
|
|
512
518
|
data=None,
|
|
513
|
-
errors=context.
|
|
519
|
+
errors=context.pre_execution_errors,
|
|
514
520
|
)
|
|
515
521
|
|
|
516
522
|
return None
|
|
@@ -518,33 +524,37 @@ class Schema(BaseSchema):
|
|
|
518
524
|
async def _handle_execution_result(
|
|
519
525
|
self,
|
|
520
526
|
context: ExecutionContext,
|
|
521
|
-
result:
|
|
527
|
+
result: ResultType,
|
|
522
528
|
extensions_runner: SchemaExtensionsRunner,
|
|
523
529
|
*,
|
|
524
530
|
# TODO: can we remove this somehow, see comment in execute
|
|
525
531
|
skip_process_errors: bool = False,
|
|
526
532
|
) -> ExecutionResult:
|
|
533
|
+
# TODO: handle this, also, why do we have both GraphQLExecutionResult and ExecutionResult?
|
|
534
|
+
if isinstance(result, GraphQLIncrementalExecutionResults):
|
|
535
|
+
return result
|
|
536
|
+
|
|
527
537
|
# Set errors on the context so that it's easier
|
|
528
538
|
# to access in extensions
|
|
529
539
|
if result.errors:
|
|
530
|
-
context.
|
|
540
|
+
context.pre_execution_errors = result.errors
|
|
531
541
|
if not skip_process_errors:
|
|
532
542
|
self._process_errors(result.errors, context)
|
|
533
543
|
if isinstance(result, GraphQLExecutionResult):
|
|
534
544
|
result = ExecutionResult(data=result.data, errors=result.errors)
|
|
535
545
|
result.extensions = await extensions_runner.get_extensions_results(context)
|
|
536
|
-
context.result = result
|
|
546
|
+
context.result = result
|
|
537
547
|
return result
|
|
538
548
|
|
|
539
549
|
async def execute(
|
|
540
550
|
self,
|
|
541
|
-
query:
|
|
542
|
-
variable_values:
|
|
543
|
-
context_value:
|
|
544
|
-
root_value:
|
|
545
|
-
operation_name:
|
|
546
|
-
allowed_operation_types:
|
|
547
|
-
operation_extensions:
|
|
551
|
+
query: str | None,
|
|
552
|
+
variable_values: dict[str, Any] | None = None,
|
|
553
|
+
context_value: Any | None = None,
|
|
554
|
+
root_value: Any | None = None,
|
|
555
|
+
operation_name: str | None = None,
|
|
556
|
+
allowed_operation_types: Iterable[OperationType] | None = None,
|
|
557
|
+
operation_extensions: dict[str, Any] | None = None,
|
|
548
558
|
) -> ExecutionResult:
|
|
549
559
|
if allowed_operation_types is None:
|
|
550
560
|
allowed_operation_types = DEFAULT_ALLOWED_OPERATION_TYPES
|
|
@@ -566,6 +576,17 @@ class Schema(BaseSchema):
|
|
|
566
576
|
extensions_runner = self.create_extensions_runner(execution_context, extensions)
|
|
567
577
|
middleware_manager = self._get_middleware_manager(extensions)
|
|
568
578
|
|
|
579
|
+
execute_function = execute
|
|
580
|
+
|
|
581
|
+
if self.config.enable_experimental_incremental_execution:
|
|
582
|
+
execute_function = experimental_execute_incrementally
|
|
583
|
+
|
|
584
|
+
if execute_function is None:
|
|
585
|
+
raise RuntimeError(
|
|
586
|
+
"Incremental execution is enabled but experimental_execute_incrementally is not available, "
|
|
587
|
+
"please install graphql-core>=3.3.0"
|
|
588
|
+
)
|
|
589
|
+
|
|
569
590
|
custom_context_kwargs = self._get_custom_context_kwargs(operation_extensions)
|
|
570
591
|
|
|
571
592
|
try:
|
|
@@ -586,7 +607,7 @@ class Schema(BaseSchema):
|
|
|
586
607
|
async with extensions_runner.executing():
|
|
587
608
|
if not execution_context.result:
|
|
588
609
|
result = await await_maybe(
|
|
589
|
-
|
|
610
|
+
execute_function(
|
|
590
611
|
self._schema,
|
|
591
612
|
execution_context.graphql_document,
|
|
592
613
|
root_value=execution_context.root_value,
|
|
@@ -603,8 +624,10 @@ class Schema(BaseSchema):
|
|
|
603
624
|
result = execution_context.result
|
|
604
625
|
# Also set errors on the execution_context so that it's easier
|
|
605
626
|
# to access in extensions
|
|
606
|
-
|
|
607
|
-
|
|
627
|
+
|
|
628
|
+
# TODO: maybe here use the first result from incremental execution if it exists
|
|
629
|
+
if isinstance(result, GraphQLExecutionResult) and result.errors:
|
|
630
|
+
execution_context.pre_execution_errors = result.errors
|
|
608
631
|
|
|
609
632
|
# Run the `Schema.process_errors` function here before
|
|
610
633
|
# extensions have a chance to modify them (see the MaskErrors
|
|
@@ -631,13 +654,13 @@ class Schema(BaseSchema):
|
|
|
631
654
|
|
|
632
655
|
def execute_sync(
|
|
633
656
|
self,
|
|
634
|
-
query:
|
|
635
|
-
variable_values:
|
|
636
|
-
context_value:
|
|
637
|
-
root_value:
|
|
638
|
-
operation_name:
|
|
639
|
-
allowed_operation_types:
|
|
640
|
-
operation_extensions:
|
|
657
|
+
query: str | None,
|
|
658
|
+
variable_values: dict[str, Any] | None = None,
|
|
659
|
+
context_value: Any | None = None,
|
|
660
|
+
root_value: Any | None = None,
|
|
661
|
+
operation_name: str | None = None,
|
|
662
|
+
allowed_operation_types: Iterable[OperationType] | None = None,
|
|
663
|
+
operation_extensions: dict[str, Any] | None = None,
|
|
641
664
|
) -> ExecutionResult:
|
|
642
665
|
if allowed_operation_types is None:
|
|
643
666
|
allowed_operation_types = DEFAULT_ALLOWED_OPERATION_TYPES
|
|
@@ -659,6 +682,16 @@ class Schema(BaseSchema):
|
|
|
659
682
|
extensions_runner = self.create_extensions_runner(execution_context, extensions)
|
|
660
683
|
middleware_manager = self._get_middleware_manager(extensions)
|
|
661
684
|
|
|
685
|
+
execute_function = execute
|
|
686
|
+
|
|
687
|
+
if self.config.enable_experimental_incremental_execution:
|
|
688
|
+
execute_function = experimental_execute_incrementally
|
|
689
|
+
|
|
690
|
+
if execute_function is None:
|
|
691
|
+
raise RuntimeError(
|
|
692
|
+
"Incremental execution is enabled but experimental_execute_incrementally is not available, "
|
|
693
|
+
"please install graphql-core>=3.3.0"
|
|
694
|
+
)
|
|
662
695
|
custom_context_kwargs = self._get_custom_context_kwargs(operation_extensions)
|
|
663
696
|
|
|
664
697
|
try:
|
|
@@ -677,7 +710,7 @@ class Schema(BaseSchema):
|
|
|
677
710
|
)
|
|
678
711
|
|
|
679
712
|
except GraphQLError as error:
|
|
680
|
-
execution_context.
|
|
713
|
+
execution_context.pre_execution_errors = [error]
|
|
681
714
|
self._process_errors([error], execution_context)
|
|
682
715
|
return ExecutionResult(
|
|
683
716
|
data=None,
|
|
@@ -697,19 +730,19 @@ class Schema(BaseSchema):
|
|
|
697
730
|
|
|
698
731
|
with extensions_runner.validation():
|
|
699
732
|
_run_validation(execution_context)
|
|
700
|
-
if execution_context.
|
|
733
|
+
if execution_context.pre_execution_errors:
|
|
701
734
|
self._process_errors(
|
|
702
|
-
execution_context.
|
|
735
|
+
execution_context.pre_execution_errors, execution_context
|
|
703
736
|
)
|
|
704
737
|
return ExecutionResult(
|
|
705
738
|
data=None,
|
|
706
|
-
errors=execution_context.
|
|
739
|
+
errors=execution_context.pre_execution_errors,
|
|
707
740
|
extensions=extensions_runner.get_extensions_results_sync(),
|
|
708
741
|
)
|
|
709
742
|
|
|
710
743
|
with extensions_runner.executing():
|
|
711
744
|
if not execution_context.result:
|
|
712
|
-
result =
|
|
745
|
+
result = execute_function(
|
|
713
746
|
self._schema,
|
|
714
747
|
execution_context.graphql_document,
|
|
715
748
|
root_value=execution_context.root_value,
|
|
@@ -733,7 +766,7 @@ class Schema(BaseSchema):
|
|
|
733
766
|
# Also set errors on the context so that it's easier
|
|
734
767
|
# to access in extensions
|
|
735
768
|
if result.errors:
|
|
736
|
-
execution_context.
|
|
769
|
+
execution_context.pre_execution_errors = result.errors
|
|
737
770
|
|
|
738
771
|
# Run the `Schema.process_errors` function here before
|
|
739
772
|
# extensions have a chance to modify them (see the MaskErrors
|
|
@@ -748,7 +781,7 @@ class Schema(BaseSchema):
|
|
|
748
781
|
raise
|
|
749
782
|
except Exception as exc: # noqa: BLE001
|
|
750
783
|
errors = [_coerce_error(exc)]
|
|
751
|
-
execution_context.
|
|
784
|
+
execution_context.pre_execution_errors = errors
|
|
752
785
|
self._process_errors(errors, execution_context)
|
|
753
786
|
return ExecutionResult(
|
|
754
787
|
data=None,
|
|
@@ -767,7 +800,7 @@ class Schema(BaseSchema):
|
|
|
767
800
|
extensions_runner: SchemaExtensionsRunner,
|
|
768
801
|
middleware_manager: MiddlewareManager,
|
|
769
802
|
execution_context_class: type[GraphQLExecutionContext] | None = None,
|
|
770
|
-
operation_extensions:
|
|
803
|
+
operation_extensions: dict[str, Any] | None = None,
|
|
771
804
|
) -> AsyncGenerator[ExecutionResult, None]:
|
|
772
805
|
async with extensions_runner.operation():
|
|
773
806
|
if initial_error := await self._parse_and_validate_async(
|
|
@@ -846,12 +879,12 @@ class Schema(BaseSchema):
|
|
|
846
879
|
|
|
847
880
|
async def subscribe(
|
|
848
881
|
self,
|
|
849
|
-
query:
|
|
850
|
-
variable_values:
|
|
851
|
-
context_value:
|
|
852
|
-
root_value:
|
|
853
|
-
operation_name:
|
|
854
|
-
operation_extensions:
|
|
882
|
+
query: str | None,
|
|
883
|
+
variable_values: dict[str, Any] | None = None,
|
|
884
|
+
context_value: Any | None = None,
|
|
885
|
+
root_value: Any | None = None,
|
|
886
|
+
operation_name: str | None = None,
|
|
887
|
+
operation_extensions: dict[str, Any] | None = None,
|
|
855
888
|
) -> SubscriptionResult:
|
|
856
889
|
execution_context = self._create_execution_context(
|
|
857
890
|
query=query,
|