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
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
from typing_extensions import
|
|
1
|
+
from typing import Literal, TypeAlias, TypedDict
|
|
2
|
+
from typing_extensions import NotRequired
|
|
3
3
|
|
|
4
4
|
from graphql import GraphQLFormattedError
|
|
5
5
|
|
|
@@ -8,35 +8,35 @@ class ConnectionInitMessage(TypedDict):
|
|
|
8
8
|
"""Direction: Client -> Server."""
|
|
9
9
|
|
|
10
10
|
type: Literal["connection_init"]
|
|
11
|
-
payload: NotRequired[
|
|
11
|
+
payload: NotRequired[dict[str, object] | None]
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class ConnectionAckMessage(TypedDict):
|
|
15
15
|
"""Direction: Server -> Client."""
|
|
16
16
|
|
|
17
17
|
type: Literal["connection_ack"]
|
|
18
|
-
payload: NotRequired[
|
|
18
|
+
payload: NotRequired[dict[str, object] | None]
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class PingMessage(TypedDict):
|
|
22
22
|
"""Direction: bidirectional."""
|
|
23
23
|
|
|
24
24
|
type: Literal["ping"]
|
|
25
|
-
payload: NotRequired[
|
|
25
|
+
payload: NotRequired[dict[str, object] | None]
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class PongMessage(TypedDict):
|
|
29
29
|
"""Direction: bidirectional."""
|
|
30
30
|
|
|
31
31
|
type: Literal["pong"]
|
|
32
|
-
payload: NotRequired[
|
|
32
|
+
payload: NotRequired[dict[str, object] | None]
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class SubscribeMessagePayload(TypedDict):
|
|
36
|
-
operationName: NotRequired[
|
|
36
|
+
operationName: NotRequired[str | None]
|
|
37
37
|
query: str
|
|
38
|
-
variables: NotRequired[
|
|
39
|
-
extensions: NotRequired[
|
|
38
|
+
variables: NotRequired[dict[str, object] | None]
|
|
39
|
+
extensions: NotRequired[dict[str, object] | None]
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class SubscribeMessage(TypedDict):
|
|
@@ -49,7 +49,7 @@ class SubscribeMessage(TypedDict):
|
|
|
49
49
|
|
|
50
50
|
class NextMessagePayload(TypedDict):
|
|
51
51
|
errors: NotRequired[list[GraphQLFormattedError]]
|
|
52
|
-
data: NotRequired[
|
|
52
|
+
data: NotRequired[dict[str, object] | None]
|
|
53
53
|
extensions: NotRequired[dict[str, object]]
|
|
54
54
|
|
|
55
55
|
|
|
@@ -76,16 +76,16 @@ class CompleteMessage(TypedDict):
|
|
|
76
76
|
type: Literal["complete"]
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
Message =
|
|
80
|
-
ConnectionInitMessage
|
|
81
|
-
ConnectionAckMessage
|
|
82
|
-
PingMessage
|
|
83
|
-
PongMessage
|
|
84
|
-
SubscribeMessage
|
|
85
|
-
NextMessage
|
|
86
|
-
ErrorMessage
|
|
87
|
-
CompleteMessage
|
|
88
|
-
|
|
79
|
+
Message: TypeAlias = (
|
|
80
|
+
ConnectionInitMessage
|
|
81
|
+
| ConnectionAckMessage
|
|
82
|
+
| PingMessage
|
|
83
|
+
| PongMessage
|
|
84
|
+
| SubscribeMessage
|
|
85
|
+
| NextMessage
|
|
86
|
+
| ErrorMessage
|
|
87
|
+
| CompleteMessage
|
|
88
|
+
)
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
__all__ = [
|
|
@@ -7,7 +7,6 @@ from typing import (
|
|
|
7
7
|
TYPE_CHECKING,
|
|
8
8
|
Any,
|
|
9
9
|
Generic,
|
|
10
|
-
Optional,
|
|
11
10
|
cast,
|
|
12
11
|
)
|
|
13
12
|
|
|
@@ -27,7 +26,6 @@ from strawberry.subscriptions.protocols.graphql_ws.types import (
|
|
|
27
26
|
)
|
|
28
27
|
from strawberry.types.execution import ExecutionResult, PreExecutionError
|
|
29
28
|
from strawberry.types.unset import UnsetType
|
|
30
|
-
from strawberry.utils.debug import pretty_print_graphql_operation
|
|
31
29
|
|
|
32
30
|
if TYPE_CHECKING:
|
|
33
31
|
from collections.abc import AsyncGenerator
|
|
@@ -42,21 +40,19 @@ class BaseGraphQLWSHandler(Generic[Context, RootValue]):
|
|
|
42
40
|
view: AsyncBaseHTTPView[Any, Any, Any, Any, Any, Context, RootValue],
|
|
43
41
|
websocket: AsyncWebSocketAdapter,
|
|
44
42
|
context: Context,
|
|
45
|
-
root_value:
|
|
43
|
+
root_value: RootValue | None,
|
|
46
44
|
schema: BaseSchema,
|
|
47
|
-
debug: bool,
|
|
48
45
|
keep_alive: bool,
|
|
49
|
-
keep_alive_interval:
|
|
46
|
+
keep_alive_interval: float | None,
|
|
50
47
|
) -> None:
|
|
51
48
|
self.view = view
|
|
52
49
|
self.websocket = websocket
|
|
53
50
|
self.context = context
|
|
54
51
|
self.root_value = root_value
|
|
55
52
|
self.schema = schema
|
|
56
|
-
self.debug = debug
|
|
57
53
|
self.keep_alive = keep_alive
|
|
58
54
|
self.keep_alive_interval = keep_alive_interval
|
|
59
|
-
self.keep_alive_task:
|
|
55
|
+
self.keep_alive_task: asyncio.Task | None = None
|
|
60
56
|
self.subscriptions: dict[str, AsyncGenerator] = {}
|
|
61
57
|
self.tasks: dict[str, asyncio.Task] = {}
|
|
62
58
|
|
|
@@ -139,9 +135,6 @@ class BaseGraphQLWSHandler(Generic[Context, RootValue]):
|
|
|
139
135
|
operation_name = payload.get("operationName")
|
|
140
136
|
variables = payload.get("variables")
|
|
141
137
|
|
|
142
|
-
if self.debug:
|
|
143
|
-
pretty_print_graphql_operation(operation_name, query, variables)
|
|
144
|
-
|
|
145
138
|
result_handler = self.handle_async_results(
|
|
146
139
|
operation_id, query, operation_name, variables
|
|
147
140
|
)
|
|
@@ -161,8 +154,8 @@ class BaseGraphQLWSHandler(Generic[Context, RootValue]):
|
|
|
161
154
|
self,
|
|
162
155
|
operation_id: str,
|
|
163
156
|
query: str,
|
|
164
|
-
operation_name:
|
|
165
|
-
variables:
|
|
157
|
+
operation_name: str | None,
|
|
158
|
+
variables: dict[str, object] | None,
|
|
166
159
|
) -> None:
|
|
167
160
|
try:
|
|
168
161
|
result_source = await self.schema.subscribe(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
from typing_extensions import
|
|
1
|
+
from typing import Literal, TypeAlias, TypedDict
|
|
2
|
+
from typing_extensions import NotRequired
|
|
3
3
|
|
|
4
4
|
from graphql import GraphQLFormattedError
|
|
5
5
|
|
|
@@ -69,18 +69,18 @@ class ConnectionKeepAliveMessage(TypedDict):
|
|
|
69
69
|
type: Literal["ka"]
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
OperationMessage =
|
|
73
|
-
ConnectionInitMessage
|
|
74
|
-
StartMessage
|
|
75
|
-
StopMessage
|
|
76
|
-
ConnectionTerminateMessage
|
|
77
|
-
ConnectionErrorMessage
|
|
78
|
-
ConnectionAckMessage
|
|
79
|
-
DataMessage
|
|
80
|
-
ErrorMessage
|
|
81
|
-
CompleteMessage
|
|
82
|
-
ConnectionKeepAliveMessage
|
|
83
|
-
|
|
72
|
+
OperationMessage: TypeAlias = (
|
|
73
|
+
ConnectionInitMessage
|
|
74
|
+
| StartMessage
|
|
75
|
+
| StopMessage
|
|
76
|
+
| ConnectionTerminateMessage
|
|
77
|
+
| ConnectionErrorMessage
|
|
78
|
+
| ConnectionAckMessage
|
|
79
|
+
| DataMessage
|
|
80
|
+
| ErrorMessage
|
|
81
|
+
| CompleteMessage
|
|
82
|
+
| ConnectionKeepAliveMessage
|
|
83
|
+
)
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
__all__ = [
|
strawberry/test/client.py
CHANGED
|
@@ -4,25 +4,25 @@ import json
|
|
|
4
4
|
import warnings
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
-
from typing import TYPE_CHECKING, Any,
|
|
8
|
-
from typing_extensions import
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
8
|
+
from typing_extensions import TypedDict
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
-
from collections.abc import Coroutine
|
|
11
|
+
from collections.abc import Coroutine
|
|
12
12
|
|
|
13
13
|
from graphql import GraphQLFormattedError
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@dataclass
|
|
17
17
|
class Response:
|
|
18
|
-
errors:
|
|
19
|
-
data:
|
|
20
|
-
extensions:
|
|
18
|
+
errors: list[GraphQLFormattedError] | None
|
|
19
|
+
data: dict[str, object] | None
|
|
20
|
+
extensions: dict[str, object] | None
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class Body(TypedDict, total=False):
|
|
24
24
|
query: str
|
|
25
|
-
variables:
|
|
25
|
+
variables: dict[str, object] | None
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class BaseGraphQLTestClient(ABC):
|
|
@@ -37,12 +37,12 @@ class BaseGraphQLTestClient(ABC):
|
|
|
37
37
|
def query(
|
|
38
38
|
self,
|
|
39
39
|
query: str,
|
|
40
|
-
variables:
|
|
41
|
-
headers:
|
|
42
|
-
asserts_errors:
|
|
43
|
-
files:
|
|
44
|
-
assert_no_errors:
|
|
45
|
-
) ->
|
|
40
|
+
variables: dict[str, Any] | None = None,
|
|
41
|
+
headers: dict[str, object] | None = None,
|
|
42
|
+
asserts_errors: bool | None = None,
|
|
43
|
+
files: dict[str, object] | None = None,
|
|
44
|
+
assert_no_errors: bool | None = True,
|
|
45
|
+
) -> Coroutine[Any, Any, Response] | Response:
|
|
46
46
|
body = self._build_body(query, variables, files)
|
|
47
47
|
|
|
48
48
|
resp = self.request(body, headers, files)
|
|
@@ -74,16 +74,16 @@ class BaseGraphQLTestClient(ABC):
|
|
|
74
74
|
def request(
|
|
75
75
|
self,
|
|
76
76
|
body: dict[str, object],
|
|
77
|
-
headers:
|
|
78
|
-
files:
|
|
77
|
+
headers: dict[str, object] | None = None,
|
|
78
|
+
files: dict[str, object] | None = None,
|
|
79
79
|
) -> Any:
|
|
80
80
|
raise NotImplementedError
|
|
81
81
|
|
|
82
82
|
def _build_body(
|
|
83
83
|
self,
|
|
84
84
|
query: str,
|
|
85
|
-
variables:
|
|
86
|
-
files:
|
|
85
|
+
variables: dict[str, Any] | None = None,
|
|
86
|
+
files: dict[str, object] | None = None,
|
|
87
87
|
) -> dict[str, object]:
|
|
88
88
|
body: dict[str, object] = {"query": query}
|
|
89
89
|
|
|
@@ -105,7 +105,7 @@ class BaseGraphQLTestClient(ABC):
|
|
|
105
105
|
|
|
106
106
|
@staticmethod
|
|
107
107
|
def _build_multipart_file_map(
|
|
108
|
-
variables: dict[str,
|
|
108
|
+
variables: dict[str, Any], files: dict[str, object]
|
|
109
109
|
) -> dict[str, list[str]]:
|
|
110
110
|
"""Creates the file mapping between the variables and the files objects passed as key arguments.
|
|
111
111
|
|
strawberry/tools/create_type.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import types
|
|
2
2
|
from collections.abc import Sequence
|
|
3
|
-
from typing import Optional
|
|
4
3
|
|
|
5
4
|
import strawberry
|
|
6
5
|
from strawberry.types.field import StrawberryField
|
|
@@ -11,8 +10,8 @@ def create_type(
|
|
|
11
10
|
fields: list[StrawberryField],
|
|
12
11
|
is_input: bool = False,
|
|
13
12
|
is_interface: bool = False,
|
|
14
|
-
description:
|
|
15
|
-
directives:
|
|
13
|
+
description: str | None = None,
|
|
14
|
+
directives: Sequence[object] | None = (),
|
|
16
15
|
extend: bool = False,
|
|
17
16
|
) -> type:
|
|
18
17
|
"""Create a Strawberry type from a list of StrawberryFields.
|
strawberry/types/arguments.py
CHANGED
|
@@ -6,11 +6,10 @@ from typing import (
|
|
|
6
6
|
TYPE_CHECKING,
|
|
7
7
|
Annotated,
|
|
8
8
|
Any,
|
|
9
|
-
Optional,
|
|
10
|
-
Union,
|
|
11
9
|
cast,
|
|
10
|
+
get_args,
|
|
11
|
+
get_origin,
|
|
12
12
|
)
|
|
13
|
-
from typing_extensions import get_args, get_origin
|
|
14
13
|
|
|
15
14
|
from strawberry.annotation import StrawberryAnnotation
|
|
16
15
|
from strawberry.exceptions import MultipleStrawberryArgumentsError, UnsupportedTypeError
|
|
@@ -47,19 +46,19 @@ DEPRECATED_NAMES: dict[str, str] = {
|
|
|
47
46
|
|
|
48
47
|
|
|
49
48
|
class StrawberryArgumentAnnotation:
|
|
50
|
-
description:
|
|
51
|
-
name:
|
|
52
|
-
deprecation_reason:
|
|
49
|
+
description: str | None
|
|
50
|
+
name: str | None
|
|
51
|
+
deprecation_reason: str | None
|
|
53
52
|
directives: Iterable[object]
|
|
54
53
|
metadata: Mapping[Any, Any]
|
|
55
54
|
|
|
56
55
|
def __init__(
|
|
57
56
|
self,
|
|
58
|
-
description:
|
|
59
|
-
name:
|
|
60
|
-
deprecation_reason:
|
|
57
|
+
description: str | None = None,
|
|
58
|
+
name: str | None = None,
|
|
59
|
+
deprecation_reason: str | None = None,
|
|
61
60
|
directives: Iterable[object] = (),
|
|
62
|
-
metadata:
|
|
61
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
63
62
|
) -> None:
|
|
64
63
|
self.description = description
|
|
65
64
|
self.name = name
|
|
@@ -72,14 +71,14 @@ class StrawberryArgument:
|
|
|
72
71
|
def __init__(
|
|
73
72
|
self,
|
|
74
73
|
python_name: str,
|
|
75
|
-
graphql_name:
|
|
74
|
+
graphql_name: str | None,
|
|
76
75
|
type_annotation: StrawberryAnnotation,
|
|
77
76
|
is_subscription: bool = False,
|
|
78
|
-
description:
|
|
77
|
+
description: str | None = None,
|
|
79
78
|
default: object = _deprecated_UNSET,
|
|
80
|
-
deprecation_reason:
|
|
79
|
+
deprecation_reason: str | None = None,
|
|
81
80
|
directives: Iterable[object] = (),
|
|
82
|
-
metadata:
|
|
81
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
83
82
|
) -> None:
|
|
84
83
|
self.python_name = python_name
|
|
85
84
|
self.graphql_name = graphql_name
|
|
@@ -130,7 +129,7 @@ class StrawberryArgument:
|
|
|
130
129
|
)
|
|
131
130
|
|
|
132
131
|
@property
|
|
133
|
-
def type(self) ->
|
|
132
|
+
def type(self) -> StrawberryType | type:
|
|
134
133
|
return self.type_annotation.resolve()
|
|
135
134
|
|
|
136
135
|
@property
|
|
@@ -145,8 +144,8 @@ class StrawberryArgument:
|
|
|
145
144
|
|
|
146
145
|
|
|
147
146
|
def _is_leaf_type(
|
|
148
|
-
type_:
|
|
149
|
-
scalar_registry: Mapping[object,
|
|
147
|
+
type_: StrawberryType | type,
|
|
148
|
+
scalar_registry: Mapping[object, ScalarWrapper | ScalarDefinition],
|
|
150
149
|
skip_classes: tuple[type, ...] = (),
|
|
151
150
|
) -> bool:
|
|
152
151
|
if type_ in skip_classes:
|
|
@@ -169,8 +168,8 @@ def _is_leaf_type(
|
|
|
169
168
|
|
|
170
169
|
|
|
171
170
|
def _is_optional_leaf_type(
|
|
172
|
-
type_:
|
|
173
|
-
scalar_registry: Mapping[object,
|
|
171
|
+
type_: StrawberryType | type,
|
|
172
|
+
scalar_registry: Mapping[object, ScalarWrapper | ScalarDefinition],
|
|
174
173
|
skip_classes: tuple[type, ...] = (),
|
|
175
174
|
) -> bool:
|
|
176
175
|
if type_ in skip_classes:
|
|
@@ -184,17 +183,31 @@ def _is_optional_leaf_type(
|
|
|
184
183
|
|
|
185
184
|
def convert_argument(
|
|
186
185
|
value: object,
|
|
187
|
-
type_:
|
|
188
|
-
scalar_registry: Mapping[object,
|
|
186
|
+
type_: StrawberryType | type,
|
|
187
|
+
scalar_registry: Mapping[object, ScalarWrapper | ScalarDefinition],
|
|
189
188
|
config: StrawberryConfig,
|
|
190
189
|
) -> object:
|
|
191
190
|
from strawberry.relay.types import GlobalID
|
|
192
191
|
|
|
193
192
|
# TODO: move this somewhere else and make it first class
|
|
194
|
-
|
|
193
|
+
# Handle StrawberryMaybe first, since it extends StrawberryOptional
|
|
194
|
+
if isinstance(type_, StrawberryMaybe):
|
|
195
|
+
# Check if this is Maybe[T | None] (has StrawberryOptional as of_type)
|
|
196
|
+
if isinstance(type_.of_type, StrawberryOptional):
|
|
197
|
+
# This is Maybe[T | None] - allows null values
|
|
198
|
+
res = convert_argument(value, type_.of_type, scalar_registry, config)
|
|
199
|
+
|
|
200
|
+
return Some(res)
|
|
201
|
+
|
|
202
|
+
# This is Maybe[T] - validation for null values is handled by MaybeNullValidationRule
|
|
203
|
+
# Convert the value and wrap in Some()
|
|
195
204
|
res = convert_argument(value, type_.of_type, scalar_registry, config)
|
|
196
205
|
|
|
197
|
-
return Some(res)
|
|
206
|
+
return Some(res)
|
|
207
|
+
|
|
208
|
+
# Handle regular StrawberryOptional (not Maybe)
|
|
209
|
+
if isinstance(type_, StrawberryOptional):
|
|
210
|
+
return convert_argument(value, type_.of_type, scalar_registry, config)
|
|
198
211
|
|
|
199
212
|
if value is None:
|
|
200
213
|
return None
|
|
@@ -257,7 +270,7 @@ def convert_argument(
|
|
|
257
270
|
def convert_arguments(
|
|
258
271
|
value: dict[str, Any],
|
|
259
272
|
arguments: list[StrawberryArgument],
|
|
260
|
-
scalar_registry: Mapping[object,
|
|
273
|
+
scalar_registry: Mapping[object, ScalarWrapper | ScalarDefinition],
|
|
261
274
|
config: StrawberryConfig,
|
|
262
275
|
) -> dict[str, Any]:
|
|
263
276
|
"""Converts a nested dictionary to a dictionary of actual types.
|
|
@@ -289,11 +302,11 @@ def convert_arguments(
|
|
|
289
302
|
|
|
290
303
|
|
|
291
304
|
def argument(
|
|
292
|
-
description:
|
|
293
|
-
name:
|
|
294
|
-
deprecation_reason:
|
|
305
|
+
description: str | None = None,
|
|
306
|
+
name: str | None = None,
|
|
307
|
+
deprecation_reason: str | None = None,
|
|
295
308
|
directives: Iterable[object] = (),
|
|
296
|
-
metadata:
|
|
309
|
+
metadata: Mapping[Any, Any] | None = None,
|
|
297
310
|
) -> StrawberryArgumentAnnotation:
|
|
298
311
|
"""Function to add metadata to an argument, like a description or deprecation reason.
|
|
299
312
|
|
strawberry/types/auto.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Annotated, Any,
|
|
4
|
-
from typing_extensions import get_args, get_origin
|
|
3
|
+
from typing import Annotated, Any, cast, get_args, get_origin
|
|
5
4
|
|
|
6
5
|
from strawberry.annotation import StrawberryAnnotation
|
|
7
6
|
from strawberry.types.base import StrawberryType
|
|
@@ -24,7 +23,7 @@ class StrawberryAutoMeta(type):
|
|
|
24
23
|
"""
|
|
25
24
|
|
|
26
25
|
def __init__(cls, *args: str, **kwargs: Any) -> None:
|
|
27
|
-
cls._instance:
|
|
26
|
+
cls._instance: StrawberryAuto | None = None
|
|
28
27
|
super().__init__(*args, **kwargs)
|
|
29
28
|
|
|
30
29
|
def __call__(cls, *args: str, **kwargs: Any) -> Any:
|
|
@@ -35,7 +34,7 @@ class StrawberryAutoMeta(type):
|
|
|
35
34
|
|
|
36
35
|
def __instancecheck__(
|
|
37
36
|
cls,
|
|
38
|
-
instance:
|
|
37
|
+
instance: StrawberryAuto | StrawberryAnnotation | StrawberryType | type,
|
|
39
38
|
) -> bool:
|
|
40
39
|
if isinstance(instance, StrawberryAnnotation):
|
|
41
40
|
resolved = instance.raw_annotation
|
strawberry/types/base.py
CHANGED
|
@@ -5,14 +5,12 @@ from abc import ABC, abstractmethod
|
|
|
5
5
|
from typing import (
|
|
6
6
|
TYPE_CHECKING,
|
|
7
7
|
Any,
|
|
8
|
-
Callable,
|
|
9
8
|
ClassVar,
|
|
10
|
-
|
|
9
|
+
Literal,
|
|
11
10
|
TypeVar,
|
|
12
|
-
Union,
|
|
13
11
|
overload,
|
|
14
12
|
)
|
|
15
|
-
from typing_extensions import
|
|
13
|
+
from typing_extensions import Protocol, Self, deprecated
|
|
16
14
|
|
|
17
15
|
from strawberry.utils.deprecations import DEPRECATION_MESSAGES, DeprecatedDescriptor
|
|
18
16
|
from strawberry.utils.inspect import get_specialized_type_var_map
|
|
@@ -20,8 +18,8 @@ from strawberry.utils.typing import is_concrete_generic
|
|
|
20
18
|
from strawberry.utils.typing import is_generic as is_type_generic
|
|
21
19
|
|
|
22
20
|
if TYPE_CHECKING:
|
|
23
|
-
from collections.abc import Mapping, Sequence
|
|
24
|
-
from
|
|
21
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
22
|
+
from typing import TypeGuard
|
|
25
23
|
|
|
26
24
|
from graphql import GraphQLAbstractType, GraphQLResolveInfo
|
|
27
25
|
|
|
@@ -51,9 +49,9 @@ class StrawberryType(ABC):
|
|
|
51
49
|
def copy_with(
|
|
52
50
|
self,
|
|
53
51
|
type_var_map: Mapping[
|
|
54
|
-
str,
|
|
52
|
+
str, StrawberryType | type[WithStrawberryObjectDefinition]
|
|
55
53
|
],
|
|
56
|
-
) ->
|
|
54
|
+
) -> StrawberryType | type[WithStrawberryObjectDefinition]:
|
|
57
55
|
raise NotImplementedError
|
|
58
56
|
|
|
59
57
|
@property
|
|
@@ -87,7 +85,7 @@ class StrawberryType(ABC):
|
|
|
87
85
|
|
|
88
86
|
class StrawberryContainer(StrawberryType):
|
|
89
87
|
def __init__(
|
|
90
|
-
self, of_type:
|
|
88
|
+
self, of_type: StrawberryType | type[WithStrawberryObjectDefinition] | type
|
|
91
89
|
) -> None:
|
|
92
90
|
self.of_type = of_type
|
|
93
91
|
|
|
@@ -117,7 +115,7 @@ class StrawberryContainer(StrawberryType):
|
|
|
117
115
|
def copy_with(
|
|
118
116
|
self,
|
|
119
117
|
type_var_map: Mapping[
|
|
120
|
-
str,
|
|
118
|
+
str, StrawberryType | type[WithStrawberryObjectDefinition]
|
|
121
119
|
],
|
|
122
120
|
) -> Self:
|
|
123
121
|
of_type_copy = self.of_type
|
|
@@ -155,7 +153,7 @@ class StrawberryList(StrawberryContainer): ...
|
|
|
155
153
|
class StrawberryOptional(StrawberryContainer):
|
|
156
154
|
def __init__(
|
|
157
155
|
self,
|
|
158
|
-
of_type:
|
|
156
|
+
of_type: StrawberryType | type[WithStrawberryObjectDefinition] | type,
|
|
159
157
|
) -> None:
|
|
160
158
|
super().__init__(of_type)
|
|
161
159
|
|
|
@@ -169,8 +167,8 @@ class StrawberryTypeVar(StrawberryType):
|
|
|
169
167
|
self.type_var = type_var
|
|
170
168
|
|
|
171
169
|
def copy_with(
|
|
172
|
-
self, type_var_map: Mapping[str,
|
|
173
|
-
) ->
|
|
170
|
+
self, type_var_map: Mapping[str, StrawberryType | type]
|
|
171
|
+
) -> StrawberryType | type:
|
|
174
172
|
return type_var_map[self.type_var.__name__]
|
|
175
173
|
|
|
176
174
|
@property
|
|
@@ -229,14 +227,14 @@ def get_object_definition(
|
|
|
229
227
|
obj: Any,
|
|
230
228
|
*,
|
|
231
229
|
strict: bool = False,
|
|
232
|
-
) ->
|
|
230
|
+
) -> StrawberryObjectDefinition | None: ...
|
|
233
231
|
|
|
234
232
|
|
|
235
233
|
def get_object_definition(
|
|
236
234
|
obj: Any,
|
|
237
235
|
*,
|
|
238
236
|
strict: bool = False,
|
|
239
|
-
) ->
|
|
237
|
+
) -> StrawberryObjectDefinition | None:
|
|
240
238
|
definition = obj.__strawberry_definition__ if has_object_definition(obj) else None
|
|
241
239
|
if strict and definition is None:
|
|
242
240
|
raise TypeError(f"{obj!r} does not have a StrawberryObjectDefinition")
|
|
@@ -256,20 +254,18 @@ class StrawberryObjectDefinition(StrawberryType):
|
|
|
256
254
|
is_input: bool
|
|
257
255
|
is_interface: bool
|
|
258
256
|
origin: type[Any]
|
|
259
|
-
description:
|
|
257
|
+
description: str | None
|
|
260
258
|
interfaces: list[StrawberryObjectDefinition]
|
|
261
259
|
extend: bool
|
|
262
|
-
directives:
|
|
263
|
-
is_type_of:
|
|
264
|
-
resolve_type:
|
|
265
|
-
Callable[[Any, GraphQLResolveInfo, GraphQLAbstractType], str]
|
|
266
|
-
]
|
|
260
|
+
directives: Sequence[object] | None
|
|
261
|
+
is_type_of: Callable[[Any, GraphQLResolveInfo], bool] | None
|
|
262
|
+
resolve_type: Callable[[Any, GraphQLResolveInfo, GraphQLAbstractType], str] | None
|
|
267
263
|
|
|
268
264
|
fields: list[StrawberryField]
|
|
269
265
|
|
|
270
|
-
concrete_of:
|
|
266
|
+
concrete_of: StrawberryObjectDefinition | None = None
|
|
271
267
|
"""Concrete implementations of Generic TypeDefinitions fill this in"""
|
|
272
|
-
type_var_map: Mapping[str,
|
|
268
|
+
type_var_map: Mapping[str, StrawberryType | type] = dataclasses.field(
|
|
273
269
|
default_factory=dict
|
|
274
270
|
)
|
|
275
271
|
|
|
@@ -291,12 +287,14 @@ class StrawberryObjectDefinition(StrawberryType):
|
|
|
291
287
|
resolved_type = StrawberryAnnotation(passed_type).resolve()
|
|
292
288
|
resolved_types.append(resolved_type)
|
|
293
289
|
|
|
294
|
-
type_var_map = dict(
|
|
290
|
+
type_var_map = dict(
|
|
291
|
+
zip((param.__name__ for param in params), resolved_types, strict=True)
|
|
292
|
+
)
|
|
295
293
|
|
|
296
294
|
return self.copy_with(type_var_map)
|
|
297
295
|
|
|
298
296
|
def copy_with(
|
|
299
|
-
self, type_var_map: Mapping[str,
|
|
297
|
+
self, type_var_map: Mapping[str, StrawberryType | type]
|
|
300
298
|
) -> type[WithStrawberryObjectDefinition]:
|
|
301
299
|
fields = [field.copy_with(type_var_map) for field in self.fields]
|
|
302
300
|
|
|
@@ -332,7 +330,7 @@ class StrawberryObjectDefinition(StrawberryType):
|
|
|
332
330
|
|
|
333
331
|
return new_type
|
|
334
332
|
|
|
335
|
-
def get_field(self, python_name: str) ->
|
|
333
|
+
def get_field(self, python_name: str) -> StrawberryField | None:
|
|
336
334
|
return next(
|
|
337
335
|
(field for field in self.fields if field.python_name == python_name), None
|
|
338
336
|
)
|
|
@@ -354,7 +352,7 @@ class StrawberryObjectDefinition(StrawberryType):
|
|
|
354
352
|
)
|
|
355
353
|
|
|
356
354
|
@property
|
|
357
|
-
def specialized_type_var_map(self) ->
|
|
355
|
+
def specialized_type_var_map(self) -> dict[str, type] | None:
|
|
358
356
|
return get_specialized_type_var_map(self.origin)
|
|
359
357
|
|
|
360
358
|
@property
|