strawberry-graphql 0.269.0.dev1746905409__py3-none-any.whl → 0.270.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- strawberry/__init__.py +0 -2
- strawberry/annotation.py +0 -7
- strawberry/http/__init__.py +10 -14
- strawberry/http/async_base_view.py +8 -81
- strawberry/http/base.py +6 -0
- strawberry/http/sync_base_view.py +2 -0
- strawberry/printer/printer.py +2 -10
- strawberry/quart/views.py +95 -16
- strawberry/schema/base.py +3 -0
- strawberry/schema/config.py +0 -1
- strawberry/schema/schema.py +94 -48
- strawberry/schema/schema_converter.py +8 -12
- strawberry/schema/types/scalar.py +1 -0
- strawberry/static/graphiql.html +5 -5
- strawberry/types/arguments.py +5 -0
- strawberry/types/info.py +5 -0
- strawberry/types/scalar.py +2 -0
- {strawberry_graphql-0.269.0.dev1746905409.dist-info → strawberry_graphql-0.270.0.dist-info}/METADATA +1 -1
- {strawberry_graphql-0.269.0.dev1746905409.dist-info → strawberry_graphql-0.270.0.dist-info}/RECORD +22 -24
- strawberry/schema/_graphql_core.py +0 -46
- strawberry/streamable.py +0 -36
- {strawberry_graphql-0.269.0.dev1746905409.dist-info → strawberry_graphql-0.270.0.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.269.0.dev1746905409.dist-info → strawberry_graphql-0.270.0.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.269.0.dev1746905409.dist-info → strawberry_graphql-0.270.0.dist-info}/entry_points.txt +0 -0
strawberry/__init__.py
CHANGED
@@ -11,7 +11,6 @@ from .permission import BasePermission
|
|
11
11
|
from .scalars import ID
|
12
12
|
from .schema import Schema
|
13
13
|
from .schema_directive import schema_directive
|
14
|
-
from .streamable import Streamable
|
15
14
|
from .types.arguments import argument
|
16
15
|
from .types.auto import auto
|
17
16
|
from .types.cast import cast
|
@@ -38,7 +37,6 @@ __all__ = [
|
|
38
37
|
"Private",
|
39
38
|
"Schema",
|
40
39
|
"Some",
|
41
|
-
"Streamable",
|
42
40
|
"argument",
|
43
41
|
"asdict",
|
44
42
|
"auto",
|
strawberry/annotation.py
CHANGED
@@ -17,7 +17,6 @@ from typing import (
|
|
17
17
|
)
|
18
18
|
from typing_extensions import Self, get_args, get_origin
|
19
19
|
|
20
|
-
from strawberry.streamable import StrawberryStreamable
|
21
20
|
from strawberry.types.base import (
|
22
21
|
StrawberryList,
|
23
22
|
StrawberryMaybe,
|
@@ -144,8 +143,6 @@ class StrawberryAnnotation:
|
|
144
143
|
|
145
144
|
if self._is_lazy_type(evaled_type):
|
146
145
|
return evaled_type
|
147
|
-
if self._is_streamable(evaled_type, args):
|
148
|
-
return self.create_list(list[evaled_type])
|
149
146
|
if self._is_list(evaled_type):
|
150
147
|
return self.create_list(evaled_type)
|
151
148
|
if type_of := self._get_maybe_type(evaled_type):
|
@@ -326,10 +323,6 @@ class StrawberryAnnotation:
|
|
326
323
|
def _get_maybe_type(cls, annotation: Any) -> type | None:
|
327
324
|
return get_args(annotation)[0] if _annotation_is_maybe(annotation) else None
|
328
325
|
|
329
|
-
@classmethod
|
330
|
-
def _is_streamable(cls, annotation: Any, args: list[Any]) -> bool:
|
331
|
-
return any(isinstance(arg, StrawberryStreamable) for arg in args)
|
332
|
-
|
333
326
|
@classmethod
|
334
327
|
def _is_strawberry_type(cls, evaled_type: Any) -> bool:
|
335
328
|
# Prevent import cycles
|
strawberry/http/__init__.py
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import Any, Optional
|
4
|
+
from typing import TYPE_CHECKING, Any, Optional
|
5
5
|
from typing_extensions import Literal, TypedDict
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
ResultType,
|
10
|
-
)
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from strawberry.types import ExecutionResult
|
11
9
|
|
12
10
|
|
13
11
|
class GraphQLHTTPResponse(TypedDict, total=False):
|
@@ -16,16 +14,13 @@ class GraphQLHTTPResponse(TypedDict, total=False):
|
|
16
14
|
extensions: Optional[dict[str, object]]
|
17
15
|
|
18
16
|
|
19
|
-
def process_result(result:
|
20
|
-
|
21
|
-
return result
|
17
|
+
def process_result(result: ExecutionResult) -> GraphQLHTTPResponse:
|
18
|
+
data: GraphQLHTTPResponse = {"data": result.data}
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
**({"extensions": extensions} if extensions else {}),
|
28
|
-
}
|
20
|
+
if result.errors:
|
21
|
+
data["errors"] = [err.formatted for err in result.errors]
|
22
|
+
if result.extensions:
|
23
|
+
data["extensions"] = result.extensions
|
29
24
|
|
30
25
|
return data
|
31
26
|
|
@@ -37,6 +32,7 @@ class GraphQLRequestData:
|
|
37
32
|
query: Optional[str]
|
38
33
|
variables: Optional[dict[str, Any]]
|
39
34
|
operation_name: Optional[str]
|
35
|
+
extensions: Optional[dict[str, Any]]
|
40
36
|
protocol: Literal["http", "multipart-subscription"] = "http"
|
41
37
|
|
42
38
|
|
@@ -25,9 +25,6 @@ from strawberry.http import (
|
|
25
25
|
process_result,
|
26
26
|
)
|
27
27
|
from strawberry.http.ides import GraphQL_IDE
|
28
|
-
from strawberry.schema._graphql_core import (
|
29
|
-
GraphQLIncrementalExecutionResults,
|
30
|
-
)
|
31
28
|
from strawberry.schema.base import BaseSchema
|
32
29
|
from strawberry.schema.exceptions import InvalidOperationTypeError
|
33
30
|
from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
|
@@ -207,6 +204,7 @@ class AsyncBaseHTTPView(
|
|
207
204
|
context_value=context,
|
208
205
|
root_value=root_value,
|
209
206
|
operation_name=request_data.operation_name,
|
207
|
+
operation_extensions=request_data.extensions,
|
210
208
|
)
|
211
209
|
|
212
210
|
return await self.schema.execute(
|
@@ -216,6 +214,7 @@ class AsyncBaseHTTPView(
|
|
216
214
|
context_value=context,
|
217
215
|
operation_name=request_data.operation_name,
|
218
216
|
allowed_operation_types=allowed_operation_types,
|
217
|
+
operation_extensions=request_data.extensions,
|
219
218
|
)
|
220
219
|
|
221
220
|
async def parse_multipart(self, request: AsyncHTTPRequestAdapter) -> dict[str, str]:
|
@@ -261,7 +260,7 @@ class AsyncBaseHTTPView(
|
|
261
260
|
root_value: Optional[RootValue] = UNSET,
|
262
261
|
) -> WebSocketResponse: ...
|
263
262
|
|
264
|
-
async def run(
|
263
|
+
async def run(
|
265
264
|
self,
|
266
265
|
request: Union[Request, WebSocketRequest],
|
267
266
|
context: Optional[Context] = UNSET,
|
@@ -352,75 +351,6 @@ class AsyncBaseHTTPView(
|
|
352
351
|
"Content-Type": "multipart/mixed;boundary=graphql;subscriptionSpec=1.0,application/json",
|
353
352
|
},
|
354
353
|
)
|
355
|
-
if isinstance(result, GraphQLIncrementalExecutionResults):
|
356
|
-
|
357
|
-
async def stream() -> AsyncGenerator[str, None]:
|
358
|
-
yield "---"
|
359
|
-
|
360
|
-
response = await self.process_result(request, result.initial_result)
|
361
|
-
|
362
|
-
response["hasNext"] = result.initial_result.has_next
|
363
|
-
response["pending"] = [
|
364
|
-
p.formatted for p in result.initial_result.pending
|
365
|
-
]
|
366
|
-
response["extensions"] = result.initial_result.extensions
|
367
|
-
|
368
|
-
yield self.encode_multipart_data(response, "-")
|
369
|
-
|
370
|
-
all_pending = result.initial_result.pending
|
371
|
-
|
372
|
-
async for value in result.subsequent_results:
|
373
|
-
response = {
|
374
|
-
"hasNext": value.has_next,
|
375
|
-
"extensions": value.extensions,
|
376
|
-
}
|
377
|
-
|
378
|
-
if value.pending:
|
379
|
-
response["pending"] = [p.formatted for p in value.pending]
|
380
|
-
|
381
|
-
if value.completed:
|
382
|
-
response["completed"] = [p.formatted for p in value.completed]
|
383
|
-
|
384
|
-
if value.incremental:
|
385
|
-
incremental = []
|
386
|
-
|
387
|
-
all_pending.extend(value.pending)
|
388
|
-
|
389
|
-
for incremental_value in value.incremental:
|
390
|
-
pending_value = next(
|
391
|
-
(
|
392
|
-
v
|
393
|
-
for v in all_pending
|
394
|
-
if v.id == incremental_value.id
|
395
|
-
),
|
396
|
-
None,
|
397
|
-
)
|
398
|
-
|
399
|
-
assert pending_value
|
400
|
-
|
401
|
-
incremental.append(
|
402
|
-
{
|
403
|
-
**incremental_value.formatted,
|
404
|
-
"path": pending_value.path,
|
405
|
-
"label": pending_value.label,
|
406
|
-
}
|
407
|
-
)
|
408
|
-
|
409
|
-
response["incremental"] = incremental
|
410
|
-
|
411
|
-
yield self.encode_multipart_data(response, "-")
|
412
|
-
|
413
|
-
yield "--\r\n"
|
414
|
-
|
415
|
-
return await self.create_streaming_response(
|
416
|
-
request,
|
417
|
-
stream,
|
418
|
-
sub_response,
|
419
|
-
headers={
|
420
|
-
"Transfer-Encoding": "chunked",
|
421
|
-
"Content-Type": 'multipart/mixed; boundary="-"',
|
422
|
-
},
|
423
|
-
)
|
424
354
|
|
425
355
|
response_data = await self.process_result(request=request, result=result)
|
426
356
|
|
@@ -432,16 +362,12 @@ class AsyncBaseHTTPView(
|
|
432
362
|
)
|
433
363
|
|
434
364
|
def encode_multipart_data(self, data: Any, separator: str) -> str:
|
435
|
-
encoded_data = self.encode_json(data)
|
436
|
-
|
437
365
|
return "".join(
|
438
366
|
[
|
439
|
-
"\r\n",
|
440
|
-
"Content-Type: application/json
|
441
|
-
|
442
|
-
"\
|
443
|
-
encoded_data,
|
444
|
-
f"\r\n--{separator}",
|
367
|
+
f"\r\n--{separator}\r\n",
|
368
|
+
"Content-Type: application/json\r\n\r\n",
|
369
|
+
self.encode_json(data),
|
370
|
+
"\n",
|
445
371
|
]
|
446
372
|
)
|
447
373
|
|
@@ -548,6 +474,7 @@ class AsyncBaseHTTPView(
|
|
548
474
|
query=data.get("query"),
|
549
475
|
variables=data.get("variables"),
|
550
476
|
operation_name=data.get("operationName"),
|
477
|
+
extensions=data.get("extensions"),
|
551
478
|
protocol=protocol,
|
552
479
|
)
|
553
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/printer/printer.py
CHANGED
@@ -561,9 +561,9 @@ def print_schema_definition(
|
|
561
561
|
def print_directive(
|
562
562
|
directive: GraphQLDirective, *, schema: BaseSchema
|
563
563
|
) -> Optional[str]:
|
564
|
-
strawberry_directive = directive.extensions
|
564
|
+
strawberry_directive = directive.extensions["strawberry-definition"]
|
565
565
|
|
566
|
-
if
|
566
|
+
if (
|
567
567
|
isinstance(strawberry_directive, StrawberrySchemaDirective)
|
568
568
|
and not strawberry_directive.print_definition
|
569
569
|
):
|
@@ -621,14 +621,6 @@ def print_schema(schema: BaseSchema) -> str:
|
|
621
621
|
if (printed_directive := print_directive(directive, schema=schema)) is not None
|
622
622
|
]
|
623
623
|
|
624
|
-
if schema.config.enable_experimental_incremental_execution:
|
625
|
-
directives.append(
|
626
|
-
"directive @defer(if: Boolean, label: String) on FRAGMENT_SPREAD | INLINE_FRAGMENT"
|
627
|
-
)
|
628
|
-
directives.append(
|
629
|
-
"directive @stream(if: Boolean, label: String, initialCount: Int = 0) on FIELD"
|
630
|
-
)
|
631
|
-
|
632
624
|
def _name_getter(type_: Any) -> str:
|
633
625
|
if hasattr(type_, "name"):
|
634
626
|
return type_.name
|
strawberry/quart/views.py
CHANGED
@@ -1,15 +1,29 @@
|
|
1
|
+
import asyncio
|
1
2
|
import warnings
|
2
|
-
from collections.abc import AsyncGenerator, Mapping
|
3
|
-
from
|
3
|
+
from collections.abc import AsyncGenerator, Mapping, Sequence
|
4
|
+
from datetime import timedelta
|
5
|
+
from json.decoder import JSONDecodeError
|
6
|
+
from typing import TYPE_CHECKING, Callable, ClassVar, Optional, Union, cast
|
4
7
|
from typing_extensions import TypeGuard
|
5
8
|
|
6
|
-
from quart import Request, Response, request
|
9
|
+
from quart import Request, Response, Websocket, request, websocket
|
10
|
+
from quart.ctx import has_websocket_context
|
7
11
|
from quart.views import View
|
8
|
-
from strawberry.http.async_base_view import
|
9
|
-
|
12
|
+
from strawberry.http.async_base_view import (
|
13
|
+
AsyncBaseHTTPView,
|
14
|
+
AsyncHTTPRequestAdapter,
|
15
|
+
AsyncWebSocketAdapter,
|
16
|
+
)
|
17
|
+
from strawberry.http.exceptions import (
|
18
|
+
HTTPException,
|
19
|
+
NonJsonMessageReceived,
|
20
|
+
NonTextMessageReceived,
|
21
|
+
WebSocketDisconnected,
|
22
|
+
)
|
10
23
|
from strawberry.http.ides import GraphQL_IDE
|
11
24
|
from strawberry.http.types import FormData, HTTPMethod, QueryParams
|
12
25
|
from strawberry.http.typevars import Context, RootValue
|
26
|
+
from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
|
13
27
|
|
14
28
|
if TYPE_CHECKING:
|
15
29
|
from quart.typing import ResponseReturnValue
|
@@ -46,15 +60,55 @@ class QuartHTTPRequestAdapter(AsyncHTTPRequestAdapter):
|
|
46
60
|
return FormData(files=files, form=form)
|
47
61
|
|
48
62
|
|
63
|
+
class QuartWebSocketAdapter(AsyncWebSocketAdapter):
|
64
|
+
def __init__(
|
65
|
+
self, view: AsyncBaseHTTPView, request: Websocket, response: Response
|
66
|
+
) -> None:
|
67
|
+
super().__init__(view)
|
68
|
+
self.ws = request
|
69
|
+
|
70
|
+
async def iter_json(
|
71
|
+
self, *, ignore_parsing_errors: bool = False
|
72
|
+
) -> AsyncGenerator[object, None]:
|
73
|
+
try:
|
74
|
+
while True:
|
75
|
+
# Raises asyncio.CancelledError when the connection is closed.
|
76
|
+
# https://quart.palletsprojects.com/en/latest/how_to_guides/websockets.html#detecting-disconnection
|
77
|
+
message = await self.ws.receive()
|
78
|
+
|
79
|
+
if not isinstance(message, str):
|
80
|
+
raise NonTextMessageReceived
|
81
|
+
|
82
|
+
try:
|
83
|
+
yield self.view.decode_json(message)
|
84
|
+
except JSONDecodeError as e:
|
85
|
+
if not ignore_parsing_errors:
|
86
|
+
raise NonJsonMessageReceived from e
|
87
|
+
except asyncio.CancelledError:
|
88
|
+
pass
|
89
|
+
|
90
|
+
async def send_json(self, message: Mapping[str, object]) -> None:
|
91
|
+
try:
|
92
|
+
# Raises asyncio.CancelledError when the connection is closed.
|
93
|
+
# https://quart.palletsprojects.com/en/latest/how_to_guides/websockets.html#detecting-disconnection
|
94
|
+
await self.ws.send(self.view.encode_json(message))
|
95
|
+
except asyncio.CancelledError as exc:
|
96
|
+
raise WebSocketDisconnected from exc
|
97
|
+
|
98
|
+
async def close(self, code: int, reason: str) -> None:
|
99
|
+
await self.ws.close(code, reason=reason)
|
100
|
+
|
101
|
+
|
49
102
|
class GraphQLView(
|
50
103
|
AsyncBaseHTTPView[
|
51
|
-
Request, Response, Response,
|
104
|
+
Request, Response, Response, Websocket, Response, Context, RootValue
|
52
105
|
],
|
53
106
|
View,
|
54
107
|
):
|
55
108
|
methods: ClassVar[list[str]] = ["GET", "POST"]
|
56
109
|
allow_queries_via_get: bool = True
|
57
110
|
request_adapter_class = QuartHTTPRequestAdapter
|
111
|
+
websocket_adapter_class = QuartWebSocketAdapter
|
58
112
|
|
59
113
|
def __init__(
|
60
114
|
self,
|
@@ -62,10 +116,23 @@ class GraphQLView(
|
|
62
116
|
graphiql: Optional[bool] = None,
|
63
117
|
graphql_ide: Optional[GraphQL_IDE] = "graphiql",
|
64
118
|
allow_queries_via_get: bool = True,
|
119
|
+
keep_alive: bool = True,
|
120
|
+
keep_alive_interval: float = 1,
|
121
|
+
debug: bool = False,
|
122
|
+
subscription_protocols: Sequence[str] = (
|
123
|
+
GRAPHQL_TRANSPORT_WS_PROTOCOL,
|
124
|
+
GRAPHQL_WS_PROTOCOL,
|
125
|
+
),
|
126
|
+
connection_init_wait_timeout: timedelta = timedelta(minutes=1),
|
65
127
|
multipart_uploads_enabled: bool = False,
|
66
128
|
) -> None:
|
67
129
|
self.schema = schema
|
68
130
|
self.allow_queries_via_get = allow_queries_via_get
|
131
|
+
self.keep_alive = keep_alive
|
132
|
+
self.keep_alive_interval = keep_alive_interval
|
133
|
+
self.debug = debug
|
134
|
+
self.subscription_protocols = subscription_protocols
|
135
|
+
self.connection_init_wait_timeout = connection_init_wait_timeout
|
69
136
|
self.multipart_uploads_enabled = multipart_uploads_enabled
|
70
137
|
|
71
138
|
if graphiql is not None:
|
@@ -88,18 +155,24 @@ class GraphQLView(
|
|
88
155
|
|
89
156
|
return sub_response
|
90
157
|
|
91
|
-
async def get_context(
|
158
|
+
async def get_context(
|
159
|
+
self, request: Union[Request, Websocket], response: Response
|
160
|
+
) -> Context:
|
92
161
|
return {"request": request, "response": response} # type: ignore
|
93
162
|
|
94
|
-
async def get_root_value(
|
163
|
+
async def get_root_value(
|
164
|
+
self, request: Union[Request, Websocket]
|
165
|
+
) -> Optional[RootValue]:
|
95
166
|
return None
|
96
167
|
|
97
168
|
async def get_sub_response(self, request: Request) -> Response:
|
98
169
|
return Response(status=200, content_type="application/json")
|
99
170
|
|
100
|
-
async def dispatch_request(self) -> "ResponseReturnValue":
|
171
|
+
async def dispatch_request(self, **kwargs: object) -> "ResponseReturnValue":
|
101
172
|
try:
|
102
|
-
return await self.run(
|
173
|
+
return await self.run(
|
174
|
+
request=websocket if has_websocket_context() else request
|
175
|
+
)
|
103
176
|
except HTTPException as e:
|
104
177
|
return Response(
|
105
178
|
response=e.reason,
|
@@ -122,16 +195,22 @@ class GraphQLView(
|
|
122
195
|
},
|
123
196
|
)
|
124
197
|
|
125
|
-
def is_websocket_request(
|
126
|
-
|
198
|
+
def is_websocket_request(
|
199
|
+
self, request: Union[Request, Websocket]
|
200
|
+
) -> TypeGuard[Websocket]:
|
201
|
+
return has_websocket_context()
|
127
202
|
|
128
|
-
async def pick_websocket_subprotocol(self, request:
|
129
|
-
|
203
|
+
async def pick_websocket_subprotocol(self, request: Websocket) -> Optional[str]:
|
204
|
+
protocols = request.requested_subprotocols
|
205
|
+
intersection = set(protocols) & set(self.subscription_protocols)
|
206
|
+
sorted_intersection = sorted(intersection, key=protocols.index)
|
207
|
+
return next(iter(sorted_intersection), None)
|
130
208
|
|
131
209
|
async def create_websocket_response(
|
132
|
-
self, request:
|
210
|
+
self, request: Websocket, subprotocol: Optional[str]
|
133
211
|
) -> Response:
|
134
|
-
|
212
|
+
await request.accept(subprotocol=subprotocol)
|
213
|
+
return Response()
|
135
214
|
|
136
215
|
|
137
216
|
__all__ = ["GraphQLView"]
|
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
|
|
strawberry/schema/config.py
CHANGED
strawberry/schema/schema.py
CHANGED
@@ -9,26 +9,34 @@ 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
|
)
|
39
|
+
from graphql.execution import execute, subscribe
|
32
40
|
from graphql.execution.middleware import MiddlewareManager
|
33
41
|
from graphql.type.directives import specified_directives
|
34
42
|
from graphql.validation import validate
|
@@ -56,20 +64,11 @@ from strawberry.types.execution import (
|
|
56
64
|
PreExecutionError,
|
57
65
|
)
|
58
66
|
from strawberry.types.graphql import OperationType
|
59
|
-
from strawberry.utils import IS_GQL_32
|
67
|
+
from strawberry.utils import IS_GQL_32, IS_GQL_33
|
60
68
|
from strawberry.utils.aio import aclosing
|
61
69
|
from strawberry.utils.await_maybe import await_maybe
|
62
70
|
|
63
71
|
from . import compat
|
64
|
-
from ._graphql_core import (
|
65
|
-
GraphQLExecutionContext,
|
66
|
-
GraphQLIncrementalExecutionResults,
|
67
|
-
ResultType,
|
68
|
-
execute,
|
69
|
-
experimental_execute_incrementally,
|
70
|
-
incremental_execution_directives,
|
71
|
-
subscribe,
|
72
|
-
)
|
73
72
|
from .base import BaseSchema
|
74
73
|
from .config import StrawberryConfig
|
75
74
|
from .exceptions import InvalidOperationTypeError
|
@@ -78,8 +77,10 @@ if TYPE_CHECKING:
|
|
78
77
|
from collections.abc import Iterable, Mapping
|
79
78
|
from typing_extensions import TypeAlias
|
80
79
|
|
81
|
-
from graphql import
|
80
|
+
from graphql.execution.collect_fields import FieldGroup # type: ignore
|
82
81
|
from graphql.language import DocumentNode
|
82
|
+
from graphql.pyutils import Path
|
83
|
+
from graphql.type import GraphQLResolveInfo
|
83
84
|
from graphql.validation import ASTValidationRule
|
84
85
|
|
85
86
|
from strawberry.directive import StrawberryDirective
|
@@ -98,7 +99,6 @@ OriginSubscriptionResult = Union[
|
|
98
99
|
AsyncIterator[OriginalExecutionResult],
|
99
100
|
]
|
100
101
|
|
101
|
-
|
102
102
|
DEFAULT_ALLOWED_OPERATION_TYPES = {
|
103
103
|
OperationType.QUERY,
|
104
104
|
OperationType.MUTATION,
|
@@ -144,6 +144,62 @@ def _coerce_error(error: Union[GraphQLError, Exception]) -> GraphQLError:
|
|
144
144
|
return GraphQLError(str(error), original_error=error)
|
145
145
|
|
146
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
|
+
|
147
203
|
class Schema(BaseSchema):
|
148
204
|
def __init__(
|
149
205
|
self,
|
@@ -203,7 +259,9 @@ class Schema(BaseSchema):
|
|
203
259
|
|
204
260
|
self.extensions = extensions
|
205
261
|
self._cached_middleware_manager: MiddlewareManager | None = None
|
206
|
-
self.execution_context_class =
|
262
|
+
self.execution_context_class = (
|
263
|
+
execution_context_class or StrawberryGraphQLCoreExecutionContext
|
264
|
+
)
|
207
265
|
self.config = config or StrawberryConfig()
|
208
266
|
|
209
267
|
self.schema_converter = GraphQLCoreConverter(
|
@@ -263,16 +321,11 @@ class Schema(BaseSchema):
|
|
263
321
|
graphql_types.append(graphql_type)
|
264
322
|
|
265
323
|
try:
|
266
|
-
directives = specified_directives + tuple(graphql_directives)
|
267
|
-
|
268
|
-
if self.config.enable_experimental_incremental_execution:
|
269
|
-
directives = tuple(directives) + tuple(incremental_execution_directives)
|
270
|
-
|
271
324
|
self._schema = GraphQLSchema(
|
272
325
|
query=query_type,
|
273
326
|
mutation=mutation_type,
|
274
327
|
subscription=subscription_type if subscription else None,
|
275
|
-
directives=
|
328
|
+
directives=specified_directives + tuple(graphql_directives),
|
276
329
|
types=graphql_types,
|
277
330
|
extensions={
|
278
331
|
GraphQLCoreConverter.DEFINITION_BACKREF: self,
|
@@ -333,6 +386,14 @@ class Schema(BaseSchema):
|
|
333
386
|
extensions=extensions,
|
334
387
|
)
|
335
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
|
+
|
336
397
|
def _get_middleware_manager(
|
337
398
|
self, extensions: list[SchemaExtension]
|
338
399
|
) -> MiddlewareManager:
|
@@ -450,16 +511,12 @@ class Schema(BaseSchema):
|
|
450
511
|
async def _handle_execution_result(
|
451
512
|
self,
|
452
513
|
context: ExecutionContext,
|
453
|
-
result:
|
514
|
+
result: Union[GraphQLExecutionResult, ExecutionResult],
|
454
515
|
extensions_runner: SchemaExtensionsRunner,
|
455
516
|
*,
|
456
517
|
# TODO: can we remove this somehow, see comment in execute
|
457
518
|
skip_process_errors: bool = False,
|
458
519
|
) -> ExecutionResult:
|
459
|
-
# TODO: handle this, also, why do we have both GraphQLExecutionResult and ExecutionResult?
|
460
|
-
if isinstance(result, GraphQLIncrementalExecutionResults):
|
461
|
-
return result
|
462
|
-
|
463
520
|
# Set errors on the context so that it's easier
|
464
521
|
# to access in extensions
|
465
522
|
if result.errors:
|
@@ -480,6 +537,7 @@ class Schema(BaseSchema):
|
|
480
537
|
root_value: Optional[Any] = None,
|
481
538
|
operation_name: Optional[str] = None,
|
482
539
|
allowed_operation_types: Optional[Iterable[OperationType]] = None,
|
540
|
+
operation_extensions: Optional[dict[str, Any]] = None,
|
483
541
|
) -> ExecutionResult:
|
484
542
|
if allowed_operation_types is None:
|
485
543
|
allowed_operation_types = DEFAULT_ALLOWED_OPERATION_TYPES
|
@@ -500,16 +558,7 @@ class Schema(BaseSchema):
|
|
500
558
|
extensions_runner = self.create_extensions_runner(execution_context, extensions)
|
501
559
|
middleware_manager = self._get_middleware_manager(extensions)
|
502
560
|
|
503
|
-
|
504
|
-
|
505
|
-
if self.config.enable_experimental_incremental_execution:
|
506
|
-
execute_function = experimental_execute_incrementally
|
507
|
-
|
508
|
-
if execute_function is None:
|
509
|
-
raise RuntimeError(
|
510
|
-
"Incremental execution is enabled but experimental_execute_incrementally is not available, "
|
511
|
-
"please install graphql-core>=3.3.0"
|
512
|
-
)
|
561
|
+
custom_context_kwargs = self._get_custom_context_kwargs(operation_extensions)
|
513
562
|
|
514
563
|
try:
|
515
564
|
async with extensions_runner.operation():
|
@@ -529,7 +578,7 @@ class Schema(BaseSchema):
|
|
529
578
|
async with extensions_runner.executing():
|
530
579
|
if not execution_context.result:
|
531
580
|
result = await await_maybe(
|
532
|
-
|
581
|
+
execute(
|
533
582
|
self._schema,
|
534
583
|
execution_context.graphql_document,
|
535
584
|
root_value=execution_context.root_value,
|
@@ -538,6 +587,7 @@ class Schema(BaseSchema):
|
|
538
587
|
operation_name=execution_context.operation_name,
|
539
588
|
context_value=execution_context.context,
|
540
589
|
execution_context_class=self.execution_context_class,
|
590
|
+
**custom_context_kwargs,
|
541
591
|
)
|
542
592
|
)
|
543
593
|
execution_context.result = result
|
@@ -545,9 +595,7 @@ class Schema(BaseSchema):
|
|
545
595
|
result = execution_context.result
|
546
596
|
# Also set errors on the execution_context so that it's easier
|
547
597
|
# to access in extensions
|
548
|
-
|
549
|
-
# TODO: maybe here use the first result from incremental execution if it exists
|
550
|
-
if isinstance(result, GraphQLExecutionResult) and result.errors:
|
598
|
+
if result.errors:
|
551
599
|
execution_context.errors = result.errors
|
552
600
|
|
553
601
|
# Run the `Schema.process_errors` function here before
|
@@ -577,6 +625,7 @@ class Schema(BaseSchema):
|
|
577
625
|
root_value: Optional[Any] = None,
|
578
626
|
operation_name: Optional[str] = None,
|
579
627
|
allowed_operation_types: Optional[Iterable[OperationType]] = None,
|
628
|
+
operation_extensions: Optional[dict[str, Any]] = None,
|
580
629
|
) -> ExecutionResult:
|
581
630
|
if allowed_operation_types is None:
|
582
631
|
allowed_operation_types = DEFAULT_ALLOWED_OPERATION_TYPES
|
@@ -597,16 +646,8 @@ class Schema(BaseSchema):
|
|
597
646
|
extensions_runner = self.create_extensions_runner(execution_context, extensions)
|
598
647
|
middleware_manager = self._get_middleware_manager(extensions)
|
599
648
|
|
600
|
-
|
601
|
-
|
602
|
-
if self.config.enable_experimental_incremental_execution:
|
603
|
-
execute_function = experimental_execute_incrementally
|
649
|
+
custom_context_kwargs = self._get_custom_context_kwargs(operation_extensions)
|
604
650
|
|
605
|
-
if execute_function is None:
|
606
|
-
raise RuntimeError(
|
607
|
-
"Incremental execution is enabled but experimental_execute_incrementally is not available, "
|
608
|
-
"please install graphql-core>=3.3.0"
|
609
|
-
)
|
610
651
|
try:
|
611
652
|
with extensions_runner.operation():
|
612
653
|
# Note: In graphql-core the schema would be validated here but in
|
@@ -648,7 +689,7 @@ class Schema(BaseSchema):
|
|
648
689
|
|
649
690
|
with extensions_runner.executing():
|
650
691
|
if not execution_context.result:
|
651
|
-
result =
|
692
|
+
result = execute(
|
652
693
|
self._schema,
|
653
694
|
execution_context.graphql_document,
|
654
695
|
root_value=execution_context.root_value,
|
@@ -657,6 +698,7 @@ class Schema(BaseSchema):
|
|
657
698
|
operation_name=execution_context.operation_name,
|
658
699
|
context_value=execution_context.context,
|
659
700
|
execution_context_class=self.execution_context_class,
|
701
|
+
**custom_context_kwargs,
|
660
702
|
)
|
661
703
|
|
662
704
|
if isawaitable(result):
|
@@ -701,6 +743,7 @@ class Schema(BaseSchema):
|
|
701
743
|
extensions_runner: SchemaExtensionsRunner,
|
702
744
|
middleware_manager: MiddlewareManager,
|
703
745
|
execution_context_class: type[GraphQLExecutionContext] | None = None,
|
746
|
+
operation_extensions: Optional[dict[str, Any]] = None,
|
704
747
|
) -> AsyncGenerator[ExecutionResult, None]:
|
705
748
|
async with extensions_runner.operation():
|
706
749
|
if initial_error := await self._parse_and_validate_async(
|
@@ -719,6 +762,7 @@ class Schema(BaseSchema):
|
|
719
762
|
gql_33_kwargs = {
|
720
763
|
"middleware": middleware_manager,
|
721
764
|
"execution_context_class": execution_context_class,
|
765
|
+
"operation_extensions": operation_extensions,
|
722
766
|
}
|
723
767
|
try:
|
724
768
|
# Might not be awaitable for pre-execution errors.
|
@@ -783,6 +827,7 @@ class Schema(BaseSchema):
|
|
783
827
|
context_value: Optional[Any] = None,
|
784
828
|
root_value: Optional[Any] = None,
|
785
829
|
operation_name: Optional[str] = None,
|
830
|
+
operation_extensions: Optional[dict[str, Any]] = None,
|
786
831
|
) -> SubscriptionResult:
|
787
832
|
execution_context = self._create_execution_context(
|
788
833
|
query=query,
|
@@ -804,6 +849,7 @@ class Schema(BaseSchema):
|
|
804
849
|
),
|
805
850
|
middleware_manager=self._get_middleware_manager(extensions),
|
806
851
|
execution_context_class=self.execution_context_class,
|
852
|
+
operation_extensions=operation_extensions,
|
807
853
|
)
|
808
854
|
|
809
855
|
def _resolve_node_ids(self) -> None:
|
@@ -270,10 +270,7 @@ class GraphQLCoreConverter:
|
|
270
270
|
GlobalID,
|
271
271
|
name=global_id_name,
|
272
272
|
description=GraphQLID.description,
|
273
|
-
|
274
|
-
GraphQLID.parse_literal(v, vars)
|
275
|
-
),
|
276
|
-
parse_value=GlobalID.from_id,
|
273
|
+
parse_value=lambda v: v,
|
277
274
|
serialize=str,
|
278
275
|
specified_by_url=("https://relay.dev/graphql/objectidentification.htm"),
|
279
276
|
)
|
@@ -803,6 +800,13 @@ class GraphQLCoreConverter:
|
|
803
800
|
return _resolver
|
804
801
|
|
805
802
|
def from_scalar(self, scalar: type) -> GraphQLScalarType:
|
803
|
+
from strawberry.relay.types import GlobalID
|
804
|
+
|
805
|
+
if not self.config.relay_use_legacy_global_id and scalar is GlobalID:
|
806
|
+
from strawberry import ID
|
807
|
+
|
808
|
+
return self.from_scalar(ID)
|
809
|
+
|
806
810
|
scalar_definition: ScalarDefinition
|
807
811
|
|
808
812
|
if scalar in self.scalar_registry:
|
@@ -818,20 +822,12 @@ class GraphQLCoreConverter:
|
|
818
822
|
scalar_name = self.config.name_converter.from_type(scalar_definition)
|
819
823
|
|
820
824
|
if scalar_name not in self.type_map:
|
821
|
-
from strawberry.relay import GlobalID
|
822
|
-
|
823
|
-
if scalar is GlobalID and hasattr(GraphQLNamedType, "reserved_types"):
|
824
|
-
GraphQLNamedType.reserved_types.pop("ID")
|
825
|
-
|
826
825
|
implementation = (
|
827
826
|
scalar_definition.implementation
|
828
827
|
if scalar_definition.implementation is not None
|
829
828
|
else _make_scalar_type(scalar_definition)
|
830
829
|
)
|
831
830
|
|
832
|
-
if scalar is GlobalID and hasattr(GraphQLNamedType, "reserved_types"):
|
833
|
-
GraphQLNamedType.reserved_types["ID"] = implementation
|
834
|
-
|
835
831
|
self.type_map[scalar_name] = ConcreteType(
|
836
832
|
definition=scalar_definition, implementation=implementation
|
837
833
|
)
|
strawberry/static/graphiql.html
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
<!
|
1
|
+
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
4
|
<title>Strawberry GraphiQL</title>
|
@@ -61,8 +61,8 @@
|
|
61
61
|
<link
|
62
62
|
crossorigin
|
63
63
|
rel="stylesheet"
|
64
|
-
href="https://unpkg.com/graphiql@3.
|
65
|
-
integrity="sha384-
|
64
|
+
href="https://unpkg.com/graphiql@3.0.9/graphiql.min.css"
|
65
|
+
integrity="sha384-yz3/sqpuplkA7msMo0FE4ekg0xdwdvZ8JX9MVZREsxipqjU4h8IRfmAMRcb1QpUy"
|
66
66
|
/>
|
67
67
|
|
68
68
|
<link
|
@@ -77,8 +77,8 @@
|
|
77
77
|
<div id="graphiql" class="graphiql-container">Loading...</div>
|
78
78
|
<script
|
79
79
|
crossorigin
|
80
|
-
src="https://unpkg.com/graphiql@3.
|
81
|
-
integrity="sha384-
|
80
|
+
src="https://unpkg.com/graphiql@3.0.9/graphiql.min.js"
|
81
|
+
integrity="sha384-Mjte+vxCWz1ZYCzszGHiJqJa5eAxiqI4mc3BErq7eDXnt+UGLXSEW7+i0wmfPiji"
|
82
82
|
></script>
|
83
83
|
<script
|
84
84
|
crossorigin
|
strawberry/types/arguments.py
CHANGED
@@ -170,6 +170,11 @@ def convert_argument(
|
|
170
170
|
]
|
171
171
|
|
172
172
|
if is_scalar(type_, scalar_registry):
|
173
|
+
from strawberry.relay.types import GlobalID
|
174
|
+
|
175
|
+
if type_ is GlobalID:
|
176
|
+
return GlobalID.from_id(value) # type: ignore
|
177
|
+
|
173
178
|
return value
|
174
179
|
|
175
180
|
if isinstance(type_, EnumDefinition):
|
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."""
|
strawberry/types/scalar.py
CHANGED
@@ -43,6 +43,7 @@ class ScalarDefinition(StrawberryType):
|
|
43
43
|
parse_value: Optional[Callable]
|
44
44
|
parse_literal: Optional[Callable]
|
45
45
|
directives: Iterable[object] = ()
|
46
|
+
origin: Optional[GraphQLScalarType | type] = None
|
46
47
|
|
47
48
|
# Optionally store the GraphQLScalarType instance so that we don't get
|
48
49
|
# duplicates
|
@@ -115,6 +116,7 @@ def _process_scalar(
|
|
115
116
|
parse_literal=parse_literal,
|
116
117
|
parse_value=parse_value,
|
117
118
|
directives=directives,
|
119
|
+
origin=cls, # type: ignore[arg-type]
|
118
120
|
_source_file=_source_file,
|
119
121
|
_source_line=_source_line,
|
120
122
|
)
|
{strawberry_graphql-0.269.0.dev1746905409.dist-info → strawberry_graphql-0.270.0.dist-info}/RECORD
RENAMED
@@ -1,10 +1,10 @@
|
|
1
|
-
strawberry/__init__.py,sha256
|
1
|
+
strawberry/__init__.py,sha256=-K---AYIgHvBVYF_9oovgEPNBbymXH673bntlV9sOeU,1491
|
2
2
|
strawberry/__main__.py,sha256=3U77Eu21mJ-LY27RG-JEnpbh6Z63wGOom4i-EoLtUcY,59
|
3
3
|
strawberry/aiohttp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
strawberry/aiohttp/test/__init__.py,sha256=4xxdUZtIISSOwjrcnmox7AvT4WWjowCm5bUuPdQneMg,71
|
5
5
|
strawberry/aiohttp/test/client.py,sha256=8FKZTnvawxYpgEICOri-34O3wHRHLhRpjH_Ktp2EupQ,1801
|
6
6
|
strawberry/aiohttp/views.py,sha256=AQVBbZTBa127TbQRwoBelTHrVdZnJeGdMYcTfNmoaSc,7887
|
7
|
-
strawberry/annotation.py,sha256=
|
7
|
+
strawberry/annotation.py,sha256=iqSXtJ4pTTLDZRPyil0f-yzpcCm8UYRiwvFWkD5LgpQ,13498
|
8
8
|
strawberry/asgi/__init__.py,sha256=psdKl_52LGkxKKbzZlmwNGZ9jz2FLyLSC7fUhys4FqY,8169
|
9
9
|
strawberry/asgi/test/__init__.py,sha256=4xxdUZtIISSOwjrcnmox7AvT4WWjowCm5bUuPdQneMg,71
|
10
10
|
strawberry/asgi/test/client.py,sha256=kp2O5znHWuAB5VVYO8p4XPSTEDDXBSjNz5WHqW0r6GM,1473
|
@@ -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=
|
134
|
-
strawberry/http/async_base_view.py,sha256=
|
135
|
-
strawberry/http/base.py,sha256=
|
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=
|
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
|
@@ -146,10 +146,10 @@ strawberry/parent.py,sha256=JYFp-HGCgwbH2oB4uLSiIO4cVsoPaxX6lfYmxOKPkSg,1362
|
|
146
146
|
strawberry/permission.py,sha256=dSRJMjSCmTlXfvfC24kCSrAk0txTjYKTJ5ZVU5IW91Y,7537
|
147
147
|
strawberry/printer/__init__.py,sha256=DmepjmgtkdF5RxK_7yC6qUyRWn56U-9qeZMbkztYB9w,62
|
148
148
|
strawberry/printer/ast_from_value.py,sha256=Tkme60qlykbN2m3dNPNMOe65X-wj6EmcDQwgQv7gUkc,4987
|
149
|
-
strawberry/printer/printer.py,sha256=
|
149
|
+
strawberry/printer/printer.py,sha256=49u3QwttTGvh13HXZtbTnkZzBwL1k5SLf8rXQLiTpl4,18814
|
150
150
|
strawberry/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
151
151
|
strawberry/quart/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
152
|
-
strawberry/quart/views.py,sha256=
|
152
|
+
strawberry/quart/views.py,sha256=f41HWnkGPuhs1NkjwHOZ0DEVnlr5nMSMr9GCxNsBxCs,7461
|
153
153
|
strawberry/relay/__init__.py,sha256=Vi4btvA_g6Cj9Tk_F9GCSegapIf2WqkOWV8y3P0cTCs,553
|
154
154
|
strawberry/relay/exceptions.py,sha256=Za0iXLBGZtd1HkesGm4xTr3QOeuyiCAe1hiCCQ2HHvE,4036
|
155
155
|
strawberry/relay/fields.py,sha256=wIwBTXsDimG6incMglEn7Gr7CO8H8AA25yhM8MT8I-0,18100
|
@@ -162,27 +162,25 @@ 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/
|
166
|
-
strawberry/schema/base.py,sha256=q5UAw6do4Ele5Cf8dNAouiPjNmZoCBNFqh5Vl05caCI,3864
|
165
|
+
strawberry/schema/base.py,sha256=wqvEOQ_aVkfebk9SlG9zg1YXl3MlwxGZhxFRoIkAxu0,4053
|
167
166
|
strawberry/schema/compat.py,sha256=xNpOEDfi-MODpplMGaKuKeQIVcr-tcAaKaU3TlBc1Zs,1873
|
168
|
-
strawberry/schema/config.py,sha256=
|
167
|
+
strawberry/schema/config.py,sha256=KeZ1Pc1gvYK0fOx9Aghx7m0Av8sWexycl3HJGFgHPvg,969
|
169
168
|
strawberry/schema/exceptions.py,sha256=rqVNb_oYrKM0dHPgvAemqCG6Um282LPPu4zwQ5cZqs4,584
|
170
169
|
strawberry/schema/name_converter.py,sha256=xFOXEgqldFkxXRkIQvsJN1dPkWbEUaIrTYNOMYSEVwQ,6945
|
171
|
-
strawberry/schema/schema.py,sha256=
|
172
|
-
strawberry/schema/schema_converter.py,sha256=
|
170
|
+
strawberry/schema/schema.py,sha256=zRIv4mpVEFjFWv-MmfjO9v7OsuSFZ2xghr_ekIAuZI4,37113
|
171
|
+
strawberry/schema/schema_converter.py,sha256=_lKctaIfNcncVCan8AElYngGxMS8vf4Wy27tXfkr0Mk,39011
|
173
172
|
strawberry/schema/types/__init__.py,sha256=oHO3COWhL3L1KLYCJNY1XFf5xt2GGtHiMC-UaYbFfnA,68
|
174
173
|
strawberry/schema/types/base_scalars.py,sha256=JRUq0WjEkR9dFewstZnqnZKp0uOEipo4UXNF5dzRf4M,1971
|
175
174
|
strawberry/schema/types/concrete_type.py,sha256=axIyFZgdwNv-XYkiqX67464wuFX6Vp0jYATwnBZSUvM,750
|
176
|
-
strawberry/schema/types/scalar.py,sha256=
|
175
|
+
strawberry/schema/types/scalar.py,sha256=bg9AumdmYUBuvaKoEZtP9YKJ7lwMtDMCWFTsZQwpdQY,2375
|
177
176
|
strawberry/schema/validation_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
178
177
|
strawberry/schema/validation_rules/one_of.py,sha256=fPuYzCyLT7p9y7dHF_sWTImArTQaEhyF664lZijB1Gw,2629
|
179
178
|
strawberry/schema_codegen/__init__.py,sha256=mN4Qmu5Iakht6nHpRpt9hCs8e--oTPlVtDJZJpzgHR4,24364
|
180
179
|
strawberry/schema_directive.py,sha256=CbjdX54EIeWGkJu4SgiLR8mph5_8wyNsgJk2oLoQK_0,2023
|
181
180
|
strawberry/schema_directives.py,sha256=KGKFWCODjm1Ah9qNV_bBwbic7Mld4qLWnWQkev-PG8A,175
|
182
181
|
strawberry/static/apollo-sandbox.html,sha256=2XzkbE0dqsFHqehE-jul9_J9TFOpwA6Ylrlo0Kdx_9w,973
|
183
|
-
strawberry/static/graphiql.html,sha256=
|
182
|
+
strawberry/static/graphiql.html,sha256=BkiqZlC63f1sHBDs_UpMzcibcNrHKh7K41Sp23yttfo,4257
|
184
183
|
strawberry/static/pathfinder.html,sha256=0DPx9AmJ2C_sJstFXnWOz9k5tVQHeHaK7qdVY4lAlmk,1547
|
185
|
-
strawberry/streamable.py,sha256=ylfMt5lfX7RRKGi86wWokvIgYQk5jZCvQVc3shK0epk,645
|
186
184
|
strawberry/subscriptions/__init__.py,sha256=1VGmiCzFepqRFyCikagkUoHHdoTG3XYlFu9GafoQMws,170
|
187
185
|
strawberry/subscriptions/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
188
186
|
strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py,sha256=wN6dkMu6WiaIZTE19PGoN9xXpIN_RdDE_q7F7ZgjCxk,138
|
@@ -197,7 +195,7 @@ strawberry/tools/__init__.py,sha256=pdGpZx8wpq03VfUZJyF9JtYxZhGqzzxCiipsalWxJX4,
|
|
197
195
|
strawberry/tools/create_type.py,sha256=--DgfZOmXJBKGcVxehNISyvpw1HzwFvRtUUPc0634MA,2056
|
198
196
|
strawberry/tools/merge_types.py,sha256=hUMRRNM28FyPp70jRA3d4svv9WoEBjaNpihBt3DaY0I,1023
|
199
197
|
strawberry/types/__init__.py,sha256=baWEdDkkmCcITOhkg2hNUOenrNV1OYdxGE5qgvIRwwU,351
|
200
|
-
strawberry/types/arguments.py,sha256=
|
198
|
+
strawberry/types/arguments.py,sha256=DVouyH70uvTcFP3PmRzo8QdMThoqXdigJbWE9Lgn5pU,9849
|
201
199
|
strawberry/types/auto.py,sha256=WZ2cQAI8nREUigBzpzFqIKGjJ_C2VqpAPNe8vPjTciM,3007
|
202
200
|
strawberry/types/base.py,sha256=tZSqxtrxXa1Y964HS2uakCbCgLyGO9A4WpODiegWzF8,15122
|
203
201
|
strawberry/types/cast.py,sha256=fx86MkLW77GIximBAwUk5vZxSGwDqUA6XicXvz8EXwQ,916
|
@@ -207,14 +205,14 @@ strawberry/types/field.py,sha256=vxb7JvkHfRmDCYsjhDmVnO2lMbtSOteQm3jQUeSFu6g,216
|
|
207
205
|
strawberry/types/fields/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
208
206
|
strawberry/types/fields/resolver.py,sha256=b6lxfw6AMOUFWm7vs7a9KzNkpR8b_S110DoIosrrWDQ,14679
|
209
207
|
strawberry/types/graphql.py,sha256=gXKzawwKiow7hvoJhq5ApNJOMUCnKmvTiHaKY5CK1Lw,867
|
210
|
-
strawberry/types/info.py,sha256=
|
208
|
+
strawberry/types/info.py,sha256=V3DQMd97tkWSdPIhp7HcelQ2h94-HSCI5zJ7cRO7i58,4907
|
211
209
|
strawberry/types/lazy_type.py,sha256=dlP9VcMjZc9sdgriiQGzOZa0TToB6Ee7zpIP8h7TLC0,5079
|
212
210
|
strawberry/types/maybe.py,sha256=Zdv4pAJwgUmaFNU8WKlwjk50qwgYEzT90WteURZBzAo,1174
|
213
211
|
strawberry/types/mutation.py,sha256=cg-_O2WWnZ-GSwOIv0toSdxlGeY2lhBBxZ24AifJuSM,11978
|
214
212
|
strawberry/types/nodes.py,sha256=RwZB43OT9BS3Cqjgq4AazqOfyq_y0GD2ysC86EDBv5U,5134
|
215
213
|
strawberry/types/object_type.py,sha256=SZOzxaS318079G-pr-1PM5iMoTddxdw8KD4cI67IhzI,15579
|
216
214
|
strawberry/types/private.py,sha256=DhJs50XVGtOXlxWZFkRpMxQ5_6oki0-x_WQsV1bGUxk,518
|
217
|
-
strawberry/types/scalar.py,sha256=
|
215
|
+
strawberry/types/scalar.py,sha256=vUWGwAYgcfY26jQUdBJ1tGOvrBq92V0p9L8AWXM7bkk,6384
|
218
216
|
strawberry/types/type_resolver.py,sha256=fH2ZOK4dAGgu8AMPi-JAXe_kEAbvvw2MCYXqbpx-kTc,6529
|
219
217
|
strawberry/types/union.py,sha256=rwZoJcMdUxJBlYMwx3ONByv6BylhvXT0Bflem6xzMM4,10090
|
220
218
|
strawberry/types/unset.py,sha256=7DVK-WWxVLo41agvavTvIbphE42BmY8UpGolXfasIvw,1682
|
@@ -231,8 +229,8 @@ strawberry/utils/logging.py,sha256=U1cseHGquN09YFhFmRkiphfASKCyK0HUZREImPgVb0c,7
|
|
231
229
|
strawberry/utils/operation.py,sha256=s7ajvLg_q6v2mg47kEMQPjO_J-XluMKTCwo4d47mGvE,1195
|
232
230
|
strawberry/utils/str_converters.py,sha256=-eH1Cl16IO_wrBlsGM-km4IY0IKsjhjnSNGRGOwQjVM,897
|
233
231
|
strawberry/utils/typing.py,sha256=SDvX-Du-9HAV3-XXjqi7Q5f5qPDDFd_gASIITiwBQT4,14073
|
234
|
-
strawberry_graphql-0.
|
235
|
-
strawberry_graphql-0.
|
236
|
-
strawberry_graphql-0.
|
237
|
-
strawberry_graphql-0.
|
238
|
-
strawberry_graphql-0.
|
232
|
+
strawberry_graphql-0.270.0.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
|
233
|
+
strawberry_graphql-0.270.0.dist-info/METADATA,sha256=YwlJxcyaBIuozms-Yes8UmLXO5GFIlFUD2UjHatXNmQ,7679
|
234
|
+
strawberry_graphql-0.270.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
235
|
+
strawberry_graphql-0.270.0.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
|
236
|
+
strawberry_graphql-0.270.0.dist-info/RECORD,,
|
@@ -1,46 +0,0 @@
|
|
1
|
-
from typing import Union
|
2
|
-
|
3
|
-
from graphql.execution import ExecutionContext as GraphQLExecutionContext
|
4
|
-
from graphql.execution import ExecutionResult as GraphQLExecutionResult
|
5
|
-
from graphql.execution import execute, subscribe
|
6
|
-
|
7
|
-
from strawberry.types import ExecutionResult
|
8
|
-
|
9
|
-
try:
|
10
|
-
from graphql import (
|
11
|
-
ExperimentalIncrementalExecutionResults as GraphQLIncrementalExecutionResults,
|
12
|
-
)
|
13
|
-
from graphql.execution import experimental_execute_incrementally
|
14
|
-
from graphql.type.directives import (
|
15
|
-
GraphQLDeferDirective,
|
16
|
-
GraphQLStreamDirective,
|
17
|
-
)
|
18
|
-
|
19
|
-
incremental_execution_directives = (
|
20
|
-
GraphQLDeferDirective,
|
21
|
-
GraphQLStreamDirective,
|
22
|
-
)
|
23
|
-
|
24
|
-
except ImportError:
|
25
|
-
GraphQLIncrementalExecutionResults = type(None)
|
26
|
-
|
27
|
-
incremental_execution_directives = []
|
28
|
-
experimental_execute_incrementally = None
|
29
|
-
|
30
|
-
|
31
|
-
# TODO: give this a better name, maybe also a better place
|
32
|
-
ResultType = Union[
|
33
|
-
GraphQLExecutionResult,
|
34
|
-
GraphQLIncrementalExecutionResults,
|
35
|
-
ExecutionResult,
|
36
|
-
]
|
37
|
-
|
38
|
-
__all__ = [
|
39
|
-
"GraphQLExecutionContext",
|
40
|
-
"GraphQLIncrementalExecutionResults",
|
41
|
-
"ResultType",
|
42
|
-
"execute",
|
43
|
-
"experimental_execute_incrementally",
|
44
|
-
"incremental_execution_directives",
|
45
|
-
"subscribe",
|
46
|
-
]
|
strawberry/streamable.py
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
from collections.abc import AsyncGenerator
|
2
|
-
from typing import Annotated, TypeVar
|
3
|
-
|
4
|
-
|
5
|
-
class StrawberryStreamable: ...
|
6
|
-
|
7
|
-
|
8
|
-
T = TypeVar("T")
|
9
|
-
|
10
|
-
Streamable = Annotated[AsyncGenerator[T, None], StrawberryStreamable()]
|
11
|
-
"""Represents a list that can be streamed using @stream.
|
12
|
-
|
13
|
-
Example:
|
14
|
-
|
15
|
-
```python
|
16
|
-
import strawberry
|
17
|
-
from dataclasses import dataclass
|
18
|
-
|
19
|
-
|
20
|
-
@strawberry.type
|
21
|
-
class Comment:
|
22
|
-
id: strawberry.ID
|
23
|
-
content: str
|
24
|
-
|
25
|
-
|
26
|
-
@strawberry.type
|
27
|
-
class Article:
|
28
|
-
@strawberry.field
|
29
|
-
@staticmethod
|
30
|
-
async def comments() -> strawberry.Streamable[Comment]:
|
31
|
-
for comment in fetch_comments():
|
32
|
-
yield comment
|
33
|
-
```
|
34
|
-
"""
|
35
|
-
|
36
|
-
__all__ = ["Streamable"]
|
{strawberry_graphql-0.269.0.dev1746905409.dist-info → strawberry_graphql-0.270.0.dist-info}/LICENSE
RENAMED
File without changes
|
{strawberry_graphql-0.269.0.dev1746905409.dist-info → strawberry_graphql-0.270.0.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|