strawberry-graphql 0.275.7__py3-none-any.whl → 0.284.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of strawberry-graphql might be problematic. Click here for more details.
- strawberry/__init__.py +2 -0
- strawberry/aiohttp/test/client.py +8 -15
- strawberry/aiohttp/views.py +15 -64
- strawberry/annotation.py +70 -25
- strawberry/asgi/__init__.py +22 -56
- strawberry/asgi/test/client.py +6 -6
- strawberry/chalice/views.py +13 -79
- strawberry/channels/handlers/base.py +7 -8
- strawberry/channels/handlers/http_handler.py +50 -32
- strawberry/channels/handlers/ws_handler.py +12 -14
- strawberry/channels/router.py +3 -4
- strawberry/channels/testing.py +7 -9
- strawberry/cli/__init__.py +7 -6
- strawberry/cli/commands/codegen.py +7 -7
- strawberry/cli/commands/dev.py +72 -0
- strawberry/cli/commands/schema_codegen.py +1 -2
- strawberry/cli/commands/server.py +3 -44
- strawberry/cli/commands/upgrade/__init__.py +3 -3
- strawberry/cli/commands/upgrade/_run_codemod.py +2 -2
- strawberry/cli/constants.py +1 -2
- strawberry/cli/{debug_server.py → dev_server.py} +3 -7
- 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/__init__.py +9 -0
- strawberry/codemods/annotated_unions.py +2 -2
- strawberry/codemods/maybe_optional.py +118 -0
- strawberry/dataloader.py +28 -24
- strawberry/directive.py +6 -7
- strawberry/django/test/client.py +3 -3
- strawberry/django/views.py +21 -91
- 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 +17 -25
- 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 +9 -3
- strawberry/extensions/field_extension.py +4 -4
- strawberry/extensions/mask_errors.py +24 -13
- 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 +2 -3
- strawberry/fastapi/context.py +6 -6
- strawberry/fastapi/router.py +43 -42
- 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 +16 -85
- strawberry/http/__init__.py +30 -20
- strawberry/http/async_base_view.py +208 -89
- strawberry/http/base.py +28 -11
- strawberry/http/exceptions.py +5 -7
- strawberry/http/ides.py +2 -3
- strawberry/http/sync_base_view.py +115 -69
- strawberry/http/types.py +3 -3
- strawberry/litestar/controller.py +43 -77
- strawberry/permission.py +4 -6
- strawberry/printer/ast_from_value.py +3 -5
- strawberry/printer/printer.py +18 -15
- strawberry/quart/views.py +16 -48
- strawberry/relay/exceptions.py +4 -4
- strawberry/relay/fields.py +33 -32
- strawberry/relay/types.py +32 -35
- strawberry/relay/utils.py +11 -23
- strawberry/resolvers.py +2 -1
- strawberry/sanic/context.py +1 -0
- strawberry/sanic/utils.py +3 -3
- strawberry/sanic/views.py +15 -54
- strawberry/scalars.py +2 -2
- strawberry/schema/_graphql_core.py +55 -0
- strawberry/schema/base.py +32 -33
- strawberry/schema/compat.py +9 -9
- strawberry/schema/config.py +10 -1
- strawberry/schema/exceptions.py +1 -3
- strawberry/schema/name_converter.py +9 -8
- strawberry/schema/schema.py +133 -100
- strawberry/schema/schema_converter.py +96 -58
- strawberry/schema/types/base_scalars.py +1 -1
- strawberry/schema/types/concrete_type.py +5 -5
- strawberry/schema/validation_rules/maybe_null.py +136 -0
- strawberry/schema_codegen/__init__.py +3 -3
- strawberry/schema_directive.py +7 -6
- strawberry/static/graphiql.html +5 -5
- strawberry/streamable.py +35 -0
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +5 -16
- strawberry/subscriptions/protocols/graphql_transport_ws/types.py +20 -20
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +5 -12
- 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 +41 -28
- strawberry/types/auto.py +3 -4
- strawberry/types/base.py +25 -27
- strawberry/types/enum.py +22 -25
- strawberry/types/execution.py +21 -16
- strawberry/types/field.py +109 -130
- 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.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/METADATA +14 -8
- strawberry_graphql-0.284.3.dist-info/RECORD +243 -0
- {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/WHEEL +1 -1
- strawberry/utils/dataclasses.py +0 -37
- strawberry/utils/debug.py +0 -46
- strawberry/utils/graphql_lexer.py +0 -35
- strawberry_graphql-0.275.7.dist-info/RECORD +0 -241
- {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/entry_points.txt +0 -0
- {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info/licenses}/LICENSE +0 -0
strawberry/types/enum.py
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import dataclasses
|
|
2
|
-
from collections.abc import Iterable, Mapping
|
|
2
|
+
from collections.abc import Callable, Iterable, Mapping
|
|
3
3
|
from enum import EnumMeta
|
|
4
4
|
from typing import (
|
|
5
5
|
Any,
|
|
6
|
-
Callable,
|
|
7
|
-
Optional,
|
|
8
6
|
TypeVar,
|
|
9
|
-
Union,
|
|
10
7
|
overload,
|
|
11
8
|
)
|
|
12
9
|
|
|
@@ -18,9 +15,9 @@ from strawberry.types.base import StrawberryType
|
|
|
18
15
|
class EnumValue:
|
|
19
16
|
name: str
|
|
20
17
|
value: Any
|
|
21
|
-
deprecation_reason:
|
|
18
|
+
deprecation_reason: str | None = None
|
|
22
19
|
directives: Iterable[object] = ()
|
|
23
|
-
description:
|
|
20
|
+
description: str | None = None
|
|
24
21
|
|
|
25
22
|
|
|
26
23
|
@dataclasses.dataclass
|
|
@@ -28,7 +25,7 @@ class EnumDefinition(StrawberryType):
|
|
|
28
25
|
wrapped_cls: EnumMeta
|
|
29
26
|
name: str
|
|
30
27
|
values: list[EnumValue]
|
|
31
|
-
description:
|
|
28
|
+
description: str | None
|
|
32
29
|
directives: Iterable[object] = ()
|
|
33
30
|
|
|
34
31
|
def __hash__(self) -> int:
|
|
@@ -36,8 +33,8 @@ class EnumDefinition(StrawberryType):
|
|
|
36
33
|
return hash(self.name)
|
|
37
34
|
|
|
38
35
|
def copy_with(
|
|
39
|
-
self, type_var_map: Mapping[str,
|
|
40
|
-
) ->
|
|
36
|
+
self, type_var_map: Mapping[str, StrawberryType | type]
|
|
37
|
+
) -> StrawberryType | type:
|
|
41
38
|
# enum don't support type parameters, so we can safely return self
|
|
42
39
|
return self
|
|
43
40
|
|
|
@@ -54,10 +51,10 @@ class EnumDefinition(StrawberryType):
|
|
|
54
51
|
@dataclasses.dataclass
|
|
55
52
|
class EnumValueDefinition:
|
|
56
53
|
value: Any
|
|
57
|
-
graphql_name:
|
|
58
|
-
deprecation_reason:
|
|
54
|
+
graphql_name: str | None = None
|
|
55
|
+
deprecation_reason: str | None = None
|
|
59
56
|
directives: Iterable[object] = ()
|
|
60
|
-
description:
|
|
57
|
+
description: str | None = None
|
|
61
58
|
|
|
62
59
|
def __int__(self) -> int:
|
|
63
60
|
return self.value
|
|
@@ -65,10 +62,10 @@ class EnumValueDefinition:
|
|
|
65
62
|
|
|
66
63
|
def enum_value(
|
|
67
64
|
value: Any,
|
|
68
|
-
name:
|
|
69
|
-
deprecation_reason:
|
|
65
|
+
name: str | None = None,
|
|
66
|
+
deprecation_reason: str | None = None,
|
|
70
67
|
directives: Iterable[object] = (),
|
|
71
|
-
description:
|
|
68
|
+
description: str | None = None,
|
|
72
69
|
) -> EnumValueDefinition:
|
|
73
70
|
"""Function to customise an enum value, for example to add a description or deprecation reason.
|
|
74
71
|
|
|
@@ -109,8 +106,8 @@ EnumType = TypeVar("EnumType", bound=EnumMeta)
|
|
|
109
106
|
|
|
110
107
|
def _process_enum(
|
|
111
108
|
cls: EnumType,
|
|
112
|
-
name:
|
|
113
|
-
description:
|
|
109
|
+
name: str | None = None,
|
|
110
|
+
description: str | None = None,
|
|
114
111
|
directives: Iterable[object] = (),
|
|
115
112
|
) -> EnumType:
|
|
116
113
|
if not isinstance(cls, EnumMeta):
|
|
@@ -166,8 +163,8 @@ def _process_enum(
|
|
|
166
163
|
def enum(
|
|
167
164
|
cls: EnumType,
|
|
168
165
|
*,
|
|
169
|
-
name:
|
|
170
|
-
description:
|
|
166
|
+
name: str | None = None,
|
|
167
|
+
description: str | None = None,
|
|
171
168
|
directives: Iterable[object] = (),
|
|
172
169
|
) -> EnumType: ...
|
|
173
170
|
|
|
@@ -176,19 +173,19 @@ def enum(
|
|
|
176
173
|
def enum(
|
|
177
174
|
cls: None = None,
|
|
178
175
|
*,
|
|
179
|
-
name:
|
|
180
|
-
description:
|
|
176
|
+
name: str | None = None,
|
|
177
|
+
description: str | None = None,
|
|
181
178
|
directives: Iterable[object] = (),
|
|
182
179
|
) -> Callable[[EnumType], EnumType]: ...
|
|
183
180
|
|
|
184
181
|
|
|
185
182
|
def enum(
|
|
186
|
-
cls:
|
|
183
|
+
cls: EnumType | None = None,
|
|
187
184
|
*,
|
|
188
|
-
name:
|
|
189
|
-
description:
|
|
185
|
+
name: str | None = None,
|
|
186
|
+
description: str | None = None,
|
|
190
187
|
directives: Iterable[object] = (),
|
|
191
|
-
) ->
|
|
188
|
+
) -> EnumType | Callable[[EnumType], EnumType]:
|
|
192
189
|
"""Annotates an Enum class a GraphQL enum.
|
|
193
190
|
|
|
194
191
|
GraphQL enums only have names, while Python enums have names and values,
|
strawberry/types/execution.py
CHANGED
|
@@ -4,10 +4,9 @@ import dataclasses
|
|
|
4
4
|
from typing import (
|
|
5
5
|
TYPE_CHECKING,
|
|
6
6
|
Any,
|
|
7
|
-
Optional,
|
|
8
7
|
runtime_checkable,
|
|
9
8
|
)
|
|
10
|
-
from typing_extensions import Protocol, TypedDict
|
|
9
|
+
from typing_extensions import Protocol, TypedDict, deprecated
|
|
11
10
|
|
|
12
11
|
from graphql import specified_rules
|
|
13
12
|
|
|
@@ -18,47 +17,47 @@ if TYPE_CHECKING:
|
|
|
18
17
|
from typing_extensions import NotRequired
|
|
19
18
|
|
|
20
19
|
from graphql import ASTValidationRule
|
|
21
|
-
from graphql import ExecutionResult as GraphQLExecutionResult
|
|
22
20
|
from graphql.error.graphql_error import GraphQLError
|
|
23
21
|
from graphql.language import DocumentNode, OperationDefinitionNode
|
|
24
22
|
|
|
25
23
|
from strawberry.schema import Schema
|
|
24
|
+
from strawberry.schema._graphql_core import GraphQLExecutionResult
|
|
26
25
|
|
|
27
26
|
from .graphql import OperationType
|
|
28
27
|
|
|
29
28
|
|
|
30
29
|
@dataclasses.dataclass
|
|
31
30
|
class ExecutionContext:
|
|
32
|
-
query:
|
|
31
|
+
query: str | None
|
|
33
32
|
schema: Schema
|
|
34
33
|
allowed_operations: Iterable[OperationType]
|
|
35
34
|
context: Any = None
|
|
36
|
-
variables:
|
|
35
|
+
variables: dict[str, Any] | None = None
|
|
37
36
|
parse_options: ParseOptions = dataclasses.field(
|
|
38
37
|
default_factory=lambda: ParseOptions()
|
|
39
38
|
)
|
|
40
|
-
root_value:
|
|
39
|
+
root_value: Any | None = None
|
|
41
40
|
validation_rules: tuple[type[ASTValidationRule], ...] = dataclasses.field(
|
|
42
41
|
default_factory=lambda: tuple(specified_rules)
|
|
43
42
|
)
|
|
44
43
|
|
|
45
44
|
# The operation name that is provided by the request
|
|
46
|
-
provided_operation_name: dataclasses.InitVar[
|
|
45
|
+
provided_operation_name: dataclasses.InitVar[str | None] = None
|
|
47
46
|
|
|
48
47
|
# Values that get populated during the GraphQL execution so that they can be
|
|
49
48
|
# accessed by extensions
|
|
50
|
-
graphql_document:
|
|
51
|
-
|
|
52
|
-
result:
|
|
49
|
+
graphql_document: DocumentNode | None = None
|
|
50
|
+
pre_execution_errors: list[GraphQLError] | None = None
|
|
51
|
+
result: GraphQLExecutionResult | None = None
|
|
53
52
|
extensions_results: dict[str, Any] = dataclasses.field(default_factory=dict)
|
|
54
53
|
|
|
55
|
-
operation_extensions:
|
|
54
|
+
operation_extensions: dict[str, Any] | None = None
|
|
56
55
|
|
|
57
56
|
def __post_init__(self, provided_operation_name: str | None) -> None:
|
|
58
57
|
self._provided_operation_name = provided_operation_name
|
|
59
58
|
|
|
60
59
|
@property
|
|
61
|
-
def operation_name(self) ->
|
|
60
|
+
def operation_name(self) -> str | None:
|
|
62
61
|
if self._provided_operation_name is not None:
|
|
63
62
|
return self._provided_operation_name
|
|
64
63
|
|
|
@@ -79,19 +78,25 @@ class ExecutionContext:
|
|
|
79
78
|
|
|
80
79
|
return get_operation_type(graphql_document, self.operation_name)
|
|
81
80
|
|
|
82
|
-
def _get_first_operation(self) ->
|
|
81
|
+
def _get_first_operation(self) -> OperationDefinitionNode | None:
|
|
83
82
|
graphql_document = self.graphql_document
|
|
84
83
|
if not graphql_document:
|
|
85
84
|
return None
|
|
86
85
|
|
|
87
86
|
return get_first_operation(graphql_document)
|
|
88
87
|
|
|
88
|
+
@property
|
|
89
|
+
@deprecated("Use 'pre_execution_errors' instead")
|
|
90
|
+
def errors(self) -> list[GraphQLError] | None:
|
|
91
|
+
"""Deprecated: Use pre_execution_errors instead."""
|
|
92
|
+
return self.pre_execution_errors
|
|
93
|
+
|
|
89
94
|
|
|
90
95
|
@dataclasses.dataclass
|
|
91
96
|
class ExecutionResult:
|
|
92
|
-
data:
|
|
93
|
-
errors:
|
|
94
|
-
extensions:
|
|
97
|
+
data: dict[str, Any] | None
|
|
98
|
+
errors: list[GraphQLError] | None
|
|
99
|
+
extensions: dict[str, Any] | None = None
|
|
95
100
|
|
|
96
101
|
|
|
97
102
|
@dataclasses.dataclass
|
strawberry/types/field.py
CHANGED
|
@@ -4,16 +4,15 @@ import contextlib
|
|
|
4
4
|
import copy
|
|
5
5
|
import dataclasses
|
|
6
6
|
import sys
|
|
7
|
-
from collections.abc import Awaitable, Coroutine, Mapping, Sequence
|
|
7
|
+
from collections.abc import Awaitable, Callable, Coroutine, Mapping, Sequence
|
|
8
8
|
from functools import cached_property
|
|
9
9
|
from typing import (
|
|
10
10
|
TYPE_CHECKING,
|
|
11
11
|
Any,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
NoReturn,
|
|
13
|
+
TypeAlias,
|
|
14
14
|
TypeVar,
|
|
15
15
|
Union,
|
|
16
|
-
cast,
|
|
17
16
|
overload,
|
|
18
17
|
)
|
|
19
18
|
|
|
@@ -30,7 +29,8 @@ from .fields.resolver import StrawberryResolver
|
|
|
30
29
|
|
|
31
30
|
if TYPE_CHECKING:
|
|
32
31
|
import builtins
|
|
33
|
-
from
|
|
32
|
+
from typing import Literal
|
|
33
|
+
from typing_extensions import Self
|
|
34
34
|
|
|
35
35
|
from strawberry.extensions.field_extension import FieldExtension
|
|
36
36
|
from strawberry.permission import BasePermission
|
|
@@ -40,24 +40,31 @@ if TYPE_CHECKING:
|
|
|
40
40
|
|
|
41
41
|
T = TypeVar("T")
|
|
42
42
|
|
|
43
|
-
_RESOLVER_TYPE_SYNC = Union[
|
|
43
|
+
_RESOLVER_TYPE_SYNC: TypeAlias = Union[
|
|
44
44
|
StrawberryResolver[T],
|
|
45
45
|
Callable[..., T],
|
|
46
46
|
"staticmethod[Any, T]",
|
|
47
47
|
"classmethod[Any, Any, T]",
|
|
48
48
|
]
|
|
49
49
|
|
|
50
|
-
_RESOLVER_TYPE_ASYNC =
|
|
51
|
-
Callable[..., Coroutine[Any, Any, T]]
|
|
52
|
-
|
|
53
|
-
]
|
|
50
|
+
_RESOLVER_TYPE_ASYNC: TypeAlias = (
|
|
51
|
+
Callable[..., Coroutine[Any, Any, T]] | Callable[..., Awaitable[T]]
|
|
52
|
+
)
|
|
54
53
|
|
|
55
|
-
_RESOLVER_TYPE =
|
|
54
|
+
_RESOLVER_TYPE: TypeAlias = _RESOLVER_TYPE_SYNC[T] | _RESOLVER_TYPE_ASYNC[T]
|
|
56
55
|
|
|
57
|
-
UNRESOLVED = object()
|
|
58
56
|
|
|
57
|
+
class UNRESOLVED:
|
|
58
|
+
def __new__(cls) -> NoReturn:
|
|
59
|
+
raise TypeError("UNRESOLVED is a sentinel and cannot be instantiated.")
|
|
59
60
|
|
|
60
|
-
|
|
61
|
+
|
|
62
|
+
FieldType: TypeAlias = (
|
|
63
|
+
StrawberryType | type[WithStrawberryObjectDefinition | UNRESOLVED]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _is_generic(resolver_type: StrawberryType | type) -> bool:
|
|
61
68
|
"""Returns True if `resolver_type` is generic else False."""
|
|
62
69
|
if isinstance(resolver_type, StrawberryType):
|
|
63
70
|
return resolver_type.is_graphql_generic
|
|
@@ -70,34 +77,36 @@ def _is_generic(resolver_type: Union[StrawberryType, type]) -> bool:
|
|
|
70
77
|
|
|
71
78
|
|
|
72
79
|
class StrawberryField(dataclasses.Field):
|
|
73
|
-
type_annotation:
|
|
80
|
+
type_annotation: StrawberryAnnotation | None
|
|
74
81
|
default_resolver: Callable[[Any, str], object] = getattr
|
|
75
82
|
|
|
76
83
|
def __init__(
|
|
77
84
|
self,
|
|
78
|
-
python_name:
|
|
79
|
-
graphql_name:
|
|
80
|
-
type_annotation:
|
|
81
|
-
origin:
|
|
85
|
+
python_name: str | None = None,
|
|
86
|
+
graphql_name: str | None = None,
|
|
87
|
+
type_annotation: StrawberryAnnotation | None = None,
|
|
88
|
+
origin: type | Callable | staticmethod | classmethod | None = None,
|
|
82
89
|
is_subscription: bool = False,
|
|
83
|
-
description:
|
|
84
|
-
base_resolver:
|
|
90
|
+
description: str | None = None,
|
|
91
|
+
base_resolver: StrawberryResolver | None = None,
|
|
85
92
|
permission_classes: list[type[BasePermission]] = (), # type: ignore
|
|
86
93
|
default: object = dataclasses.MISSING,
|
|
87
|
-
default_factory:
|
|
88
|
-
metadata:
|
|
89
|
-
deprecation_reason:
|
|
94
|
+
default_factory: Callable[[], Any] | object = dataclasses.MISSING,
|
|
95
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
96
|
+
deprecation_reason: str | None = None,
|
|
90
97
|
directives: Sequence[object] = (),
|
|
91
98
|
extensions: list[FieldExtension] = (), # type: ignore
|
|
92
99
|
) -> None:
|
|
93
100
|
# basic fields are fields with no provided resolver
|
|
94
101
|
is_basic_field = not base_resolver
|
|
95
102
|
|
|
96
|
-
kwargs: Any = {
|
|
103
|
+
kwargs: Any = {
|
|
104
|
+
"kw_only": True,
|
|
105
|
+
}
|
|
97
106
|
|
|
98
|
-
#
|
|
99
|
-
if sys.version_info >= (3,
|
|
100
|
-
kwargs["
|
|
107
|
+
# doc was added to python 3.14 and it is required
|
|
108
|
+
if sys.version_info >= (3, 14):
|
|
109
|
+
kwargs["doc"] = None
|
|
101
110
|
|
|
102
111
|
super().__init__(
|
|
103
112
|
default=default,
|
|
@@ -116,11 +125,11 @@ class StrawberryField(dataclasses.Field):
|
|
|
116
125
|
|
|
117
126
|
self.type_annotation = type_annotation
|
|
118
127
|
|
|
119
|
-
self.description:
|
|
128
|
+
self.description: str | None = description
|
|
120
129
|
self.origin = origin
|
|
121
130
|
|
|
122
|
-
self._arguments:
|
|
123
|
-
self._base_resolver:
|
|
131
|
+
self._arguments: list[StrawberryArgument] | None = None
|
|
132
|
+
self._base_resolver: StrawberryResolver | None = None
|
|
124
133
|
if base_resolver is not None:
|
|
125
134
|
self.base_resolver = base_resolver
|
|
126
135
|
|
|
@@ -212,8 +221,8 @@ class StrawberryField(dataclasses.Field):
|
|
|
212
221
|
return self
|
|
213
222
|
|
|
214
223
|
def get_result(
|
|
215
|
-
self, source: Any, info:
|
|
216
|
-
) ->
|
|
224
|
+
self, source: Any, info: Info | None, args: list[Any], kwargs: Any
|
|
225
|
+
) -> Awaitable[Any] | Any:
|
|
217
226
|
"""Calls the resolver defined for the StrawberryField.
|
|
218
227
|
|
|
219
228
|
If the field doesn't have a resolver defined we default
|
|
@@ -255,7 +264,7 @@ class StrawberryField(dataclasses.Field):
|
|
|
255
264
|
else _is_generic(self.type)
|
|
256
265
|
)
|
|
257
266
|
|
|
258
|
-
def _python_name(self) ->
|
|
267
|
+
def _python_name(self) -> str | None:
|
|
259
268
|
if self.name:
|
|
260
269
|
return self.name
|
|
261
270
|
|
|
@@ -270,7 +279,7 @@ class StrawberryField(dataclasses.Field):
|
|
|
270
279
|
python_name: str = property(_python_name, _set_python_name) # type: ignore[assignment]
|
|
271
280
|
|
|
272
281
|
@property
|
|
273
|
-
def base_resolver(self) ->
|
|
282
|
+
def base_resolver(self) -> StrawberryResolver | None:
|
|
274
283
|
return self._base_resolver
|
|
275
284
|
|
|
276
285
|
@base_resolver.setter
|
|
@@ -293,14 +302,8 @@ class StrawberryField(dataclasses.Field):
|
|
|
293
302
|
# removed.
|
|
294
303
|
_ = resolver.arguments
|
|
295
304
|
|
|
296
|
-
@property
|
|
297
|
-
def type(
|
|
298
|
-
self,
|
|
299
|
-
) -> Union[ # type: ignore [valid-type]
|
|
300
|
-
StrawberryType,
|
|
301
|
-
type[WithStrawberryObjectDefinition],
|
|
302
|
-
Literal[UNRESOLVED],
|
|
303
|
-
]:
|
|
305
|
+
@property
|
|
306
|
+
def type(self) -> FieldType:
|
|
304
307
|
return self.resolve_type()
|
|
305
308
|
|
|
306
309
|
@type.setter
|
|
@@ -330,15 +333,11 @@ class StrawberryField(dataclasses.Field):
|
|
|
330
333
|
def resolve_type(
|
|
331
334
|
self,
|
|
332
335
|
*,
|
|
333
|
-
type_definition:
|
|
334
|
-
) ->
|
|
335
|
-
StrawberryType,
|
|
336
|
-
type[WithStrawberryObjectDefinition],
|
|
337
|
-
Literal[UNRESOLVED],
|
|
338
|
-
]:
|
|
336
|
+
type_definition: StrawberryObjectDefinition | None = None,
|
|
337
|
+
) -> FieldType:
|
|
339
338
|
# We return UNRESOLVED by default, which means this case will raise a
|
|
340
339
|
# MissingReturnAnnotationError exception in _check_field_annotations
|
|
341
|
-
resolved = UNRESOLVED
|
|
340
|
+
resolved: FieldType = UNRESOLVED # type: ignore[assignment]
|
|
342
341
|
|
|
343
342
|
# We are catching NameError because dataclasses tries to fetch the type
|
|
344
343
|
# of the field from the class before the class is fully defined.
|
|
@@ -348,7 +347,7 @@ class StrawberryField(dataclasses.Field):
|
|
|
348
347
|
with contextlib.suppress(NameError):
|
|
349
348
|
# Prioritise the field type over the resolver return type
|
|
350
349
|
if self.type_annotation is not None:
|
|
351
|
-
resolved = self.type_annotation.resolve()
|
|
350
|
+
resolved = self.type_annotation.resolve(type_definition=type_definition)
|
|
352
351
|
elif self.base_resolver is not None and self.base_resolver.type is not None:
|
|
353
352
|
# Handle unannotated functions (such as lambdas)
|
|
354
353
|
# Generics will raise MissingTypesForGenericError later
|
|
@@ -356,36 +355,16 @@ class StrawberryField(dataclasses.Field):
|
|
|
356
355
|
# which is the same behaviour as having no type information.
|
|
357
356
|
resolved = self.base_resolver.type
|
|
358
357
|
|
|
359
|
-
# If this is a generic field, try to resolve it using its origin's
|
|
360
|
-
# specialized type_var_map
|
|
361
|
-
# TODO: should we check arguments here too?
|
|
362
|
-
if _is_generic(resolved): # type: ignore
|
|
363
|
-
specialized_type_var_map = (
|
|
364
|
-
type_definition and type_definition.specialized_type_var_map
|
|
365
|
-
)
|
|
366
|
-
if specialized_type_var_map and isinstance(resolved, StrawberryType):
|
|
367
|
-
resolved = resolved.copy_with(specialized_type_var_map)
|
|
368
|
-
|
|
369
|
-
# If the field is still generic, try to resolve it from the type_definition
|
|
370
|
-
# that is asking for it.
|
|
371
|
-
if (
|
|
372
|
-
_is_generic(cast("Union[StrawberryType, type]", resolved))
|
|
373
|
-
and type_definition is not None
|
|
374
|
-
and type_definition.type_var_map
|
|
375
|
-
and isinstance(resolved, StrawberryType)
|
|
376
|
-
):
|
|
377
|
-
resolved = resolved.copy_with(type_definition.type_var_map)
|
|
378
|
-
|
|
379
358
|
return resolved
|
|
380
359
|
|
|
381
360
|
def copy_with(
|
|
382
|
-
self, type_var_map: Mapping[str,
|
|
361
|
+
self, type_var_map: Mapping[str, StrawberryType | builtins.type]
|
|
383
362
|
) -> Self:
|
|
384
363
|
new_field = copy.copy(self)
|
|
385
364
|
|
|
386
|
-
override_type:
|
|
387
|
-
|
|
388
|
-
|
|
365
|
+
override_type: StrawberryType | type[WithStrawberryObjectDefinition] | None = (
|
|
366
|
+
None
|
|
367
|
+
)
|
|
389
368
|
type_ = self.resolve_type()
|
|
390
369
|
if has_object_definition(type_):
|
|
391
370
|
type_definition = type_.__strawberry_definition__
|
|
@@ -426,18 +405,18 @@ class StrawberryField(dataclasses.Field):
|
|
|
426
405
|
def field(
|
|
427
406
|
*,
|
|
428
407
|
resolver: _RESOLVER_TYPE_ASYNC[T],
|
|
429
|
-
name:
|
|
408
|
+
name: str | None = None,
|
|
430
409
|
is_subscription: bool = False,
|
|
431
|
-
description:
|
|
410
|
+
description: str | None = None,
|
|
432
411
|
init: Literal[False] = False,
|
|
433
|
-
permission_classes:
|
|
434
|
-
deprecation_reason:
|
|
412
|
+
permission_classes: list[type[BasePermission]] | None = None,
|
|
413
|
+
deprecation_reason: str | None = None,
|
|
435
414
|
default: Any = dataclasses.MISSING,
|
|
436
|
-
default_factory:
|
|
437
|
-
metadata:
|
|
438
|
-
directives:
|
|
439
|
-
extensions:
|
|
440
|
-
graphql_type:
|
|
415
|
+
default_factory: Callable[..., object] | object = dataclasses.MISSING,
|
|
416
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
417
|
+
directives: Sequence[object] | None = (),
|
|
418
|
+
extensions: list[FieldExtension] | None = None,
|
|
419
|
+
graphql_type: Any | None = None,
|
|
441
420
|
) -> T: ...
|
|
442
421
|
|
|
443
422
|
|
|
@@ -445,36 +424,36 @@ def field(
|
|
|
445
424
|
def field(
|
|
446
425
|
*,
|
|
447
426
|
resolver: _RESOLVER_TYPE_SYNC[T],
|
|
448
|
-
name:
|
|
427
|
+
name: str | None = None,
|
|
449
428
|
is_subscription: bool = False,
|
|
450
|
-
description:
|
|
429
|
+
description: str | None = None,
|
|
451
430
|
init: Literal[False] = False,
|
|
452
|
-
permission_classes:
|
|
453
|
-
deprecation_reason:
|
|
431
|
+
permission_classes: list[type[BasePermission]] | None = None,
|
|
432
|
+
deprecation_reason: str | None = None,
|
|
454
433
|
default: Any = dataclasses.MISSING,
|
|
455
|
-
default_factory:
|
|
456
|
-
metadata:
|
|
457
|
-
directives:
|
|
458
|
-
extensions:
|
|
459
|
-
graphql_type:
|
|
434
|
+
default_factory: Callable[..., object] | object = dataclasses.MISSING,
|
|
435
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
436
|
+
directives: Sequence[object] | None = (),
|
|
437
|
+
extensions: list[FieldExtension] | None = None,
|
|
438
|
+
graphql_type: Any | None = None,
|
|
460
439
|
) -> T: ...
|
|
461
440
|
|
|
462
441
|
|
|
463
442
|
@overload
|
|
464
443
|
def field(
|
|
465
444
|
*,
|
|
466
|
-
name:
|
|
445
|
+
name: str | None = None,
|
|
467
446
|
is_subscription: bool = False,
|
|
468
|
-
description:
|
|
447
|
+
description: str | None = None,
|
|
469
448
|
init: Literal[True] = True,
|
|
470
|
-
permission_classes:
|
|
471
|
-
deprecation_reason:
|
|
449
|
+
permission_classes: list[type[BasePermission]] | None = None,
|
|
450
|
+
deprecation_reason: str | None = None,
|
|
472
451
|
default: Any = dataclasses.MISSING,
|
|
473
|
-
default_factory:
|
|
474
|
-
metadata:
|
|
475
|
-
directives:
|
|
476
|
-
extensions:
|
|
477
|
-
graphql_type:
|
|
452
|
+
default_factory: Callable[..., object] | object = dataclasses.MISSING,
|
|
453
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
454
|
+
directives: Sequence[object] | None = (),
|
|
455
|
+
extensions: list[FieldExtension] | None = None,
|
|
456
|
+
graphql_type: Any | None = None,
|
|
478
457
|
) -> Any: ...
|
|
479
458
|
|
|
480
459
|
|
|
@@ -482,17 +461,17 @@ def field(
|
|
|
482
461
|
def field(
|
|
483
462
|
resolver: _RESOLVER_TYPE_ASYNC[T],
|
|
484
463
|
*,
|
|
485
|
-
name:
|
|
464
|
+
name: str | None = None,
|
|
486
465
|
is_subscription: bool = False,
|
|
487
|
-
description:
|
|
488
|
-
permission_classes:
|
|
489
|
-
deprecation_reason:
|
|
466
|
+
description: str | None = None,
|
|
467
|
+
permission_classes: list[type[BasePermission]] | None = None,
|
|
468
|
+
deprecation_reason: str | None = None,
|
|
490
469
|
default: Any = dataclasses.MISSING,
|
|
491
|
-
default_factory:
|
|
492
|
-
metadata:
|
|
493
|
-
directives:
|
|
494
|
-
extensions:
|
|
495
|
-
graphql_type:
|
|
470
|
+
default_factory: Callable[..., object] | object = dataclasses.MISSING,
|
|
471
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
472
|
+
directives: Sequence[object] | None = (),
|
|
473
|
+
extensions: list[FieldExtension] | None = None,
|
|
474
|
+
graphql_type: Any | None = None,
|
|
496
475
|
) -> StrawberryField: ...
|
|
497
476
|
|
|
498
477
|
|
|
@@ -500,38 +479,38 @@ def field(
|
|
|
500
479
|
def field(
|
|
501
480
|
resolver: _RESOLVER_TYPE_SYNC[T],
|
|
502
481
|
*,
|
|
503
|
-
name:
|
|
482
|
+
name: str | None = None,
|
|
504
483
|
is_subscription: bool = False,
|
|
505
|
-
description:
|
|
506
|
-
permission_classes:
|
|
507
|
-
deprecation_reason:
|
|
484
|
+
description: str | None = None,
|
|
485
|
+
permission_classes: list[type[BasePermission]] | None = None,
|
|
486
|
+
deprecation_reason: str | None = None,
|
|
508
487
|
default: Any = dataclasses.MISSING,
|
|
509
|
-
default_factory:
|
|
510
|
-
metadata:
|
|
511
|
-
directives:
|
|
512
|
-
extensions:
|
|
513
|
-
graphql_type:
|
|
488
|
+
default_factory: Callable[..., object] | object = dataclasses.MISSING,
|
|
489
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
490
|
+
directives: Sequence[object] | None = (),
|
|
491
|
+
extensions: list[FieldExtension] | None = None,
|
|
492
|
+
graphql_type: Any | None = None,
|
|
514
493
|
) -> StrawberryField: ...
|
|
515
494
|
|
|
516
495
|
|
|
517
496
|
def field(
|
|
518
|
-
resolver:
|
|
497
|
+
resolver: _RESOLVER_TYPE[Any] | None = None,
|
|
519
498
|
*,
|
|
520
|
-
name:
|
|
499
|
+
name: str | None = None,
|
|
521
500
|
is_subscription: bool = False,
|
|
522
|
-
description:
|
|
523
|
-
permission_classes:
|
|
524
|
-
deprecation_reason:
|
|
501
|
+
description: str | None = None,
|
|
502
|
+
permission_classes: list[type[BasePermission]] | None = None,
|
|
503
|
+
deprecation_reason: str | None = None,
|
|
525
504
|
default: Any = dataclasses.MISSING,
|
|
526
|
-
default_factory:
|
|
527
|
-
metadata:
|
|
528
|
-
directives:
|
|
529
|
-
extensions:
|
|
530
|
-
graphql_type:
|
|
505
|
+
default_factory: Callable[..., object] | object = dataclasses.MISSING,
|
|
506
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
507
|
+
directives: Sequence[object] | None = (),
|
|
508
|
+
extensions: list[FieldExtension] | None = None,
|
|
509
|
+
graphql_type: Any | None = None,
|
|
531
510
|
# This init parameter is used by PyRight to determine whether this field
|
|
532
511
|
# is added in the constructor or not. It is not used to change
|
|
533
512
|
# any behavior at the moment.
|
|
534
|
-
init: Literal[True, False
|
|
513
|
+
init: Literal[True, False] | None = None,
|
|
535
514
|
) -> Any:
|
|
536
515
|
"""Annotates a method or property as a GraphQL field.
|
|
537
516
|
|