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,7 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections.abc import Callable
|
|
3
4
|
from enum import Enum
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
5
6
|
|
|
6
7
|
from strawberry.utils.await_maybe import AsyncIteratorOrIterator, AwaitableOrValue
|
|
7
8
|
|
strawberry/extensions/context.py
CHANGED
|
@@ -8,17 +8,14 @@ from asyncio import iscoroutinefunction
|
|
|
8
8
|
from typing import (
|
|
9
9
|
TYPE_CHECKING,
|
|
10
10
|
Any,
|
|
11
|
-
Callable,
|
|
12
11
|
NamedTuple,
|
|
13
|
-
Optional,
|
|
14
|
-
Union,
|
|
15
12
|
)
|
|
16
13
|
|
|
17
14
|
from strawberry.extensions import SchemaExtension
|
|
18
15
|
from strawberry.utils.await_maybe import AwaitableOrValue, await_maybe
|
|
19
16
|
|
|
20
17
|
if TYPE_CHECKING:
|
|
21
|
-
from collections.abc import AsyncIterator, Iterator
|
|
18
|
+
from collections.abc import AsyncIterator, Callable, Iterator
|
|
22
19
|
from types import TracebackType
|
|
23
20
|
|
|
24
21
|
from strawberry.extensions.base_extension import Hook
|
|
@@ -28,10 +25,8 @@ class WrappedHook(NamedTuple):
|
|
|
28
25
|
extension: SchemaExtension
|
|
29
26
|
hook: Callable[
|
|
30
27
|
...,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
contextlib.AbstractContextManager[None],
|
|
34
|
-
],
|
|
28
|
+
contextlib.AbstractAsyncContextManager[None]
|
|
29
|
+
| contextlib.AbstractContextManager[None],
|
|
35
30
|
]
|
|
36
31
|
is_async: bool
|
|
37
32
|
|
|
@@ -65,12 +60,12 @@ class ExtensionContextManagerBase:
|
|
|
65
60
|
if hook:
|
|
66
61
|
self.hooks.append(hook)
|
|
67
62
|
|
|
68
|
-
def get_hook(self, extension: SchemaExtension) ->
|
|
63
|
+
def get_hook(self, extension: SchemaExtension) -> WrappedHook | None:
|
|
69
64
|
on_start = getattr(extension, self.LEGACY_ENTER, None)
|
|
70
65
|
on_end = getattr(extension, self.LEGACY_EXIT, None)
|
|
71
66
|
|
|
72
67
|
is_legacy = on_start is not None or on_end is not None
|
|
73
|
-
hook_fn:
|
|
68
|
+
hook_fn: Hook | None = getattr(type(extension), self.HOOK_NAME)
|
|
74
69
|
hook_fn = hook_fn if hook_fn is not self.default_hook else None
|
|
75
70
|
if is_legacy and hook_fn is not None:
|
|
76
71
|
raise ValueError(
|
|
@@ -111,8 +106,8 @@ class ExtensionContextManagerBase:
|
|
|
111
106
|
@staticmethod
|
|
112
107
|
def from_legacy(
|
|
113
108
|
extension: SchemaExtension,
|
|
114
|
-
on_start:
|
|
115
|
-
on_end:
|
|
109
|
+
on_start: Callable[[], None] | None = None,
|
|
110
|
+
on_end: Callable[[], None] | None = None,
|
|
116
111
|
) -> WrappedHook:
|
|
117
112
|
if iscoroutinefunction(on_start) or iscoroutinefunction(on_end):
|
|
118
113
|
|
|
@@ -176,9 +171,9 @@ class ExtensionContextManagerBase:
|
|
|
176
171
|
|
|
177
172
|
def __exit__(
|
|
178
173
|
self,
|
|
179
|
-
exc_type:
|
|
180
|
-
exc_val:
|
|
181
|
-
exc_tb:
|
|
174
|
+
exc_type: type[BaseException] | None,
|
|
175
|
+
exc_val: BaseException | None,
|
|
176
|
+
exc_tb: TracebackType | None,
|
|
182
177
|
) -> None:
|
|
183
178
|
self.exit_stack.__exit__(exc_type, exc_val, exc_tb)
|
|
184
179
|
|
|
@@ -195,9 +190,9 @@ class ExtensionContextManagerBase:
|
|
|
195
190
|
|
|
196
191
|
async def __aexit__(
|
|
197
192
|
self,
|
|
198
|
-
exc_type:
|
|
199
|
-
exc_val:
|
|
200
|
-
exc_tb:
|
|
193
|
+
exc_type: type[BaseException] | None,
|
|
194
|
+
exc_val: BaseException | None,
|
|
195
|
+
exc_tb: TracebackType | None,
|
|
201
196
|
) -> None:
|
|
202
197
|
await self.async_exit_stack.__aexit__(exc_type, exc_val, exc_tb)
|
|
203
198
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
from strawberry.extensions import SchemaExtension
|
|
6
6
|
from strawberry.types.nodes import convert_arguments
|
|
7
7
|
from strawberry.utils.await_maybe import await_maybe
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
|
|
10
12
|
from graphql import DirectiveNode, GraphQLResolveInfo
|
|
11
13
|
|
|
12
14
|
from strawberry.directive import StrawberryDirective
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import itertools
|
|
4
|
-
from collections.abc import Awaitable
|
|
4
|
+
from collections.abc import Awaitable, Callable
|
|
5
5
|
from functools import cached_property
|
|
6
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
|
-
from
|
|
9
|
+
from typing import TypeAlias
|
|
10
10
|
|
|
11
11
|
from strawberry.types import Info
|
|
12
12
|
from strawberry.types.field import StrawberryField
|
|
@@ -69,7 +69,7 @@ def _get_async_resolvers(
|
|
|
69
69
|
|
|
70
70
|
def build_field_extension_resolvers(
|
|
71
71
|
field: StrawberryField,
|
|
72
|
-
) -> list[
|
|
72
|
+
) -> list[SyncExtensionResolver | AsyncExtensionResolver]:
|
|
73
73
|
"""Builds a list of resolvers for a field with extensions.
|
|
74
74
|
|
|
75
75
|
Verifies that all of the field extensions for a given field support
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Union
|
|
2
|
-
|
|
3
1
|
from graphql import (
|
|
4
2
|
ExecutableDefinitionNode,
|
|
5
3
|
FieldNode,
|
|
@@ -64,7 +62,7 @@ def create_validator(max_alias_count: int) -> type[ValidationRule]:
|
|
|
64
62
|
|
|
65
63
|
|
|
66
64
|
def count_fields_with_alias(
|
|
67
|
-
selection_set_owner:
|
|
65
|
+
selection_set_owner: ExecutableDefinitionNode | FieldNode | InlineFragmentNode,
|
|
68
66
|
) -> int:
|
|
69
67
|
if selection_set_owner.selection_set is None:
|
|
70
68
|
return 0
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from collections.abc import Iterator
|
|
2
2
|
from functools import lru_cache
|
|
3
|
-
from typing import Optional
|
|
4
3
|
|
|
5
4
|
from graphql.language.parser import parse
|
|
6
5
|
|
|
@@ -25,7 +24,7 @@ class ParserCache(SchemaExtension):
|
|
|
25
24
|
```
|
|
26
25
|
"""
|
|
27
26
|
|
|
28
|
-
def __init__(self, maxsize:
|
|
27
|
+
def __init__(self, maxsize: int | None = None) -> None:
|
|
29
28
|
"""Initialize the ParserCache.
|
|
30
29
|
|
|
31
30
|
Args:
|
|
@@ -28,12 +28,11 @@
|
|
|
28
28
|
from __future__ import annotations
|
|
29
29
|
|
|
30
30
|
import re
|
|
31
|
+
from collections.abc import Callable
|
|
31
32
|
from dataclasses import dataclass
|
|
32
33
|
from typing import (
|
|
33
34
|
TYPE_CHECKING,
|
|
34
|
-
|
|
35
|
-
Optional,
|
|
36
|
-
Union,
|
|
35
|
+
TypeAlias,
|
|
37
36
|
)
|
|
38
37
|
|
|
39
38
|
from graphql import GraphQLError
|
|
@@ -61,12 +60,17 @@ from strawberry.extensions.utils import is_introspection_key
|
|
|
61
60
|
if TYPE_CHECKING:
|
|
62
61
|
from collections.abc import Iterable
|
|
63
62
|
|
|
64
|
-
IgnoreType =
|
|
63
|
+
IgnoreType: TypeAlias = Callable[[str], bool] | re.Pattern | str
|
|
65
64
|
|
|
66
|
-
FieldArgumentType =
|
|
67
|
-
bool
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
FieldArgumentType: TypeAlias = (
|
|
66
|
+
bool
|
|
67
|
+
| int
|
|
68
|
+
| float
|
|
69
|
+
| str
|
|
70
|
+
| list["FieldArgumentType"]
|
|
71
|
+
| dict[str, "FieldArgumentType"]
|
|
72
|
+
)
|
|
73
|
+
FieldArgumentsType: TypeAlias = dict[str, FieldArgumentType]
|
|
70
74
|
|
|
71
75
|
|
|
72
76
|
@dataclass
|
|
@@ -99,8 +103,8 @@ class QueryDepthLimiter(AddValidationRules):
|
|
|
99
103
|
def __init__(
|
|
100
104
|
self,
|
|
101
105
|
max_depth: int,
|
|
102
|
-
callback:
|
|
103
|
-
should_ignore:
|
|
106
|
+
callback: Callable[[dict[str, int]], None] | None = None,
|
|
107
|
+
should_ignore: ShouldIgnoreType | None = None,
|
|
104
108
|
) -> None:
|
|
105
109
|
"""Initialize the QueryDepthLimiter.
|
|
106
110
|
|
|
@@ -122,8 +126,8 @@ class QueryDepthLimiter(AddValidationRules):
|
|
|
122
126
|
|
|
123
127
|
def create_validator(
|
|
124
128
|
max_depth: int,
|
|
125
|
-
should_ignore:
|
|
126
|
-
callback:
|
|
129
|
+
should_ignore: ShouldIgnoreType | None,
|
|
130
|
+
callback: Callable[[dict[str, int]], None] | None = None,
|
|
127
131
|
) -> type[ValidationRule]:
|
|
128
132
|
class DepthLimitValidator(ValidationRule):
|
|
129
133
|
def __init__(self, validation_context: ValidationContext) -> None:
|
|
@@ -218,7 +222,7 @@ def determine_depth(
|
|
|
218
222
|
max_depth: int,
|
|
219
223
|
context: ValidationContext,
|
|
220
224
|
operation_name: str,
|
|
221
|
-
should_ignore:
|
|
225
|
+
should_ignore: ShouldIgnoreType | None,
|
|
222
226
|
) -> int:
|
|
223
227
|
if depth_so_far > max_depth:
|
|
224
228
|
context.report_error(
|
|
@@ -288,7 +292,7 @@ def determine_depth(
|
|
|
288
292
|
raise TypeError(f"Depth crawler cannot handle: {node.kind}") # pragma: no cover
|
|
289
293
|
|
|
290
294
|
|
|
291
|
-
def is_ignored(node: FieldNode, ignore:
|
|
295
|
+
def is_ignored(node: FieldNode, ignore: list[IgnoreType] | None = None) -> bool:
|
|
292
296
|
if ignore is None:
|
|
293
297
|
return False
|
|
294
298
|
|
strawberry/extensions/runner.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
6
|
from strawberry.extensions.context import (
|
|
7
7
|
ExecutingContextManager,
|
|
@@ -23,7 +23,7 @@ class SchemaExtensionsRunner:
|
|
|
23
23
|
def __init__(
|
|
24
24
|
self,
|
|
25
25
|
execution_context: ExecutionContext,
|
|
26
|
-
extensions:
|
|
26
|
+
extensions: list[SchemaExtension] | None = None,
|
|
27
27
|
) -> None:
|
|
28
28
|
self.execution_context = execution_context
|
|
29
29
|
self.extensions = extensions or []
|
|
@@ -4,7 +4,7 @@ import dataclasses
|
|
|
4
4
|
import time
|
|
5
5
|
from datetime import datetime, timezone
|
|
6
6
|
from inspect import isawaitable
|
|
7
|
-
from typing import TYPE_CHECKING, Any
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
8
|
|
|
9
9
|
from strawberry.extensions import SchemaExtension
|
|
10
10
|
from strawberry.extensions.utils import get_path_from_info
|
|
@@ -12,7 +12,7 @@ from strawberry.extensions.utils import get_path_from_info
|
|
|
12
12
|
from .utils import should_skip_tracing
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
|
-
from collections.abc import Generator
|
|
15
|
+
from collections.abc import Callable, Generator
|
|
16
16
|
|
|
17
17
|
from graphql import GraphQLResolveInfo
|
|
18
18
|
|
|
@@ -38,7 +38,7 @@ class ApolloResolverStats:
|
|
|
38
38
|
field_name: str
|
|
39
39
|
return_type: Any
|
|
40
40
|
start_offset: int
|
|
41
|
-
duration:
|
|
41
|
+
duration: int | None = None
|
|
42
42
|
|
|
43
43
|
def to_json(self) -> dict[str, Any]:
|
|
44
44
|
return {
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import hashlib
|
|
4
4
|
from functools import cached_property
|
|
5
5
|
from inspect import isawaitable
|
|
6
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
import ddtrace
|
|
9
9
|
from packaging import version
|
|
@@ -19,7 +19,7 @@ else:
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
22
|
-
from collections.abc import Generator, Iterator
|
|
22
|
+
from collections.abc import Callable, Generator, Iterator
|
|
23
23
|
|
|
24
24
|
from graphql import GraphQLResolveInfo
|
|
25
25
|
|
|
@@ -30,7 +30,7 @@ class DatadogTracingExtension(SchemaExtension):
|
|
|
30
30
|
def __init__(
|
|
31
31
|
self,
|
|
32
32
|
*,
|
|
33
|
-
execution_context:
|
|
33
|
+
execution_context: ExecutionContext | None = None,
|
|
34
34
|
) -> None:
|
|
35
35
|
if execution_context:
|
|
36
36
|
self.execution_context = execution_context
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections.abc import Callable
|
|
3
4
|
from copy import deepcopy
|
|
4
5
|
from inspect import isawaitable
|
|
5
6
|
from typing import (
|
|
6
7
|
TYPE_CHECKING,
|
|
7
8
|
Any,
|
|
8
|
-
Callable,
|
|
9
|
-
Optional,
|
|
10
|
-
Union,
|
|
11
9
|
)
|
|
12
10
|
|
|
13
11
|
from opentelemetry import trace
|
|
@@ -33,16 +31,16 @@ ArgFilter = Callable[[dict[str, Any], "GraphQLResolveInfo"], dict[str, Any]]
|
|
|
33
31
|
|
|
34
32
|
|
|
35
33
|
class OpenTelemetryExtension(SchemaExtension):
|
|
36
|
-
_arg_filter:
|
|
34
|
+
_arg_filter: ArgFilter | None
|
|
37
35
|
_span_holder: dict[LifecycleStep, Span]
|
|
38
36
|
_tracer: Tracer
|
|
39
37
|
|
|
40
38
|
def __init__(
|
|
41
39
|
self,
|
|
42
40
|
*,
|
|
43
|
-
execution_context:
|
|
44
|
-
arg_filter:
|
|
45
|
-
tracer_provider:
|
|
41
|
+
execution_context: ExecutionContext | None = None,
|
|
42
|
+
arg_filter: ArgFilter | None = None,
|
|
43
|
+
tracer_provider: trace.TracerProvider | None = None,
|
|
46
44
|
) -> None:
|
|
47
45
|
self._arg_filter = arg_filter
|
|
48
46
|
self._tracer = trace.get_tracer("strawberry", tracer_provider=tracer_provider)
|
|
@@ -129,7 +127,7 @@ class OpenTelemetryExtension(SchemaExtension):
|
|
|
129
127
|
return bytes(value) # Convert bytearray and memoryview to bytes
|
|
130
128
|
return str(value)
|
|
131
129
|
|
|
132
|
-
def convert_set_to_allowed_types(self, value:
|
|
130
|
+
def convert_set_to_allowed_types(self, value: set | frozenset) -> str:
|
|
133
131
|
return (
|
|
134
132
|
"{" + ", ".join(str(self.convert_to_allowed_types(x)) for x in value) + "}"
|
|
135
133
|
)
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
from strawberry.extensions.utils import is_introspection_field
|
|
6
6
|
from strawberry.resolvers import is_default_resolver
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
|
+
from collections.abc import Callable
|
|
10
|
+
|
|
9
11
|
from graphql import GraphQLResolveInfo
|
|
10
12
|
|
|
11
13
|
|
strawberry/extensions/utils.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from graphql import GraphQLResolveInfo
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def is_introspection_key(key:
|
|
9
|
+
def is_introspection_key(key: str | int) -> bool:
|
|
10
10
|
# from: https://spec.graphql.org/June2018/#sec-Schema
|
|
11
11
|
# > All types and directives defined within a schema must not have a name which
|
|
12
12
|
# > begins with "__" (two underscores), as this is used exclusively
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from collections.abc import Iterator
|
|
2
2
|
from functools import lru_cache
|
|
3
|
-
from typing import Optional
|
|
4
3
|
|
|
5
4
|
from strawberry.extensions.base_extension import SchemaExtension
|
|
6
5
|
|
|
@@ -22,7 +21,7 @@ class ValidationCache(SchemaExtension):
|
|
|
22
21
|
```
|
|
23
22
|
"""
|
|
24
23
|
|
|
25
|
-
def __init__(self, maxsize:
|
|
24
|
+
def __init__(self, maxsize: int | None = None) -> None:
|
|
26
25
|
"""Initialize the ValidationCache.
|
|
27
26
|
|
|
28
27
|
Args:
|
strawberry/fastapi/context.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any,
|
|
1
|
+
from typing import Any, Union
|
|
2
2
|
|
|
3
3
|
from starlette.background import BackgroundTasks
|
|
4
4
|
from starlette.requests import Request
|
|
@@ -7,17 +7,17 @@ from starlette.websockets import WebSocket
|
|
|
7
7
|
|
|
8
8
|
CustomContext = Union["BaseContext", dict[str, Any]]
|
|
9
9
|
MergedContext = Union[
|
|
10
|
-
"BaseContext", dict[str,
|
|
10
|
+
"BaseContext", dict[str, Any | BackgroundTasks | Request | Response | WebSocket]
|
|
11
11
|
]
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class BaseContext:
|
|
15
|
-
connection_params:
|
|
15
|
+
connection_params: Any | None = None
|
|
16
16
|
|
|
17
17
|
def __init__(self) -> None:
|
|
18
|
-
self.request:
|
|
19
|
-
self.background_tasks:
|
|
20
|
-
self.response:
|
|
18
|
+
self.request: Request | WebSocket | None = None
|
|
19
|
+
self.background_tasks: BackgroundTasks | None = None
|
|
20
|
+
self.response: Response | None = None
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
__all__ = ["BaseContext"]
|
strawberry/fastapi/router.py
CHANGED
|
@@ -6,13 +6,14 @@ from inspect import signature
|
|
|
6
6
|
from typing import (
|
|
7
7
|
TYPE_CHECKING,
|
|
8
8
|
Any,
|
|
9
|
-
|
|
10
|
-
Optional,
|
|
11
|
-
Union,
|
|
9
|
+
TypeGuard,
|
|
12
10
|
cast,
|
|
13
11
|
)
|
|
14
|
-
from typing_extensions import TypeGuard
|
|
15
12
|
|
|
13
|
+
from fastapi import APIRouter, Depends, params
|
|
14
|
+
from fastapi.datastructures import Default
|
|
15
|
+
from fastapi.routing import APIRoute
|
|
16
|
+
from fastapi.utils import generate_unique_id
|
|
16
17
|
from lia import HTTPException, StarletteRequestAdapter
|
|
17
18
|
from starlette import status
|
|
18
19
|
from starlette.background import BackgroundTasks # noqa: TC002
|
|
@@ -26,10 +27,6 @@ from starlette.responses import (
|
|
|
26
27
|
)
|
|
27
28
|
from starlette.websockets import WebSocket
|
|
28
29
|
|
|
29
|
-
from fastapi import APIRouter, Depends, params
|
|
30
|
-
from fastapi.datastructures import Default
|
|
31
|
-
from fastapi.routing import APIRoute
|
|
32
|
-
from fastapi.utils import generate_unique_id
|
|
33
30
|
from strawberry.asgi import ASGIWebSocketAdapter
|
|
34
31
|
from strawberry.exceptions import InvalidCustomContext
|
|
35
32
|
from strawberry.fastapi.context import BaseContext, CustomContext
|
|
@@ -41,6 +38,7 @@ if TYPE_CHECKING:
|
|
|
41
38
|
from collections.abc import (
|
|
42
39
|
AsyncIterator,
|
|
43
40
|
Awaitable,
|
|
41
|
+
Callable,
|
|
44
42
|
Sequence,
|
|
45
43
|
)
|
|
46
44
|
from enum import Enum
|
|
@@ -62,7 +60,7 @@ class GraphQLRouter(
|
|
|
62
60
|
):
|
|
63
61
|
allow_queries_via_get = True
|
|
64
62
|
request_adapter_class = StarletteRequestAdapter
|
|
65
|
-
websocket_adapter_class = ASGIWebSocketAdapter
|
|
63
|
+
websocket_adapter_class = ASGIWebSocketAdapter # type: ignore
|
|
66
64
|
|
|
67
65
|
@staticmethod
|
|
68
66
|
async def __get_root_value() -> None:
|
|
@@ -71,16 +69,16 @@ class GraphQLRouter(
|
|
|
71
69
|
@staticmethod
|
|
72
70
|
def __get_context_getter(
|
|
73
71
|
custom_getter: Callable[
|
|
74
|
-
...,
|
|
72
|
+
..., CustomContext | None | Awaitable[CustomContext | None]
|
|
75
73
|
],
|
|
76
74
|
) -> Callable[..., Awaitable[CustomContext]]:
|
|
77
75
|
async def dependency(
|
|
78
|
-
custom_context:
|
|
76
|
+
custom_context: CustomContext | None,
|
|
79
77
|
background_tasks: BackgroundTasks,
|
|
80
78
|
connection: HTTPConnection,
|
|
81
79
|
response: Response = None, # type: ignore
|
|
82
80
|
) -> MergedContext:
|
|
83
|
-
request = cast("
|
|
81
|
+
request = cast("Request | WebSocket", connection)
|
|
84
82
|
if isinstance(custom_context, BaseContext):
|
|
85
83
|
custom_context.request = request
|
|
86
84
|
custom_context.background_tasks = background_tasks
|
|
@@ -122,35 +120,34 @@ class GraphQLRouter(
|
|
|
122
120
|
self,
|
|
123
121
|
schema: BaseSchema,
|
|
124
122
|
path: str = "",
|
|
125
|
-
graphiql:
|
|
126
|
-
graphql_ide:
|
|
123
|
+
graphiql: bool | None = None,
|
|
124
|
+
graphql_ide: GraphQL_IDE | None = "graphiql",
|
|
127
125
|
allow_queries_via_get: bool = True,
|
|
128
126
|
keep_alive: bool = False,
|
|
129
127
|
keep_alive_interval: float = 1,
|
|
130
|
-
root_value_getter:
|
|
131
|
-
context_getter:
|
|
132
|
-
|
|
133
|
-
] = None,
|
|
128
|
+
root_value_getter: Callable[[], RootValue] | None = None,
|
|
129
|
+
context_getter: Callable[..., Context | None | Awaitable[Context | None]]
|
|
130
|
+
| None = None,
|
|
134
131
|
subscription_protocols: Sequence[str] = (
|
|
135
132
|
GRAPHQL_TRANSPORT_WS_PROTOCOL,
|
|
136
133
|
GRAPHQL_WS_PROTOCOL,
|
|
137
134
|
),
|
|
138
135
|
connection_init_wait_timeout: timedelta = timedelta(minutes=1),
|
|
139
136
|
prefix: str = "",
|
|
140
|
-
tags:
|
|
141
|
-
dependencies:
|
|
137
|
+
tags: list[str | Enum] | None = None,
|
|
138
|
+
dependencies: Sequence[params.Depends] | None = None,
|
|
142
139
|
default_response_class: type[Response] = Default(JSONResponse),
|
|
143
|
-
responses:
|
|
144
|
-
callbacks:
|
|
145
|
-
routes:
|
|
140
|
+
responses: dict[int | str, dict[str, Any]] | None = None,
|
|
141
|
+
callbacks: list[BaseRoute] | None = None,
|
|
142
|
+
routes: list[BaseRoute] | None = None,
|
|
146
143
|
redirect_slashes: bool = True,
|
|
147
|
-
default:
|
|
148
|
-
dependency_overrides_provider:
|
|
144
|
+
default: ASGIApp | None = None,
|
|
145
|
+
dependency_overrides_provider: Any | None = None,
|
|
149
146
|
route_class: type[APIRoute] = APIRoute,
|
|
150
|
-
on_startup:
|
|
151
|
-
on_shutdown:
|
|
152
|
-
lifespan:
|
|
153
|
-
deprecated:
|
|
147
|
+
on_startup: Sequence[Callable[[], Any]] | None = None,
|
|
148
|
+
on_shutdown: Sequence[Callable[[], Any]] | None = None,
|
|
149
|
+
lifespan: Lifespan[Any] | None = None,
|
|
150
|
+
deprecated: bool | None = None,
|
|
154
151
|
include_in_schema: bool = True,
|
|
155
152
|
generate_unique_id_function: Callable[[APIRoute], str] = Default(
|
|
156
153
|
generate_unique_id
|
|
@@ -265,13 +262,13 @@ class GraphQLRouter(
|
|
|
265
262
|
return HTMLResponse(self.graphql_ide_html)
|
|
266
263
|
|
|
267
264
|
async def get_context(
|
|
268
|
-
self, request:
|
|
265
|
+
self, request: Request | WebSocket, response: Response | WebSocket
|
|
269
266
|
) -> Context: # pragma: no cover
|
|
270
267
|
raise ValueError("`get_context` is not used by FastAPI GraphQL Router")
|
|
271
268
|
|
|
272
269
|
async def get_root_value(
|
|
273
|
-
self, request:
|
|
274
|
-
) ->
|
|
270
|
+
self, request: Request | WebSocket
|
|
271
|
+
) -> RootValue | None: # pragma: no cover
|
|
275
272
|
raise ValueError("`get_root_value` is not used by FastAPI GraphQL Router")
|
|
276
273
|
|
|
277
274
|
async def get_sub_response(self, request: Request) -> Response:
|
|
@@ -279,7 +276,7 @@ class GraphQLRouter(
|
|
|
279
276
|
|
|
280
277
|
def create_response(
|
|
281
278
|
self,
|
|
282
|
-
response_data:
|
|
279
|
+
response_data: GraphQLHTTPResponse | list[GraphQLHTTPResponse],
|
|
283
280
|
sub_response: Response,
|
|
284
281
|
) -> Response:
|
|
285
282
|
response = Response(
|
|
@@ -309,18 +306,18 @@ class GraphQLRouter(
|
|
|
309
306
|
)
|
|
310
307
|
|
|
311
308
|
def is_websocket_request(
|
|
312
|
-
self, request:
|
|
309
|
+
self, request: Request | WebSocket
|
|
313
310
|
) -> TypeGuard[WebSocket]:
|
|
314
311
|
return request.scope["type"] == "websocket"
|
|
315
312
|
|
|
316
|
-
async def pick_websocket_subprotocol(self, request: WebSocket) ->
|
|
313
|
+
async def pick_websocket_subprotocol(self, request: WebSocket) -> str | None:
|
|
317
314
|
protocols = request["subprotocols"]
|
|
318
315
|
intersection = set(protocols) & set(self.protocols)
|
|
319
316
|
sorted_intersection = sorted(intersection, key=protocols.index)
|
|
320
317
|
return next(iter(sorted_intersection), None)
|
|
321
318
|
|
|
322
319
|
async def create_websocket_response(
|
|
323
|
-
self, request: WebSocket, subprotocol:
|
|
320
|
+
self, request: WebSocket, subprotocol: str | None
|
|
324
321
|
) -> WebSocket:
|
|
325
322
|
await request.accept(subprotocol=subprotocol)
|
|
326
323
|
return request
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
from collections.abc import Iterable
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
from strawberry.types.arguments import StrawberryArgumentAnnotation
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
def argument(
|
|
8
|
-
description:
|
|
9
|
-
name:
|
|
10
|
-
deprecation_reason:
|
|
7
|
+
description: str | None = None,
|
|
8
|
+
name: str | None = None,
|
|
9
|
+
deprecation_reason: str | None = None,
|
|
11
10
|
directives: Iterable[object] = (),
|
|
12
11
|
inaccessible: bool = False,
|
|
13
|
-
tags:
|
|
12
|
+
tags: Iterable[str] | None = (),
|
|
14
13
|
) -> StrawberryArgumentAnnotation:
|
|
15
14
|
from strawberry.federation.schema_directives import Inaccessible, Tag
|
|
16
15
|
|