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.

Files changed (161) hide show
  1. strawberry/__init__.py +2 -0
  2. strawberry/aiohttp/test/client.py +8 -15
  3. strawberry/aiohttp/views.py +15 -64
  4. strawberry/annotation.py +70 -25
  5. strawberry/asgi/__init__.py +22 -56
  6. strawberry/asgi/test/client.py +6 -6
  7. strawberry/chalice/views.py +13 -79
  8. strawberry/channels/handlers/base.py +7 -8
  9. strawberry/channels/handlers/http_handler.py +50 -32
  10. strawberry/channels/handlers/ws_handler.py +12 -14
  11. strawberry/channels/router.py +3 -4
  12. strawberry/channels/testing.py +7 -9
  13. strawberry/cli/__init__.py +7 -6
  14. strawberry/cli/commands/codegen.py +7 -7
  15. strawberry/cli/commands/dev.py +72 -0
  16. strawberry/cli/commands/schema_codegen.py +1 -2
  17. strawberry/cli/commands/server.py +3 -44
  18. strawberry/cli/commands/upgrade/__init__.py +3 -3
  19. strawberry/cli/commands/upgrade/_run_codemod.py +2 -2
  20. strawberry/cli/constants.py +1 -2
  21. strawberry/cli/{debug_server.py → dev_server.py} +3 -7
  22. strawberry/codegen/plugins/print_operation.py +2 -2
  23. strawberry/codegen/plugins/python.py +2 -2
  24. strawberry/codegen/query_codegen.py +20 -30
  25. strawberry/codegen/types.py +32 -32
  26. strawberry/codemods/__init__.py +9 -0
  27. strawberry/codemods/annotated_unions.py +2 -2
  28. strawberry/codemods/maybe_optional.py +118 -0
  29. strawberry/dataloader.py +28 -24
  30. strawberry/directive.py +6 -7
  31. strawberry/django/test/client.py +3 -3
  32. strawberry/django/views.py +21 -91
  33. strawberry/exceptions/__init__.py +4 -4
  34. strawberry/exceptions/conflicting_arguments.py +2 -2
  35. strawberry/exceptions/duplicated_type_name.py +4 -4
  36. strawberry/exceptions/exception.py +3 -3
  37. strawberry/exceptions/handler.py +8 -7
  38. strawberry/exceptions/invalid_argument_type.py +2 -2
  39. strawberry/exceptions/invalid_superclass_interface.py +2 -2
  40. strawberry/exceptions/invalid_union_type.py +4 -4
  41. strawberry/exceptions/missing_arguments_annotations.py +2 -2
  42. strawberry/exceptions/missing_dependencies.py +2 -4
  43. strawberry/exceptions/missing_field_annotation.py +2 -2
  44. strawberry/exceptions/missing_return_annotation.py +2 -2
  45. strawberry/exceptions/object_is_not_a_class.py +2 -2
  46. strawberry/exceptions/object_is_not_an_enum.py +2 -2
  47. strawberry/exceptions/permission_fail_silently_requires_optional.py +2 -2
  48. strawberry/exceptions/private_strawberry_field.py +2 -2
  49. strawberry/exceptions/scalar_already_registered.py +2 -2
  50. strawberry/exceptions/syntax.py +3 -3
  51. strawberry/exceptions/unresolved_field_type.py +2 -2
  52. strawberry/exceptions/utils/source_finder.py +25 -25
  53. strawberry/experimental/pydantic/_compat.py +8 -7
  54. strawberry/experimental/pydantic/conversion.py +2 -2
  55. strawberry/experimental/pydantic/conversion_types.py +2 -2
  56. strawberry/experimental/pydantic/error_type.py +10 -12
  57. strawberry/experimental/pydantic/fields.py +9 -15
  58. strawberry/experimental/pydantic/object_type.py +17 -25
  59. strawberry/experimental/pydantic/utils.py +1 -2
  60. strawberry/ext/mypy_plugin.py +12 -14
  61. strawberry/extensions/base_extension.py +2 -1
  62. strawberry/extensions/context.py +13 -18
  63. strawberry/extensions/directives.py +9 -3
  64. strawberry/extensions/field_extension.py +4 -4
  65. strawberry/extensions/mask_errors.py +24 -13
  66. strawberry/extensions/max_aliases.py +1 -3
  67. strawberry/extensions/parser_cache.py +1 -2
  68. strawberry/extensions/query_depth_limiter.py +18 -14
  69. strawberry/extensions/runner.py +2 -2
  70. strawberry/extensions/tracing/apollo.py +3 -3
  71. strawberry/extensions/tracing/datadog.py +3 -3
  72. strawberry/extensions/tracing/opentelemetry.py +6 -8
  73. strawberry/extensions/tracing/utils.py +3 -1
  74. strawberry/extensions/utils.py +2 -2
  75. strawberry/extensions/validation_cache.py +2 -3
  76. strawberry/fastapi/context.py +6 -6
  77. strawberry/fastapi/router.py +43 -42
  78. strawberry/federation/argument.py +4 -5
  79. strawberry/federation/enum.py +18 -21
  80. strawberry/federation/field.py +94 -97
  81. strawberry/federation/object_type.py +56 -58
  82. strawberry/federation/scalar.py +27 -35
  83. strawberry/federation/schema.py +15 -16
  84. strawberry/federation/schema_directive.py +7 -6
  85. strawberry/federation/schema_directives.py +11 -11
  86. strawberry/federation/union.py +4 -4
  87. strawberry/flask/views.py +16 -85
  88. strawberry/http/__init__.py +30 -20
  89. strawberry/http/async_base_view.py +208 -89
  90. strawberry/http/base.py +28 -11
  91. strawberry/http/exceptions.py +5 -7
  92. strawberry/http/ides.py +2 -3
  93. strawberry/http/sync_base_view.py +115 -69
  94. strawberry/http/types.py +3 -3
  95. strawberry/litestar/controller.py +43 -77
  96. strawberry/permission.py +4 -6
  97. strawberry/printer/ast_from_value.py +3 -5
  98. strawberry/printer/printer.py +18 -15
  99. strawberry/quart/views.py +16 -48
  100. strawberry/relay/exceptions.py +4 -4
  101. strawberry/relay/fields.py +33 -32
  102. strawberry/relay/types.py +32 -35
  103. strawberry/relay/utils.py +11 -23
  104. strawberry/resolvers.py +2 -1
  105. strawberry/sanic/context.py +1 -0
  106. strawberry/sanic/utils.py +3 -3
  107. strawberry/sanic/views.py +15 -54
  108. strawberry/scalars.py +2 -2
  109. strawberry/schema/_graphql_core.py +55 -0
  110. strawberry/schema/base.py +32 -33
  111. strawberry/schema/compat.py +9 -9
  112. strawberry/schema/config.py +10 -1
  113. strawberry/schema/exceptions.py +1 -3
  114. strawberry/schema/name_converter.py +9 -8
  115. strawberry/schema/schema.py +133 -100
  116. strawberry/schema/schema_converter.py +96 -58
  117. strawberry/schema/types/base_scalars.py +1 -1
  118. strawberry/schema/types/concrete_type.py +5 -5
  119. strawberry/schema/validation_rules/maybe_null.py +136 -0
  120. strawberry/schema_codegen/__init__.py +3 -3
  121. strawberry/schema_directive.py +7 -6
  122. strawberry/static/graphiql.html +5 -5
  123. strawberry/streamable.py +35 -0
  124. strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +5 -16
  125. strawberry/subscriptions/protocols/graphql_transport_ws/types.py +20 -20
  126. strawberry/subscriptions/protocols/graphql_ws/handlers.py +5 -12
  127. strawberry/subscriptions/protocols/graphql_ws/types.py +14 -14
  128. strawberry/test/client.py +18 -18
  129. strawberry/tools/create_type.py +2 -3
  130. strawberry/types/arguments.py +41 -28
  131. strawberry/types/auto.py +3 -4
  132. strawberry/types/base.py +25 -27
  133. strawberry/types/enum.py +22 -25
  134. strawberry/types/execution.py +21 -16
  135. strawberry/types/field.py +109 -130
  136. strawberry/types/fields/resolver.py +19 -21
  137. strawberry/types/info.py +5 -11
  138. strawberry/types/lazy_type.py +2 -3
  139. strawberry/types/maybe.py +12 -3
  140. strawberry/types/mutation.py +115 -118
  141. strawberry/types/nodes.py +2 -2
  142. strawberry/types/object_type.py +43 -63
  143. strawberry/types/scalar.py +37 -43
  144. strawberry/types/union.py +12 -14
  145. strawberry/utils/aio.py +12 -9
  146. strawberry/utils/await_maybe.py +3 -3
  147. strawberry/utils/deprecations.py +2 -2
  148. strawberry/utils/importer.py +1 -2
  149. strawberry/utils/inspect.py +4 -6
  150. strawberry/utils/logging.py +2 -2
  151. strawberry/utils/operation.py +4 -4
  152. strawberry/utils/typing.py +18 -83
  153. {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/METADATA +14 -8
  154. strawberry_graphql-0.284.3.dist-info/RECORD +243 -0
  155. {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/WHEEL +1 -1
  156. strawberry/utils/dataclasses.py +0 -37
  157. strawberry/utils/debug.py +0 -46
  158. strawberry/utils/graphql_lexer.py +0 -35
  159. strawberry_graphql-0.275.7.dist-info/RECORD +0 -241
  160. {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/entry_points.txt +0 -0
  161. {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info/licenses}/LICENSE +0 -0
@@ -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 typing_extensions import TypeAlias
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
- Union[PreExecutionError, ExecutionResult], None
98
+ PreExecutionError | ExecutionResult, None
95
99
  ]
96
100
 
97
- OriginSubscriptionResult = Union[
98
- OriginalExecutionResult,
99
- AsyncIterator[OriginalExecutionResult],
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], Optional[ExecutionContext]], None]"
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 len(execution_context.validation_rules) > 0 and execution_context.errors is None:
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.errors = validate_document(
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: Union[GraphQLError, Exception]) -> GraphQLError:
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
- def build_resolve_info(
172
- self,
173
- field_def: GraphQLField,
174
- field_group: FieldGroup,
175
- parent_type: GraphQLObjectType,
176
- path: Path,
177
- ) -> GraphQLResolveInfo:
178
- if IS_GQL_33:
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
- field_group.fields[0].node.name.value,
181
- field_group.to_nodes(),
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: Optional[type] = None,
210
- subscription: Optional[type] = None,
211
+ mutation: type | None = None,
212
+ subscription: type | None = None,
211
213
  directives: Iterable[StrawberryDirective] = (),
212
- types: Iterable[Union[type, StrawberryType]] = (),
213
- extensions: Iterable[Union[type[SchemaExtension], SchemaExtension]] = (),
214
- execution_context_class: Optional[type[GraphQLExecutionContext]] = None,
215
- config: Optional[StrawberryConfig] = None,
216
- scalar_overrides: Optional[
217
- Mapping[object, Union[type, ScalarWrapper, ScalarDefinition]],
218
- ] = None,
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=specified_directives + tuple(graphql_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: Optional[dict[str, Any]] = None
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: Optional[str],
416
+ query: str | None,
410
417
  allowed_operation_types: Iterable[OperationType],
411
- variable_values: Optional[dict[str, Any]] = None,
412
- context_value: Optional[Any] = None,
413
- root_value: Optional[Any] = None,
414
- operation_name: Optional[str] = None,
415
- operation_extensions: Optional[dict[str, Any]] = None,
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
- ) -> Optional[
432
- Union[
433
- StrawberryObjectDefinition,
434
- ScalarDefinition,
435
- EnumDefinition,
436
- StrawberryUnion,
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
- ) -> Optional[StrawberryField]:
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) -> Optional[StrawberryDirective]:
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
- ) -> Optional[PreExecutionError]:
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.errors = [error]
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.errors = [error]
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.errors:
516
+ if context.pre_execution_errors:
511
517
  return PreExecutionError(
512
518
  data=None,
513
- errors=context.errors,
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: Union[GraphQLExecutionResult, ExecutionResult],
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.errors = result.errors
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 # type: ignore # mypy failed to deduce correct type.
546
+ context.result = result
537
547
  return result
538
548
 
539
549
  async def execute(
540
550
  self,
541
- query: Optional[str],
542
- variable_values: Optional[dict[str, Any]] = None,
543
- context_value: Optional[Any] = None,
544
- root_value: Optional[Any] = None,
545
- operation_name: Optional[str] = None,
546
- allowed_operation_types: Optional[Iterable[OperationType]] = None,
547
- operation_extensions: Optional[dict[str, Any]] = None,
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
- execute(
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
- if result.errors:
607
- execution_context.errors = result.errors
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: Optional[str],
635
- variable_values: Optional[dict[str, Any]] = None,
636
- context_value: Optional[Any] = None,
637
- root_value: Optional[Any] = None,
638
- operation_name: Optional[str] = None,
639
- allowed_operation_types: Optional[Iterable[OperationType]] = None,
640
- operation_extensions: Optional[dict[str, Any]] = None,
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.errors = [error]
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.errors:
733
+ if execution_context.pre_execution_errors:
701
734
  self._process_errors(
702
- execution_context.errors, execution_context
735
+ execution_context.pre_execution_errors, execution_context
703
736
  )
704
737
  return ExecutionResult(
705
738
  data=None,
706
- errors=execution_context.errors,
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 = execute(
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.errors = result.errors
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.errors = errors
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: Optional[dict[str, Any]] = None,
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: Optional[str],
850
- variable_values: Optional[dict[str, Any]] = None,
851
- context_value: Optional[Any] = None,
852
- root_value: Optional[Any] = None,
853
- operation_name: Optional[str] = None,
854
- operation_extensions: Optional[dict[str, Any]] = None,
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,