strawberry-graphql 0.268.1__py3-none-any.whl → 0.269.0.dev1747164009__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.
@@ -32,6 +32,7 @@ class GraphQLRequestData:
32
32
  query: Optional[str]
33
33
  variables: Optional[dict[str, Any]]
34
34
  operation_name: Optional[str]
35
+ extensions: Optional[dict[str, Any]]
35
36
  protocol: Literal["http", "multipart-subscription"] = "http"
36
37
 
37
38
 
@@ -204,6 +204,7 @@ class AsyncBaseHTTPView(
204
204
  context_value=context,
205
205
  root_value=root_value,
206
206
  operation_name=request_data.operation_name,
207
+ operation_extensions=request_data.extensions,
207
208
  )
208
209
 
209
210
  return await self.schema.execute(
@@ -213,6 +214,7 @@ class AsyncBaseHTTPView(
213
214
  context_value=context,
214
215
  operation_name=request_data.operation_name,
215
216
  allowed_operation_types=allowed_operation_types,
217
+ operation_extensions=request_data.extensions,
216
218
  )
217
219
 
218
220
  async def parse_multipart(self, request: AsyncHTTPRequestAdapter) -> dict[str, str]:
@@ -472,6 +474,7 @@ class AsyncBaseHTTPView(
472
474
  query=data.get("query"),
473
475
  variables=data.get("variables"),
474
476
  operation_name=data.get("operationName"),
477
+ extensions=data.get("extensions"),
475
478
  protocol=protocol,
476
479
  )
477
480
 
strawberry/http/base.py CHANGED
@@ -59,6 +59,12 @@ class BaseView(Generic[Request]):
59
59
  if variables:
60
60
  params["variables"] = self.parse_json(variables)
61
61
 
62
+ if "extensions" in params:
63
+ extensions = params["extensions"]
64
+
65
+ if extensions:
66
+ params["extensions"] = self.parse_json(extensions)
67
+
62
68
  return params
63
69
 
64
70
  @property
@@ -122,6 +122,7 @@ class SyncBaseHTTPView(
122
122
  context_value=context,
123
123
  operation_name=request_data.operation_name,
124
124
  allowed_operation_types=allowed_operation_types,
125
+ operation_extensions=request_data.extensions,
125
126
  )
126
127
 
127
128
  def parse_multipart(self, request: SyncHTTPRequestAdapter) -> dict[str, str]:
@@ -154,6 +155,7 @@ class SyncBaseHTTPView(
154
155
  query=data.get("query"),
155
156
  variables=data.get("variables"),
156
157
  operation_name=data.get("operationName"),
158
+ extensions=data.get("extensions"),
157
159
  )
158
160
 
159
161
  def _handle_errors(
strawberry/schema/base.py CHANGED
@@ -47,6 +47,7 @@ class BaseSchema(Protocol):
47
47
  root_value: Optional[Any] = None,
48
48
  operation_name: Optional[str] = None,
49
49
  allowed_operation_types: Optional[Iterable[OperationType]] = None,
50
+ operation_extensions: Optional[dict[str, Any]] = None,
50
51
  ) -> ExecutionResult:
51
52
  raise NotImplementedError
52
53
 
@@ -59,6 +60,7 @@ class BaseSchema(Protocol):
59
60
  root_value: Optional[Any] = None,
60
61
  operation_name: Optional[str] = None,
61
62
  allowed_operation_types: Optional[Iterable[OperationType]] = None,
63
+ operation_extensions: Optional[dict[str, Any]] = None,
62
64
  ) -> ExecutionResult:
63
65
  raise NotImplementedError
64
66
 
@@ -70,6 +72,7 @@ class BaseSchema(Protocol):
70
72
  context_value: Optional[Any] = None,
71
73
  root_value: Optional[Any] = None,
72
74
  operation_name: Optional[str] = None,
75
+ operation_extensions: Optional[dict[str, Any]] = None,
73
76
  ) -> SubscriptionResult:
74
77
  raise NotImplementedError
75
78
 
@@ -9,27 +9,33 @@ from typing import (
9
9
  TYPE_CHECKING,
10
10
  Any,
11
11
  Callable,
12
+ NamedTuple,
12
13
  Optional,
13
14
  Union,
14
15
  cast,
15
16
  )
16
17
 
18
+ from graphql import ExecutionContext as GraphQLExecutionContext
17
19
  from graphql import ExecutionResult as GraphQLExecutionResult
18
20
  from graphql import (
19
21
  ExecutionResult as OriginalExecutionResult,
20
22
  )
21
23
  from graphql import (
24
+ FieldNode,
25
+ FragmentDefinitionNode,
22
26
  GraphQLBoolean,
23
27
  GraphQLError,
24
28
  GraphQLField,
25
29
  GraphQLNamedType,
26
30
  GraphQLNonNull,
31
+ GraphQLObjectType,
32
+ GraphQLOutputType,
27
33
  GraphQLSchema,
34
+ OperationDefinitionNode,
28
35
  get_introspection_query,
29
36
  parse,
30
37
  validate_schema,
31
38
  )
32
- from graphql.execution import ExecutionContext as GraphQLExecutionContext
33
39
  from graphql.execution import execute, subscribe
34
40
  from graphql.execution.middleware import MiddlewareManager
35
41
  from graphql.type.directives import specified_directives
@@ -58,7 +64,7 @@ from strawberry.types.execution import (
58
64
  PreExecutionError,
59
65
  )
60
66
  from strawberry.types.graphql import OperationType
61
- from strawberry.utils import IS_GQL_32
67
+ from strawberry.utils import IS_GQL_32, IS_GQL_33
62
68
  from strawberry.utils.aio import aclosing
63
69
  from strawberry.utils.await_maybe import await_maybe
64
70
 
@@ -71,8 +77,10 @@ if TYPE_CHECKING:
71
77
  from collections.abc import Iterable, Mapping
72
78
  from typing_extensions import TypeAlias
73
79
 
74
- from graphql import ExecutionContext as GraphQLExecutionContext
80
+ from graphql.execution.collect_fields import FieldGroup # type: ignore
75
81
  from graphql.language import DocumentNode
82
+ from graphql.pyutils import Path
83
+ from graphql.type import GraphQLResolveInfo
76
84
  from graphql.validation import ASTValidationRule
77
85
 
78
86
  from strawberry.directive import StrawberryDirective
@@ -136,6 +144,62 @@ def _coerce_error(error: Union[GraphQLError, Exception]) -> GraphQLError:
136
144
  return GraphQLError(str(error), original_error=error)
137
145
 
138
146
 
147
+ class _OperationContextAwareGraphQLResolveInfo(NamedTuple): # pyright: ignore
148
+ field_name: str
149
+ field_nodes: list[FieldNode]
150
+ return_type: GraphQLOutputType
151
+ parent_type: GraphQLObjectType
152
+ path: Path
153
+ schema: GraphQLSchema
154
+ fragments: dict[str, FragmentDefinitionNode]
155
+ root_value: Any
156
+ operation: OperationDefinitionNode
157
+ variable_values: dict[str, Any]
158
+ context: Any
159
+ is_awaitable: Callable[[Any], bool]
160
+ operation_extensions: dict[str, Any]
161
+
162
+
163
+ class StrawberryGraphQLCoreExecutionContext(GraphQLExecutionContext):
164
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
165
+ operation_extensions = kwargs.pop("operation_extensions", None)
166
+
167
+ super().__init__(*args, **kwargs)
168
+
169
+ self.operation_extensions = operation_extensions
170
+
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
+ return _OperationContextAwareGraphQLResolveInfo( # type: ignore
180
+ field_group.fields[0].node.name.value,
181
+ field_group.to_nodes(),
182
+ field_def.type,
183
+ parent_type,
184
+ path,
185
+ self.schema,
186
+ self.fragments,
187
+ self.root_value,
188
+ self.operation,
189
+ self.variable_values,
190
+ self.context_value,
191
+ self.is_awaitable,
192
+ self.operation_extensions,
193
+ )
194
+
195
+ return super().build_resolve_info(
196
+ field_def,
197
+ field_group,
198
+ parent_type,
199
+ path,
200
+ )
201
+
202
+
139
203
  class Schema(BaseSchema):
140
204
  def __init__(
141
205
  self,
@@ -195,7 +259,9 @@ class Schema(BaseSchema):
195
259
 
196
260
  self.extensions = extensions
197
261
  self._cached_middleware_manager: MiddlewareManager | None = None
198
- self.execution_context_class = execution_context_class
262
+ self.execution_context_class = (
263
+ execution_context_class or StrawberryGraphQLCoreExecutionContext
264
+ )
199
265
  self.config = config or StrawberryConfig()
200
266
 
201
267
  self.schema_converter = GraphQLCoreConverter(
@@ -320,6 +386,14 @@ class Schema(BaseSchema):
320
386
  extensions=extensions,
321
387
  )
322
388
 
389
+ def _get_custom_context_kwargs(
390
+ self, operation_extensions: Optional[dict[str, Any]] = None
391
+ ) -> dict[str, Any]:
392
+ if not IS_GQL_33:
393
+ return {}
394
+
395
+ return {"operation_extensions": operation_extensions}
396
+
323
397
  def _get_middleware_manager(
324
398
  self, extensions: list[SchemaExtension]
325
399
  ) -> MiddlewareManager:
@@ -463,6 +537,7 @@ class Schema(BaseSchema):
463
537
  root_value: Optional[Any] = None,
464
538
  operation_name: Optional[str] = None,
465
539
  allowed_operation_types: Optional[Iterable[OperationType]] = None,
540
+ operation_extensions: Optional[dict[str, Any]] = None,
466
541
  ) -> ExecutionResult:
467
542
  if allowed_operation_types is None:
468
543
  allowed_operation_types = DEFAULT_ALLOWED_OPERATION_TYPES
@@ -483,6 +558,8 @@ class Schema(BaseSchema):
483
558
  extensions_runner = self.create_extensions_runner(execution_context, extensions)
484
559
  middleware_manager = self._get_middleware_manager(extensions)
485
560
 
561
+ custom_context_kwargs = self._get_custom_context_kwargs(operation_extensions)
562
+
486
563
  try:
487
564
  async with extensions_runner.operation():
488
565
  # Note: In graphql-core the schema would be validated here but in
@@ -510,6 +587,7 @@ class Schema(BaseSchema):
510
587
  operation_name=execution_context.operation_name,
511
588
  context_value=execution_context.context,
512
589
  execution_context_class=self.execution_context_class,
590
+ **custom_context_kwargs,
513
591
  )
514
592
  )
515
593
  execution_context.result = result
@@ -547,6 +625,7 @@ class Schema(BaseSchema):
547
625
  root_value: Optional[Any] = None,
548
626
  operation_name: Optional[str] = None,
549
627
  allowed_operation_types: Optional[Iterable[OperationType]] = None,
628
+ operation_extensions: Optional[dict[str, Any]] = None,
550
629
  ) -> ExecutionResult:
551
630
  if allowed_operation_types is None:
552
631
  allowed_operation_types = DEFAULT_ALLOWED_OPERATION_TYPES
@@ -567,6 +646,8 @@ class Schema(BaseSchema):
567
646
  extensions_runner = self.create_extensions_runner(execution_context, extensions)
568
647
  middleware_manager = self._get_middleware_manager(extensions)
569
648
 
649
+ custom_context_kwargs = self._get_custom_context_kwargs(operation_extensions)
650
+
570
651
  try:
571
652
  with extensions_runner.operation():
572
653
  # Note: In graphql-core the schema would be validated here but in
@@ -617,6 +698,7 @@ class Schema(BaseSchema):
617
698
  operation_name=execution_context.operation_name,
618
699
  context_value=execution_context.context,
619
700
  execution_context_class=self.execution_context_class,
701
+ **custom_context_kwargs,
620
702
  )
621
703
 
622
704
  if isawaitable(result):
@@ -661,6 +743,7 @@ class Schema(BaseSchema):
661
743
  extensions_runner: SchemaExtensionsRunner,
662
744
  middleware_manager: MiddlewareManager,
663
745
  execution_context_class: type[GraphQLExecutionContext] | None = None,
746
+ operation_extensions: Optional[dict[str, Any]] = None,
664
747
  ) -> AsyncGenerator[ExecutionResult, None]:
665
748
  async with extensions_runner.operation():
666
749
  if initial_error := await self._parse_and_validate_async(
@@ -679,6 +762,7 @@ class Schema(BaseSchema):
679
762
  gql_33_kwargs = {
680
763
  "middleware": middleware_manager,
681
764
  "execution_context_class": execution_context_class,
765
+ "operation_extensions": operation_extensions,
682
766
  }
683
767
  try:
684
768
  # Might not be awaitable for pre-execution errors.
@@ -743,6 +827,7 @@ class Schema(BaseSchema):
743
827
  context_value: Optional[Any] = None,
744
828
  root_value: Optional[Any] = None,
745
829
  operation_name: Optional[str] = None,
830
+ operation_extensions: Optional[dict[str, Any]] = None,
746
831
  ) -> SubscriptionResult:
747
832
  execution_context = self._create_execution_context(
748
833
  query=query,
@@ -764,6 +849,7 @@ class Schema(BaseSchema):
764
849
  ),
765
850
  middleware_manager=self._get_middleware_manager(extensions),
766
851
  execution_context_class=self.execution_context_class,
852
+ operation_extensions=operation_extensions,
767
853
  )
768
854
 
769
855
  def _resolve_node_ids(self) -> None:
strawberry/types/info.py CHANGED
@@ -113,6 +113,11 @@ class Info(Generic[ContextType, RootValueType]):
113
113
  """The context passed to the query execution."""
114
114
  return self._raw_info.context
115
115
 
116
+ @property
117
+ def input_extensions(self) -> dict[str, Any]:
118
+ """The input extensions passed to the query execution."""
119
+ return self._raw_info.operation_extensions # type: ignore
120
+
116
121
  @property
117
122
  def root_value(self) -> RootValueType:
118
123
  """The root value passed to the query execution."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: strawberry-graphql
3
- Version: 0.268.1
3
+ Version: 0.269.0.dev1747164009
4
4
  Summary: A library for creating GraphQL APIs
5
5
  License: MIT
6
6
  Keywords: graphql,api,rest,starlette,async
@@ -130,13 +130,13 @@ strawberry/file_uploads/scalars.py,sha256=NRDeB7j8aotqIkz9r62ISTf4DrxQxEZYUuHsX5
130
130
  strawberry/file_uploads/utils.py,sha256=-c6TbqUI-Dkb96hWCrZabh6TL2OabBuQNkCarOqgDm4,1181
131
131
  strawberry/flask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
132
132
  strawberry/flask/views.py,sha256=MCvAsNgTZLU8RvTYKWfnLU2w7Wv1ZZpxW9W3TyTZuPY,6355
133
- strawberry/http/__init__.py,sha256=BV_JpUwNongW38UzFstM72hDXNUjSxdJm_M96pDFU1c,1122
134
- strawberry/http/async_base_view.py,sha256=9micSD_KpoB8oBHAPlcTpt44bVABDYScvyfHa3NP4rE,16352
135
- strawberry/http/base.py,sha256=Lz-u5SWg2uQp3l5GMKZDPQuJOR42LXHgjV1PZHwiapE,2373
133
+ strawberry/http/__init__.py,sha256=ytAirKk7K7D5knY21tpCGeZ-sCPgwMsijL5AxmOy-94,1163
134
+ strawberry/http/async_base_view.py,sha256=NnFYHy_3b6WtxRZoLCWDeOXDqEz2VxzG6jlKcIwrM4E,16519
135
+ strawberry/http/base.py,sha256=MiX0-RqOkhRvlfpmuvgTHp4tygbUmG8fnLc0uCrOllU,2550
136
136
  strawberry/http/exceptions.py,sha256=9E2dreS1crRoJVUEPuHyx23NcDELDHNzkAOa-rGv-8I,348
137
137
  strawberry/http/ides.py,sha256=WjU0nsMDgr3Bd1ebWkUEkO2d1hk0dI16mLqXyCHqklA,613
138
138
  strawberry/http/parse_content_type.py,sha256=CYHO8F9b9DP1gJ1xxPjc9L2GkBwsyC1O_GCEp1QOuG0,381
139
- strawberry/http/sync_base_view.py,sha256=iKcc9bDu7wQnOTfcCEW56I-Y35xdkb1P_sP3-y7RTh8,7180
139
+ strawberry/http/sync_base_view.py,sha256=x_RQ7XdzwPmMl1vCh3bmgVvShQp28azSEkVMCX2o6Mc,7285
140
140
  strawberry/http/temporal_response.py,sha256=HTt65g-YxqlPGxjqvH5bzGoU1b3CctVR-9cmCRo5dUo,196
141
141
  strawberry/http/types.py,sha256=H0wGOdCO-5tNKZM_6cAtNRwZAjoEXnAC5N0Q7b70AtU,398
142
142
  strawberry/http/typevars.py,sha256=Uu6NkKe3h7o29ZWwldq6sJy4ioSSeXODTCDRvY2hUpE,489
@@ -162,12 +162,12 @@ strawberry/sanic/utils.py,sha256=XjUVBFuBWfECBCZbx_YtrjQnFTUyIGTo7aISIeB22Gc,100
162
162
  strawberry/sanic/views.py,sha256=F5ZrKt-R3135evKLfhQuPd1isOexI0Lrzevm_6Te4Eg,7069
163
163
  strawberry/scalars.py,sha256=CGkG8CIfurXiYhidmW3qwy6M5BF_Mhih3wAEcWx_iBU,2278
164
164
  strawberry/schema/__init__.py,sha256=u1QCyDVQExUVDA20kyosKPz3TS5HMCN2NrXclhiFAL4,92
165
- strawberry/schema/base.py,sha256=q5UAw6do4Ele5Cf8dNAouiPjNmZoCBNFqh5Vl05caCI,3864
165
+ strawberry/schema/base.py,sha256=wqvEOQ_aVkfebk9SlG9zg1YXl3MlwxGZhxFRoIkAxu0,4053
166
166
  strawberry/schema/compat.py,sha256=xNpOEDfi-MODpplMGaKuKeQIVcr-tcAaKaU3TlBc1Zs,1873
167
167
  strawberry/schema/config.py,sha256=KeZ1Pc1gvYK0fOx9Aghx7m0Av8sWexycl3HJGFgHPvg,969
168
168
  strawberry/schema/exceptions.py,sha256=rqVNb_oYrKM0dHPgvAemqCG6Um282LPPu4zwQ5cZqs4,584
169
169
  strawberry/schema/name_converter.py,sha256=xFOXEgqldFkxXRkIQvsJN1dPkWbEUaIrTYNOMYSEVwQ,6945
170
- strawberry/schema/schema.py,sha256=rDfNclXSRHqn3NNGzPAovZoVeMh0VC5wVCCUprwZJV8,34215
170
+ strawberry/schema/schema.py,sha256=zRIv4mpVEFjFWv-MmfjO9v7OsuSFZ2xghr_ekIAuZI4,37113
171
171
  strawberry/schema/schema_converter.py,sha256=u12Og8eUX8SNMtJB6LYkj9zEpoQs-rDOXpN7tU8JG7k,39785
172
172
  strawberry/schema/types/__init__.py,sha256=oHO3COWhL3L1KLYCJNY1XFf5xt2GGtHiMC-UaYbFfnA,68
173
173
  strawberry/schema/types/base_scalars.py,sha256=JRUq0WjEkR9dFewstZnqnZKp0uOEipo4UXNF5dzRf4M,1971
@@ -205,7 +205,7 @@ strawberry/types/field.py,sha256=vxb7JvkHfRmDCYsjhDmVnO2lMbtSOteQm3jQUeSFu6g,216
205
205
  strawberry/types/fields/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
206
206
  strawberry/types/fields/resolver.py,sha256=b6lxfw6AMOUFWm7vs7a9KzNkpR8b_S110DoIosrrWDQ,14679
207
207
  strawberry/types/graphql.py,sha256=gXKzawwKiow7hvoJhq5ApNJOMUCnKmvTiHaKY5CK1Lw,867
208
- strawberry/types/info.py,sha256=bPP7XTQQScmskJcmVv36iqLAWpdGmF2nhYjI1pJ-csI,4709
208
+ strawberry/types/info.py,sha256=V3DQMd97tkWSdPIhp7HcelQ2h94-HSCI5zJ7cRO7i58,4907
209
209
  strawberry/types/lazy_type.py,sha256=dlP9VcMjZc9sdgriiQGzOZa0TToB6Ee7zpIP8h7TLC0,5079
210
210
  strawberry/types/maybe.py,sha256=Zdv4pAJwgUmaFNU8WKlwjk50qwgYEzT90WteURZBzAo,1174
211
211
  strawberry/types/mutation.py,sha256=cg-_O2WWnZ-GSwOIv0toSdxlGeY2lhBBxZ24AifJuSM,11978
@@ -229,8 +229,8 @@ strawberry/utils/logging.py,sha256=U1cseHGquN09YFhFmRkiphfASKCyK0HUZREImPgVb0c,7
229
229
  strawberry/utils/operation.py,sha256=s7ajvLg_q6v2mg47kEMQPjO_J-XluMKTCwo4d47mGvE,1195
230
230
  strawberry/utils/str_converters.py,sha256=-eH1Cl16IO_wrBlsGM-km4IY0IKsjhjnSNGRGOwQjVM,897
231
231
  strawberry/utils/typing.py,sha256=SDvX-Du-9HAV3-XXjqi7Q5f5qPDDFd_gASIITiwBQT4,14073
232
- strawberry_graphql-0.268.1.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
233
- strawberry_graphql-0.268.1.dist-info/METADATA,sha256=0KP8VbWiBIyL4DP__ItZildr2PoqR_WjXmRoTc_9PDE,7679
234
- strawberry_graphql-0.268.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
235
- strawberry_graphql-0.268.1.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
236
- strawberry_graphql-0.268.1.dist-info/RECORD,,
232
+ strawberry_graphql-0.269.0.dev1747164009.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
233
+ strawberry_graphql-0.269.0.dev1747164009.dist-info/METADATA,sha256=JpVEXkg2xDj9vjnGUpAV7_XvnIg6LV74yCj9xo6ZAR4,7693
234
+ strawberry_graphql-0.269.0.dev1747164009.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
235
+ strawberry_graphql-0.269.0.dev1747164009.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
236
+ strawberry_graphql-0.269.0.dev1747164009.dist-info/RECORD,,