strawberry-graphql 0.283.0__py3-none-any.whl → 0.284.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of strawberry-graphql might be problematic. Click here for more details.
- strawberry/aiohttp/test/client.py +8 -15
- strawberry/aiohttp/views.py +12 -15
- strawberry/annotation.py +19 -23
- strawberry/asgi/__init__.py +18 -17
- strawberry/asgi/test/client.py +6 -6
- strawberry/chalice/views.py +6 -6
- strawberry/channels/handlers/base.py +7 -8
- strawberry/channels/handlers/http_handler.py +18 -20
- strawberry/channels/handlers/ws_handler.py +10 -12
- strawberry/channels/router.py +3 -4
- strawberry/channels/testing.py +7 -9
- strawberry/cli/commands/codegen.py +7 -7
- strawberry/cli/commands/schema_codegen.py +1 -2
- strawberry/cli/commands/upgrade/__init__.py +1 -3
- strawberry/cli/commands/upgrade/_run_codemod.py +2 -2
- strawberry/codegen/plugins/print_operation.py +2 -2
- strawberry/codegen/plugins/python.py +2 -2
- strawberry/codegen/query_codegen.py +20 -30
- strawberry/codegen/types.py +32 -32
- strawberry/codemods/annotated_unions.py +2 -2
- strawberry/dataloader.py +28 -24
- strawberry/directive.py +6 -7
- strawberry/django/test/client.py +3 -3
- strawberry/django/views.py +16 -19
- strawberry/exceptions/__init__.py +4 -4
- strawberry/exceptions/conflicting_arguments.py +2 -2
- strawberry/exceptions/duplicated_type_name.py +4 -4
- strawberry/exceptions/exception.py +3 -3
- strawberry/exceptions/handler.py +8 -7
- strawberry/exceptions/invalid_argument_type.py +2 -2
- strawberry/exceptions/invalid_superclass_interface.py +2 -2
- strawberry/exceptions/invalid_union_type.py +4 -4
- strawberry/exceptions/missing_arguments_annotations.py +2 -2
- strawberry/exceptions/missing_dependencies.py +2 -4
- strawberry/exceptions/missing_field_annotation.py +2 -2
- strawberry/exceptions/missing_return_annotation.py +2 -2
- strawberry/exceptions/object_is_not_a_class.py +2 -2
- strawberry/exceptions/object_is_not_an_enum.py +2 -2
- strawberry/exceptions/permission_fail_silently_requires_optional.py +2 -2
- strawberry/exceptions/private_strawberry_field.py +2 -2
- strawberry/exceptions/scalar_already_registered.py +2 -2
- strawberry/exceptions/syntax.py +3 -3
- strawberry/exceptions/unresolved_field_type.py +2 -2
- strawberry/exceptions/utils/source_finder.py +25 -25
- strawberry/experimental/pydantic/_compat.py +8 -7
- strawberry/experimental/pydantic/conversion.py +2 -2
- strawberry/experimental/pydantic/conversion_types.py +2 -2
- strawberry/experimental/pydantic/error_type.py +10 -12
- strawberry/experimental/pydantic/fields.py +9 -15
- strawberry/experimental/pydantic/object_type.py +15 -23
- strawberry/experimental/pydantic/utils.py +1 -2
- strawberry/ext/mypy_plugin.py +12 -14
- strawberry/extensions/base_extension.py +2 -1
- strawberry/extensions/context.py +13 -18
- strawberry/extensions/directives.py +3 -1
- strawberry/extensions/field_extension.py +4 -4
- strawberry/extensions/max_aliases.py +1 -3
- strawberry/extensions/parser_cache.py +1 -2
- strawberry/extensions/query_depth_limiter.py +18 -14
- strawberry/extensions/runner.py +2 -2
- strawberry/extensions/tracing/apollo.py +3 -3
- strawberry/extensions/tracing/datadog.py +3 -3
- strawberry/extensions/tracing/opentelemetry.py +6 -8
- strawberry/extensions/tracing/utils.py +3 -1
- strawberry/extensions/utils.py +2 -2
- strawberry/extensions/validation_cache.py +1 -2
- strawberry/fastapi/context.py +6 -6
- strawberry/fastapi/router.py +33 -36
- strawberry/federation/argument.py +4 -5
- strawberry/federation/enum.py +18 -21
- strawberry/federation/field.py +94 -97
- strawberry/federation/object_type.py +56 -58
- strawberry/federation/scalar.py +27 -35
- strawberry/federation/schema.py +15 -16
- strawberry/federation/schema_directive.py +7 -6
- strawberry/federation/schema_directives.py +11 -11
- strawberry/federation/union.py +4 -4
- strawberry/flask/views.py +10 -11
- strawberry/http/__init__.py +14 -14
- strawberry/http/async_base_view.py +23 -28
- strawberry/http/base.py +11 -12
- strawberry/http/ides.py +2 -3
- strawberry/http/sync_base_view.py +11 -13
- strawberry/http/types.py +3 -3
- strawberry/litestar/controller.py +40 -35
- strawberry/permission.py +4 -6
- strawberry/printer/ast_from_value.py +3 -5
- strawberry/printer/printer.py +8 -13
- strawberry/quart/views.py +12 -14
- strawberry/relay/exceptions.py +4 -4
- strawberry/relay/fields.py +33 -32
- strawberry/relay/types.py +31 -34
- strawberry/relay/utils.py +2 -2
- strawberry/resolvers.py +2 -1
- strawberry/sanic/context.py +1 -0
- strawberry/sanic/utils.py +3 -3
- strawberry/sanic/views.py +11 -14
- strawberry/scalars.py +2 -2
- strawberry/schema/_graphql_core.py +5 -5
- strawberry/schema/base.py +32 -33
- strawberry/schema/compat.py +9 -9
- strawberry/schema/config.py +5 -2
- strawberry/schema/exceptions.py +1 -3
- strawberry/schema/name_converter.py +6 -6
- strawberry/schema/schema.py +55 -60
- strawberry/schema/schema_converter.py +27 -22
- strawberry/schema/types/base_scalars.py +1 -1
- strawberry/schema/types/concrete_type.py +5 -5
- strawberry/schema_codegen/__init__.py +3 -3
- strawberry/schema_directive.py +7 -6
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +5 -6
- strawberry/subscriptions/protocols/graphql_transport_ws/types.py +20 -20
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +5 -6
- strawberry/subscriptions/protocols/graphql_ws/types.py +14 -14
- strawberry/test/client.py +18 -18
- strawberry/tools/create_type.py +2 -3
- strawberry/types/arguments.py +25 -26
- strawberry/types/auto.py +3 -4
- strawberry/types/base.py +25 -27
- strawberry/types/enum.py +22 -25
- strawberry/types/execution.py +14 -15
- strawberry/types/field.py +108 -108
- strawberry/types/fields/resolver.py +19 -21
- strawberry/types/info.py +5 -11
- strawberry/types/lazy_type.py +2 -3
- strawberry/types/maybe.py +12 -3
- strawberry/types/mutation.py +115 -118
- strawberry/types/nodes.py +2 -2
- strawberry/types/object_type.py +43 -63
- strawberry/types/scalar.py +37 -43
- strawberry/types/union.py +12 -14
- strawberry/utils/aio.py +12 -9
- strawberry/utils/await_maybe.py +3 -3
- strawberry/utils/deprecations.py +2 -2
- strawberry/utils/importer.py +1 -2
- strawberry/utils/inspect.py +4 -6
- strawberry/utils/logging.py +2 -2
- strawberry/utils/operation.py +4 -4
- strawberry/utils/typing.py +18 -83
- {strawberry_graphql-0.283.0.dist-info → strawberry_graphql-0.284.3.dist-info}/METADATA +2 -2
- strawberry_graphql-0.284.3.dist-info/RECORD +243 -0
- strawberry/utils/dataclasses.py +0 -37
- strawberry_graphql-0.283.0.dist-info/RECORD +0 -244
- {strawberry_graphql-0.283.0.dist-info → strawberry_graphql-0.284.3.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.283.0.dist-info → strawberry_graphql-0.284.3.dist-info}/entry_points.txt +0 -0
- {strawberry_graphql-0.283.0.dist-info → strawberry_graphql-0.284.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
|
-
from typing import
|
|
5
|
-
TYPE_CHECKING,
|
|
6
|
-
Any,
|
|
7
|
-
Optional,
|
|
8
|
-
)
|
|
4
|
+
from typing import Any
|
|
9
5
|
|
|
10
6
|
from strawberry.test.client import BaseGraphQLTestClient, Response
|
|
11
7
|
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from collections.abc import Mapping
|
|
14
|
-
|
|
15
8
|
|
|
16
9
|
class GraphQLTestClient(BaseGraphQLTestClient):
|
|
17
10
|
async def query(
|
|
18
11
|
self,
|
|
19
12
|
query: str,
|
|
20
|
-
variables:
|
|
21
|
-
headers:
|
|
22
|
-
asserts_errors:
|
|
23
|
-
files:
|
|
24
|
-
assert_no_errors:
|
|
13
|
+
variables: dict[str, Any] | None = None,
|
|
14
|
+
headers: dict[str, object] | None = None,
|
|
15
|
+
asserts_errors: bool | None = None,
|
|
16
|
+
files: dict[str, object] | None = None,
|
|
17
|
+
assert_no_errors: bool | None = True,
|
|
25
18
|
) -> Response:
|
|
26
19
|
body = self._build_body(query, variables, files)
|
|
27
20
|
|
|
@@ -54,8 +47,8 @@ class GraphQLTestClient(BaseGraphQLTestClient):
|
|
|
54
47
|
async def request(
|
|
55
48
|
self,
|
|
56
49
|
body: dict[str, object],
|
|
57
|
-
headers:
|
|
58
|
-
files:
|
|
50
|
+
headers: dict[str, object] | None = None,
|
|
51
|
+
files: dict[str, object] | None = None,
|
|
59
52
|
) -> Any:
|
|
60
53
|
return await self._client.post(
|
|
61
54
|
self.url,
|
strawberry/aiohttp/views.py
CHANGED
|
@@ -6,15 +6,12 @@ from datetime import timedelta
|
|
|
6
6
|
from json.decoder import JSONDecodeError
|
|
7
7
|
from typing import (
|
|
8
8
|
TYPE_CHECKING,
|
|
9
|
-
|
|
10
|
-
Optional,
|
|
11
|
-
Union,
|
|
9
|
+
TypeGuard,
|
|
12
10
|
)
|
|
13
|
-
from typing_extensions import TypeGuard
|
|
14
11
|
|
|
12
|
+
from aiohttp import ClientConnectionResetError, http, web
|
|
15
13
|
from lia import AiohttpHTTPRequestAdapter, HTTPException
|
|
16
14
|
|
|
17
|
-
from aiohttp import ClientConnectionResetError, http, web
|
|
18
15
|
from strawberry.http.async_base_view import (
|
|
19
16
|
AsyncBaseHTTPView,
|
|
20
17
|
AsyncWebSocketAdapter,
|
|
@@ -31,7 +28,7 @@ from strawberry.http.typevars import (
|
|
|
31
28
|
from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
|
|
32
29
|
|
|
33
30
|
if TYPE_CHECKING:
|
|
34
|
-
from collections.abc import AsyncGenerator, Mapping, Sequence
|
|
31
|
+
from collections.abc import AsyncGenerator, Callable, Mapping, Sequence
|
|
35
32
|
|
|
36
33
|
from strawberry.http import GraphQLHTTPResponse
|
|
37
34
|
from strawberry.http.ides import GraphQL_IDE
|
|
@@ -73,7 +70,7 @@ class AiohttpWebSocketAdapter(AsyncWebSocketAdapter):
|
|
|
73
70
|
class GraphQLView(
|
|
74
71
|
AsyncBaseHTTPView[
|
|
75
72
|
web.Request,
|
|
76
|
-
|
|
73
|
+
web.Response | web.StreamResponse,
|
|
77
74
|
web.Response,
|
|
78
75
|
web.Request,
|
|
79
76
|
web.WebSocketResponse,
|
|
@@ -87,13 +84,13 @@ class GraphQLView(
|
|
|
87
84
|
|
|
88
85
|
allow_queries_via_get = True
|
|
89
86
|
request_adapter_class = AiohttpHTTPRequestAdapter
|
|
90
|
-
websocket_adapter_class = AiohttpWebSocketAdapter
|
|
87
|
+
websocket_adapter_class = AiohttpWebSocketAdapter # type: ignore
|
|
91
88
|
|
|
92
89
|
def __init__(
|
|
93
90
|
self,
|
|
94
91
|
schema: BaseSchema,
|
|
95
|
-
graphiql:
|
|
96
|
-
graphql_ide:
|
|
92
|
+
graphiql: bool | None = None,
|
|
93
|
+
graphql_ide: GraphQL_IDE | None = "graphiql",
|
|
97
94
|
allow_queries_via_get: bool = True,
|
|
98
95
|
keep_alive: bool = True,
|
|
99
96
|
keep_alive_interval: float = 1,
|
|
@@ -132,12 +129,12 @@ class GraphQLView(
|
|
|
132
129
|
ws = web.WebSocketResponse(protocols=self.subscription_protocols)
|
|
133
130
|
return ws.can_prepare(request).ok
|
|
134
131
|
|
|
135
|
-
async def pick_websocket_subprotocol(self, request: web.Request) ->
|
|
132
|
+
async def pick_websocket_subprotocol(self, request: web.Request) -> str | None:
|
|
136
133
|
ws = web.WebSocketResponse(protocols=self.subscription_protocols)
|
|
137
134
|
return ws.can_prepare(request).protocol
|
|
138
135
|
|
|
139
136
|
async def create_websocket_response(
|
|
140
|
-
self, request: web.Request, subprotocol:
|
|
137
|
+
self, request: web.Request, subprotocol: str | None
|
|
141
138
|
) -> web.WebSocketResponse:
|
|
142
139
|
protocols = [subprotocol] if subprotocol else []
|
|
143
140
|
ws = web.WebSocketResponse(protocols=protocols)
|
|
@@ -153,17 +150,17 @@ class GraphQLView(
|
|
|
153
150
|
status=e.status_code,
|
|
154
151
|
)
|
|
155
152
|
|
|
156
|
-
async def get_root_value(self, request: web.Request) ->
|
|
153
|
+
async def get_root_value(self, request: web.Request) -> RootValue | None:
|
|
157
154
|
return None
|
|
158
155
|
|
|
159
156
|
async def get_context(
|
|
160
|
-
self, request: web.Request, response:
|
|
157
|
+
self, request: web.Request, response: web.Response | web.WebSocketResponse
|
|
161
158
|
) -> Context:
|
|
162
159
|
return {"request": request, "response": response} # type: ignore
|
|
163
160
|
|
|
164
161
|
def create_response(
|
|
165
162
|
self,
|
|
166
|
-
response_data:
|
|
163
|
+
response_data: GraphQLHTTPResponse | list[GraphQLHTTPResponse],
|
|
167
164
|
sub_response: web.Response,
|
|
168
165
|
) -> web.Response:
|
|
169
166
|
sub_response.text = self.encode_json(response_data)
|
strawberry/annotation.py
CHANGED
|
@@ -5,17 +5,19 @@ import typing
|
|
|
5
5
|
import warnings
|
|
6
6
|
from collections import abc
|
|
7
7
|
from enum import Enum
|
|
8
|
+
from types import UnionType
|
|
8
9
|
from typing import (
|
|
9
10
|
TYPE_CHECKING,
|
|
10
11
|
Annotated,
|
|
11
12
|
Any,
|
|
12
13
|
ForwardRef,
|
|
13
|
-
Optional,
|
|
14
14
|
TypeVar,
|
|
15
15
|
Union,
|
|
16
16
|
cast,
|
|
17
|
+
get_args,
|
|
18
|
+
get_origin,
|
|
17
19
|
)
|
|
18
|
-
from typing_extensions import Self
|
|
20
|
+
from typing_extensions import Self
|
|
19
21
|
|
|
20
22
|
from strawberry.streamable import StrawberryStreamable
|
|
21
23
|
from strawberry.types.base import (
|
|
@@ -58,14 +60,14 @@ class StrawberryAnnotation:
|
|
|
58
60
|
|
|
59
61
|
def __init__(
|
|
60
62
|
self,
|
|
61
|
-
annotation:
|
|
63
|
+
annotation: object | str,
|
|
62
64
|
*,
|
|
63
|
-
namespace:
|
|
65
|
+
namespace: dict[str, Any] | None = None,
|
|
64
66
|
) -> None:
|
|
65
67
|
self.raw_annotation = annotation
|
|
66
68
|
self.namespace = namespace
|
|
67
69
|
|
|
68
|
-
self.__resolve_cache__:
|
|
70
|
+
self.__resolve_cache__: StrawberryType | type | None = None
|
|
69
71
|
|
|
70
72
|
def __eq__(self, other: object) -> bool:
|
|
71
73
|
if not isinstance(other, StrawberryAnnotation):
|
|
@@ -78,8 +80,8 @@ class StrawberryAnnotation:
|
|
|
78
80
|
|
|
79
81
|
@staticmethod
|
|
80
82
|
def from_annotation(
|
|
81
|
-
annotation: object, namespace:
|
|
82
|
-
) ->
|
|
83
|
+
annotation: object, namespace: dict[str, Any] | None = None
|
|
84
|
+
) -> StrawberryAnnotation | None:
|
|
83
85
|
if annotation is None:
|
|
84
86
|
return None
|
|
85
87
|
|
|
@@ -88,7 +90,7 @@ class StrawberryAnnotation:
|
|
|
88
90
|
return annotation
|
|
89
91
|
|
|
90
92
|
@property
|
|
91
|
-
def annotation(self) ->
|
|
93
|
+
def annotation(self) -> object | str:
|
|
92
94
|
"""Return evaluated type on success or fallback to raw (string) annotation."""
|
|
93
95
|
try:
|
|
94
96
|
return self.evaluate()
|
|
@@ -98,7 +100,7 @@ class StrawberryAnnotation:
|
|
|
98
100
|
return self.raw_annotation
|
|
99
101
|
|
|
100
102
|
@annotation.setter
|
|
101
|
-
def annotation(self, value:
|
|
103
|
+
def annotation(self, value: object | str) -> None:
|
|
102
104
|
self.raw_annotation = value
|
|
103
105
|
|
|
104
106
|
self.__resolve_cache__ = None
|
|
@@ -128,8 +130,8 @@ class StrawberryAnnotation:
|
|
|
128
130
|
def resolve(
|
|
129
131
|
self,
|
|
130
132
|
*,
|
|
131
|
-
type_definition:
|
|
132
|
-
) ->
|
|
133
|
+
type_definition: StrawberryObjectDefinition | None = None,
|
|
134
|
+
) -> StrawberryType | type:
|
|
133
135
|
"""Return resolved (transformed) annotation."""
|
|
134
136
|
if (resolved := self.__resolve_cache__) is None:
|
|
135
137
|
resolved = self._resolve()
|
|
@@ -158,11 +160,11 @@ class StrawberryAnnotation:
|
|
|
158
160
|
|
|
159
161
|
return resolved
|
|
160
162
|
|
|
161
|
-
def _resolve(self) ->
|
|
163
|
+
def _resolve(self) -> StrawberryType | type:
|
|
162
164
|
evaled_type = cast("Any", self.evaluate())
|
|
163
165
|
return self._resolve_evaled_type(evaled_type)
|
|
164
166
|
|
|
165
|
-
def _resolve_evaled_type(self, evaled_type: Any) ->
|
|
167
|
+
def _resolve_evaled_type(self, evaled_type: Any) -> StrawberryType | type:
|
|
166
168
|
if is_private(evaled_type):
|
|
167
169
|
return evaled_type
|
|
168
170
|
|
|
@@ -244,7 +246,7 @@ class StrawberryAnnotation:
|
|
|
244
246
|
# passed as we can safely use `Union` for both optional types
|
|
245
247
|
# (e.g. `Optional[str]`) and optional unions (e.g.
|
|
246
248
|
# `Optional[Union[TypeA, TypeB]]`)
|
|
247
|
-
child_type = Union[non_optional_types] # type: ignore
|
|
249
|
+
child_type = Union[non_optional_types] # type: ignore # noqa: UP007
|
|
248
250
|
|
|
249
251
|
of_type = StrawberryAnnotation(
|
|
250
252
|
annotation=child_type,
|
|
@@ -321,7 +323,7 @@ class StrawberryAnnotation:
|
|
|
321
323
|
return issubclass(annotation, Enum)
|
|
322
324
|
|
|
323
325
|
@classmethod
|
|
324
|
-
def _is_type_generic(cls, type_:
|
|
326
|
+
def _is_type_generic(cls, type_: StrawberryType | type) -> bool:
|
|
325
327
|
"""Returns True if `resolver_type` is generic else False."""
|
|
326
328
|
from strawberry.types.base import StrawberryType
|
|
327
329
|
|
|
@@ -413,16 +415,10 @@ class StrawberryAnnotation:
|
|
|
413
415
|
"""Returns True if annotation is a Union."""
|
|
414
416
|
# this check is needed because unions declared with the new syntax `A | B`
|
|
415
417
|
# don't have a `__origin__` property on them, but they are instances of
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
from types import UnionType
|
|
419
|
-
|
|
420
|
-
if isinstance(annotation, UnionType):
|
|
421
|
-
return True
|
|
418
|
+
if isinstance(annotation, UnionType):
|
|
419
|
+
return True
|
|
422
420
|
|
|
423
421
|
# unions declared as Union[A, B] fall through to this check
|
|
424
|
-
# even on python 3.10+
|
|
425
|
-
|
|
426
422
|
annotation_origin = getattr(annotation, "__origin__", None)
|
|
427
423
|
|
|
428
424
|
if annotation_origin is typing.Union:
|
strawberry/asgi/__init__.py
CHANGED
|
@@ -5,11 +5,8 @@ from datetime import timedelta
|
|
|
5
5
|
from json import JSONDecodeError
|
|
6
6
|
from typing import (
|
|
7
7
|
TYPE_CHECKING,
|
|
8
|
-
|
|
9
|
-
Optional,
|
|
10
|
-
Union,
|
|
8
|
+
TypeGuard,
|
|
11
9
|
)
|
|
12
|
-
from typing_extensions import TypeGuard
|
|
13
10
|
|
|
14
11
|
from lia import HTTPException, StarletteRequestAdapter
|
|
15
12
|
from starlette import status
|
|
@@ -38,7 +35,13 @@ from strawberry.http.typevars import (
|
|
|
38
35
|
from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
|
|
39
36
|
|
|
40
37
|
if TYPE_CHECKING:
|
|
41
|
-
from collections.abc import
|
|
38
|
+
from collections.abc import (
|
|
39
|
+
AsyncGenerator,
|
|
40
|
+
AsyncIterator,
|
|
41
|
+
Callable,
|
|
42
|
+
Mapping,
|
|
43
|
+
Sequence,
|
|
44
|
+
)
|
|
42
45
|
|
|
43
46
|
from starlette.types import Receive, Scope, Send
|
|
44
47
|
|
|
@@ -93,13 +96,13 @@ class GraphQL(
|
|
|
93
96
|
):
|
|
94
97
|
allow_queries_via_get = True
|
|
95
98
|
request_adapter_class = StarletteRequestAdapter
|
|
96
|
-
websocket_adapter_class = ASGIWebSocketAdapter
|
|
99
|
+
websocket_adapter_class = ASGIWebSocketAdapter # type: ignore
|
|
97
100
|
|
|
98
101
|
def __init__(
|
|
99
102
|
self,
|
|
100
103
|
schema: BaseSchema,
|
|
101
|
-
graphiql:
|
|
102
|
-
graphql_ide:
|
|
104
|
+
graphiql: bool | None = None,
|
|
105
|
+
graphql_ide: GraphQL_IDE | None = "graphiql",
|
|
103
106
|
allow_queries_via_get: bool = True,
|
|
104
107
|
keep_alive: bool = False,
|
|
105
108
|
keep_alive_interval: float = 1,
|
|
@@ -144,19 +147,17 @@ class GraphQL(
|
|
|
144
147
|
else: # pragma: no cover
|
|
145
148
|
raise ValueError("Unknown scope type: {!r}".format(scope["type"]))
|
|
146
149
|
|
|
147
|
-
async def get_root_value(
|
|
148
|
-
self, request: Union[Request, WebSocket]
|
|
149
|
-
) -> Optional[RootValue]:
|
|
150
|
+
async def get_root_value(self, request: Request | WebSocket) -> RootValue | None:
|
|
150
151
|
return None
|
|
151
152
|
|
|
152
153
|
async def get_context(
|
|
153
|
-
self, request:
|
|
154
|
+
self, request: Request | WebSocket, response: Response | WebSocket
|
|
154
155
|
) -> Context:
|
|
155
156
|
return {"request": request, "response": response} # type: ignore
|
|
156
157
|
|
|
157
158
|
async def get_sub_response(
|
|
158
159
|
self,
|
|
159
|
-
request:
|
|
160
|
+
request: Request | WebSocket,
|
|
160
161
|
) -> Response:
|
|
161
162
|
sub_response = Response()
|
|
162
163
|
sub_response.status_code = None # type: ignore
|
|
@@ -169,7 +170,7 @@ class GraphQL(
|
|
|
169
170
|
|
|
170
171
|
def create_response(
|
|
171
172
|
self,
|
|
172
|
-
response_data:
|
|
173
|
+
response_data: GraphQLHTTPResponse | list[GraphQLHTTPResponse],
|
|
173
174
|
sub_response: Response,
|
|
174
175
|
) -> Response:
|
|
175
176
|
response = Response(
|
|
@@ -205,18 +206,18 @@ class GraphQL(
|
|
|
205
206
|
)
|
|
206
207
|
|
|
207
208
|
def is_websocket_request(
|
|
208
|
-
self, request:
|
|
209
|
+
self, request: Request | WebSocket
|
|
209
210
|
) -> TypeGuard[WebSocket]:
|
|
210
211
|
return request.scope["type"] == "websocket"
|
|
211
212
|
|
|
212
|
-
async def pick_websocket_subprotocol(self, request: WebSocket) ->
|
|
213
|
+
async def pick_websocket_subprotocol(self, request: WebSocket) -> str | None:
|
|
213
214
|
protocols = request["subprotocols"]
|
|
214
215
|
intersection = set(protocols) & set(self.protocols)
|
|
215
216
|
sorted_intersection = sorted(intersection, key=protocols.index)
|
|
216
217
|
return next(iter(sorted_intersection), None)
|
|
217
218
|
|
|
218
219
|
async def create_websocket_response(
|
|
219
|
-
self, request: WebSocket, subprotocol:
|
|
220
|
+
self, request: WebSocket, subprotocol: str | None
|
|
220
221
|
) -> WebSocket:
|
|
221
222
|
await request.accept(subprotocol=subprotocol)
|
|
222
223
|
return request
|
strawberry/asgi/test/client.py
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
6
|
from strawberry.test import BaseGraphQLTestClient
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from collections.abc import Mapping
|
|
10
|
-
from
|
|
10
|
+
from typing import Literal
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class GraphQLTestClient(BaseGraphQLTestClient):
|
|
14
14
|
def _build_body(
|
|
15
15
|
self,
|
|
16
16
|
query: str,
|
|
17
|
-
variables:
|
|
18
|
-
files:
|
|
17
|
+
variables: dict[str, Mapping] | None = None,
|
|
18
|
+
files: dict[str, object] | None = None,
|
|
19
19
|
) -> dict[str, object]:
|
|
20
20
|
body: dict[str, object] = {"query": query}
|
|
21
21
|
|
|
@@ -36,8 +36,8 @@ class GraphQLTestClient(BaseGraphQLTestClient):
|
|
|
36
36
|
def request(
|
|
37
37
|
self,
|
|
38
38
|
body: dict[str, object],
|
|
39
|
-
headers:
|
|
40
|
-
files:
|
|
39
|
+
headers: dict[str, object] | None = None,
|
|
40
|
+
files: dict[str, object] | None = None,
|
|
41
41
|
) -> Any:
|
|
42
42
|
return self._client.post(
|
|
43
43
|
self.url,
|
strawberry/chalice/views.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
|
+
from chalice.app import Request, Response
|
|
6
7
|
from lia import ChaliceHTTPRequestAdapter, HTTPException
|
|
7
8
|
|
|
8
|
-
from chalice.app import Request, Response
|
|
9
9
|
from strawberry.http.sync_base_view import SyncBaseHTTPView
|
|
10
10
|
from strawberry.http.temporal_response import TemporalResponse
|
|
11
11
|
from strawberry.http.typevars import Context, RootValue
|
|
@@ -25,8 +25,8 @@ class GraphQLView(
|
|
|
25
25
|
def __init__(
|
|
26
26
|
self,
|
|
27
27
|
schema: BaseSchema,
|
|
28
|
-
graphiql:
|
|
29
|
-
graphql_ide:
|
|
28
|
+
graphiql: bool | None = None,
|
|
29
|
+
graphql_ide: GraphQL_IDE | None = "graphiql",
|
|
30
30
|
allow_queries_via_get: bool = True,
|
|
31
31
|
) -> None:
|
|
32
32
|
self.allow_queries_via_get = allow_queries_via_get
|
|
@@ -41,7 +41,7 @@ class GraphQLView(
|
|
|
41
41
|
else:
|
|
42
42
|
self.graphql_ide = graphql_ide
|
|
43
43
|
|
|
44
|
-
def get_root_value(self, request: Request) ->
|
|
44
|
+
def get_root_value(self, request: Request) -> RootValue | None:
|
|
45
45
|
return None
|
|
46
46
|
|
|
47
47
|
def render_graphql_ide(self, request: Request) -> Response:
|
|
@@ -58,7 +58,7 @@ class GraphQLView(
|
|
|
58
58
|
|
|
59
59
|
def create_response(
|
|
60
60
|
self,
|
|
61
|
-
response_data:
|
|
61
|
+
response_data: GraphQLHTTPResponse | list[GraphQLHTTPResponse],
|
|
62
62
|
sub_response: TemporalResponse,
|
|
63
63
|
) -> Response:
|
|
64
64
|
status_code = 200
|
|
@@ -2,13 +2,12 @@ import asyncio
|
|
|
2
2
|
import contextlib
|
|
3
3
|
import warnings
|
|
4
4
|
from collections import defaultdict
|
|
5
|
-
from collections.abc import AsyncGenerator, Awaitable, Sequence
|
|
5
|
+
from collections.abc import AsyncGenerator, Awaitable, Callable, Sequence
|
|
6
6
|
from typing import (
|
|
7
7
|
Any,
|
|
8
|
-
|
|
9
|
-
Optional,
|
|
8
|
+
Literal,
|
|
10
9
|
)
|
|
11
|
-
from typing_extensions import
|
|
10
|
+
from typing_extensions import Protocol, TypedDict
|
|
12
11
|
from weakref import WeakSet
|
|
13
12
|
|
|
14
13
|
from channels.consumer import AsyncConsumer
|
|
@@ -54,7 +53,7 @@ class ChannelsConsumer(AsyncConsumer):
|
|
|
54
53
|
"""Base channels async consumer."""
|
|
55
54
|
|
|
56
55
|
channel_name: str
|
|
57
|
-
channel_layer:
|
|
56
|
+
channel_layer: ChannelsLayer | None
|
|
58
57
|
channel_receive: Callable[[], Awaitable[dict]]
|
|
59
58
|
|
|
60
59
|
def __init__(self, *args: str, **kwargs: Any) -> None:
|
|
@@ -80,7 +79,7 @@ class ChannelsConsumer(AsyncConsumer):
|
|
|
80
79
|
self,
|
|
81
80
|
type: str,
|
|
82
81
|
*,
|
|
83
|
-
timeout:
|
|
82
|
+
timeout: float | None = None,
|
|
84
83
|
groups: Sequence[str] = (),
|
|
85
84
|
) -> AsyncGenerator[Any, None]:
|
|
86
85
|
"""Listen for messages sent to this consumer.
|
|
@@ -139,7 +138,7 @@ class ChannelsConsumer(AsyncConsumer):
|
|
|
139
138
|
self,
|
|
140
139
|
type: str,
|
|
141
140
|
*,
|
|
142
|
-
timeout:
|
|
141
|
+
timeout: float | None = None,
|
|
143
142
|
groups: Sequence[str] = (),
|
|
144
143
|
) -> AsyncGenerator[Any, None]:
|
|
145
144
|
"""Listen for messages sent to this consumer.
|
|
@@ -188,7 +187,7 @@ class ChannelsConsumer(AsyncConsumer):
|
|
|
188
187
|
await self.channel_layer.group_discard(group, self.channel_name)
|
|
189
188
|
|
|
190
189
|
async def _listen_to_channel_generator(
|
|
191
|
-
self, queue: asyncio.Queue, timeout:
|
|
190
|
+
self, queue: asyncio.Queue, timeout: float | None
|
|
192
191
|
) -> AsyncGenerator[Any, None]:
|
|
193
192
|
"""Generator for listen_to_channel method.
|
|
194
193
|
|
|
@@ -5,17 +5,17 @@ import json
|
|
|
5
5
|
import warnings
|
|
6
6
|
from functools import cached_property
|
|
7
7
|
from io import BytesIO
|
|
8
|
-
from typing import TYPE_CHECKING, Any,
|
|
9
|
-
from typing_extensions import
|
|
8
|
+
from typing import TYPE_CHECKING, Any, TypeGuard
|
|
9
|
+
from typing_extensions import assert_never
|
|
10
10
|
from urllib.parse import parse_qs
|
|
11
11
|
|
|
12
|
+
from channels.db import database_sync_to_async
|
|
13
|
+
from channels.generic.http import AsyncHttpConsumer
|
|
12
14
|
from django.conf import settings
|
|
13
15
|
from django.core.files import uploadhandler
|
|
14
16
|
from django.http.multipartparser import MultiPartParser
|
|
15
17
|
from lia import AsyncHTTPRequestAdapter, FormData, HTTPException, SyncHTTPRequestAdapter
|
|
16
18
|
|
|
17
|
-
from channels.db import database_sync_to_async
|
|
18
|
-
from channels.generic.http import AsyncHttpConsumer
|
|
19
19
|
from strawberry.http.async_base_view import AsyncBaseHTTPView
|
|
20
20
|
from strawberry.http.sync_base_view import SyncBaseHTTPView
|
|
21
21
|
from strawberry.http.temporal_response import TemporalResponse
|
|
@@ -25,7 +25,7 @@ from strawberry.types.unset import UNSET
|
|
|
25
25
|
from .base import ChannelsConsumer
|
|
26
26
|
|
|
27
27
|
if TYPE_CHECKING:
|
|
28
|
-
from collections.abc import AsyncGenerator, Mapping
|
|
28
|
+
from collections.abc import AsyncGenerator, Callable, Mapping
|
|
29
29
|
|
|
30
30
|
from strawberry.http import GraphQLHTTPResponse
|
|
31
31
|
from strawberry.http.ides import GraphQL_IDE
|
|
@@ -77,7 +77,7 @@ class ChannelsRequest:
|
|
|
77
77
|
return self.consumer.scope["method"].upper()
|
|
78
78
|
|
|
79
79
|
@property
|
|
80
|
-
def content_type(self) ->
|
|
80
|
+
def content_type(self) -> str | None:
|
|
81
81
|
return self.headers.get("content-type", None)
|
|
82
82
|
|
|
83
83
|
@cached_property
|
|
@@ -123,7 +123,7 @@ class BaseChannelsRequestAdapter:
|
|
|
123
123
|
return self.request.headers
|
|
124
124
|
|
|
125
125
|
@property
|
|
126
|
-
def content_type(self) ->
|
|
126
|
+
def content_type(self) -> str | None:
|
|
127
127
|
return self.request.content_type
|
|
128
128
|
|
|
129
129
|
@property
|
|
@@ -163,7 +163,7 @@ class SyncChannelsRequestAdapter(BaseChannelsRequestAdapter, SyncHTTPRequestAdap
|
|
|
163
163
|
return self.request.body
|
|
164
164
|
|
|
165
165
|
@property
|
|
166
|
-
def post_data(self) -> Mapping[str,
|
|
166
|
+
def post_data(self) -> Mapping[str, str | bytes]:
|
|
167
167
|
return self.request.form_data.form
|
|
168
168
|
|
|
169
169
|
@property
|
|
@@ -176,13 +176,13 @@ class SyncChannelsRequestAdapter(BaseChannelsRequestAdapter, SyncHTTPRequestAdap
|
|
|
176
176
|
|
|
177
177
|
class BaseGraphQLHTTPConsumer(ChannelsConsumer, AsyncHttpConsumer):
|
|
178
178
|
graphql_ide_html: str
|
|
179
|
-
graphql_ide:
|
|
179
|
+
graphql_ide: GraphQL_IDE | None = "graphiql"
|
|
180
180
|
|
|
181
181
|
def __init__(
|
|
182
182
|
self,
|
|
183
183
|
schema: BaseSchema,
|
|
184
|
-
graphiql:
|
|
185
|
-
graphql_ide:
|
|
184
|
+
graphiql: bool | None = None,
|
|
185
|
+
graphql_ide: GraphQL_IDE | None = "graphiql",
|
|
186
186
|
allow_queries_via_get: bool = True,
|
|
187
187
|
multipart_uploads_enabled: bool = False,
|
|
188
188
|
**kwargs: Any,
|
|
@@ -205,7 +205,7 @@ class BaseGraphQLHTTPConsumer(ChannelsConsumer, AsyncHttpConsumer):
|
|
|
205
205
|
|
|
206
206
|
def create_response(
|
|
207
207
|
self,
|
|
208
|
-
response_data:
|
|
208
|
+
response_data: GraphQLHTTPResponse | list[GraphQLHTTPResponse],
|
|
209
209
|
sub_response: TemporalResponse,
|
|
210
210
|
) -> ChannelsResponse:
|
|
211
211
|
return ChannelsResponse(
|
|
@@ -247,7 +247,7 @@ class GraphQLHTTPConsumer(
|
|
|
247
247
|
BaseGraphQLHTTPConsumer,
|
|
248
248
|
AsyncBaseHTTPView[
|
|
249
249
|
ChannelsRequest,
|
|
250
|
-
|
|
250
|
+
ChannelsResponse | MultipartChannelsResponse,
|
|
251
251
|
TemporalResponse,
|
|
252
252
|
ChannelsRequest,
|
|
253
253
|
TemporalResponse,
|
|
@@ -279,7 +279,7 @@ class GraphQLHTTPConsumer(
|
|
|
279
279
|
allow_queries_via_get: bool = True
|
|
280
280
|
request_adapter_class = ChannelsRequestAdapter
|
|
281
281
|
|
|
282
|
-
async def get_root_value(self, request: ChannelsRequest) ->
|
|
282
|
+
async def get_root_value(self, request: ChannelsRequest) -> RootValue | None:
|
|
283
283
|
return None # pragma: no cover
|
|
284
284
|
|
|
285
285
|
async def get_context(
|
|
@@ -322,13 +322,11 @@ class GraphQLHTTPConsumer(
|
|
|
322
322
|
) -> TypeGuard[ChannelsRequest]:
|
|
323
323
|
return False
|
|
324
324
|
|
|
325
|
-
async def pick_websocket_subprotocol(
|
|
326
|
-
self, request: ChannelsRequest
|
|
327
|
-
) -> Optional[str]:
|
|
325
|
+
async def pick_websocket_subprotocol(self, request: ChannelsRequest) -> str | None:
|
|
328
326
|
return None
|
|
329
327
|
|
|
330
328
|
async def create_websocket_response(
|
|
331
|
-
self, request: ChannelsRequest, subprotocol:
|
|
329
|
+
self, request: ChannelsRequest, subprotocol: str | None
|
|
332
330
|
) -> TemporalResponse:
|
|
333
331
|
raise NotImplementedError
|
|
334
332
|
|
|
@@ -353,7 +351,7 @@ class SyncGraphQLHTTPConsumer(
|
|
|
353
351
|
allow_queries_via_get: bool = True
|
|
354
352
|
request_adapter_class = SyncChannelsRequestAdapter
|
|
355
353
|
|
|
356
|
-
def get_root_value(self, request: ChannelsRequest) ->
|
|
354
|
+
def get_root_value(self, request: ChannelsRequest) -> RootValue | None:
|
|
357
355
|
return None # pragma: no cover
|
|
358
356
|
|
|
359
357
|
def get_context(
|
|
@@ -381,7 +379,7 @@ class SyncGraphQLHTTPConsumer(
|
|
|
381
379
|
self,
|
|
382
380
|
request: ChannelsRequest,
|
|
383
381
|
context: Context = UNSET,
|
|
384
|
-
root_value:
|
|
382
|
+
root_value: RootValue | None = UNSET,
|
|
385
383
|
) -> ChannelsResponse | MultipartChannelsResponse:
|
|
386
384
|
return super().run(request, context, root_value)
|
|
387
385
|
|