strawberry-graphql 0.257.0.dev1735244504__py3-none-any.whl → 0.258.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- strawberry/__init__.py +2 -0
- strawberry/aiohttp/test/client.py +1 -3
- strawberry/aiohttp/views.py +3 -3
- strawberry/annotation.py +5 -7
- strawberry/asgi/__init__.py +4 -4
- strawberry/channels/handlers/ws_handler.py +3 -3
- strawberry/channels/testing.py +3 -1
- strawberry/cli/__init__.py +7 -5
- strawberry/cli/commands/codegen.py +12 -14
- strawberry/cli/commands/server.py +2 -2
- strawberry/cli/commands/upgrade/_run_codemod.py +2 -3
- strawberry/cli/utils/__init__.py +1 -1
- strawberry/codegen/plugins/python.py +4 -5
- strawberry/codegen/plugins/typescript.py +3 -2
- strawberry/codegen/query_codegen.py +12 -11
- strawberry/codemods/annotated_unions.py +1 -1
- strawberry/codemods/update_imports.py +2 -4
- strawberry/dataloader.py +2 -2
- strawberry/django/__init__.py +2 -2
- strawberry/django/views.py +2 -3
- strawberry/exceptions/__init__.py +4 -2
- strawberry/exceptions/exception.py +1 -1
- strawberry/exceptions/permission_fail_silently_requires_optional.py +2 -1
- strawberry/exceptions/utils/source_finder.py +1 -1
- strawberry/experimental/pydantic/_compat.py +4 -4
- strawberry/experimental/pydantic/conversion.py +4 -5
- strawberry/experimental/pydantic/fields.py +1 -2
- strawberry/experimental/pydantic/object_type.py +6 -2
- strawberry/experimental/pydantic/utils.py +3 -9
- strawberry/ext/mypy_plugin.py +7 -14
- strawberry/extensions/context.py +15 -19
- strawberry/extensions/field_extension.py +53 -54
- strawberry/extensions/query_depth_limiter.py +27 -33
- strawberry/extensions/tracing/datadog.py +1 -1
- strawberry/extensions/tracing/opentelemetry.py +9 -14
- strawberry/fastapi/router.py +2 -3
- strawberry/federation/schema.py +3 -3
- strawberry/flask/views.py +3 -2
- strawberry/http/async_base_view.py +2 -4
- strawberry/http/ides.py +1 -3
- strawberry/http/sync_base_view.py +1 -2
- strawberry/litestar/controller.py +6 -5
- strawberry/permission.py +1 -1
- strawberry/quart/views.py +2 -2
- strawberry/relay/fields.py +38 -4
- strawberry/relay/types.py +6 -1
- strawberry/relay/utils.py +6 -1
- strawberry/schema/base.py +0 -2
- strawberry/schema/execute.py +11 -11
- strawberry/schema/name_converter.py +4 -5
- strawberry/schema/schema.py +6 -4
- strawberry/schema/schema_converter.py +24 -19
- strawberry/schema/subscribe.py +4 -4
- strawberry/schema/types/base_scalars.py +4 -2
- strawberry/schema/types/scalar.py +1 -1
- strawberry/schema_codegen/__init__.py +5 -6
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +2 -2
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +0 -3
- strawberry/test/client.py +1 -2
- strawberry/types/arguments.py +2 -2
- strawberry/types/auto.py +3 -3
- strawberry/types/base.py +12 -16
- strawberry/types/cast.py +35 -0
- strawberry/types/field.py +11 -7
- strawberry/types/fields/resolver.py +12 -19
- strawberry/types/union.py +1 -1
- strawberry/types/unset.py +1 -2
- strawberry/utils/debug.py +1 -1
- strawberry/utils/deprecations.py +1 -1
- strawberry/utils/graphql_lexer.py +6 -4
- strawberry/utils/typing.py +1 -2
- {strawberry_graphql-0.257.0.dev1735244504.dist-info → strawberry_graphql-0.258.0.dist-info}/METADATA +3 -3
- {strawberry_graphql-0.257.0.dev1735244504.dist-info → strawberry_graphql-0.258.0.dist-info}/RECORD +76 -75
- {strawberry_graphql-0.257.0.dev1735244504.dist-info → strawberry_graphql-0.258.0.dist-info}/WHEEL +1 -1
- {strawberry_graphql-0.257.0.dev1735244504.dist-info → strawberry_graphql-0.258.0.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.257.0.dev1735244504.dist-info → strawberry_graphql-0.258.0.dist-info}/entry_points.txt +0 -0
strawberry/relay/fields.py
CHANGED
@@ -37,6 +37,7 @@ from strawberry.relay.exceptions import (
|
|
37
37
|
)
|
38
38
|
from strawberry.types.arguments import StrawberryArgument, argument
|
39
39
|
from strawberry.types.base import StrawberryList, StrawberryOptional
|
40
|
+
from strawberry.types.cast import cast as strawberry_cast
|
40
41
|
from strawberry.types.field import _RESOLVER_TYPE, StrawberryField, field
|
41
42
|
from strawberry.types.fields.resolver import StrawberryResolver
|
42
43
|
from strawberry.types.lazy_type import LazyType
|
@@ -88,12 +89,27 @@ class NodeExtension(FieldExtension):
|
|
88
89
|
info: Info,
|
89
90
|
id: Annotated[GlobalID, argument(description="The ID of the object.")],
|
90
91
|
) -> Union[Node, None, Awaitable[Union[Node, None]]]:
|
91
|
-
|
92
|
+
node_type = id.resolve_type(info)
|
93
|
+
resolved_node = node_type.resolve_node(
|
92
94
|
id.node_id,
|
93
95
|
info=info,
|
94
96
|
required=not is_optional,
|
95
97
|
)
|
96
98
|
|
99
|
+
# We are using `strawberry_cast` here to cast the resolved node to make
|
100
|
+
# sure `is_type_of` will not try to find its type again. Very important
|
101
|
+
# when returning a non type (e.g. Django/SQLAlchemy/Pydantic model), as
|
102
|
+
# we could end up resolving to a different type in case more than one
|
103
|
+
# are registered.
|
104
|
+
if inspect.isawaitable(resolved_node):
|
105
|
+
|
106
|
+
async def resolve() -> Any:
|
107
|
+
return strawberry_cast(node_type, await resolved_node)
|
108
|
+
|
109
|
+
return resolve()
|
110
|
+
|
111
|
+
return cast(Node, strawberry_cast(node_type, resolved_node))
|
112
|
+
|
97
113
|
return resolver
|
98
114
|
|
99
115
|
def get_node_list_resolver(
|
@@ -139,6 +155,14 @@ class NodeExtension(FieldExtension):
|
|
139
155
|
if inspect.isasyncgen(nodes)
|
140
156
|
}
|
141
157
|
|
158
|
+
# We are using `strawberry_cast` here to cast the resolved node to make
|
159
|
+
# sure `is_type_of` will not try to find its type again. Very important
|
160
|
+
# when returning a non type (e.g. Django/SQLAlchemy/Pydantic model), as
|
161
|
+
# we could end up resolving to a different type in case more than one
|
162
|
+
# are registered
|
163
|
+
def cast_nodes(node_t: type[Node], nodes: Iterable[Any]) -> list[Node]:
|
164
|
+
return [cast(Node, strawberry_cast(node_t, node)) for node in nodes]
|
165
|
+
|
142
166
|
if awaitable_nodes or asyncgen_nodes:
|
143
167
|
|
144
168
|
async def resolve(resolved: Any = resolved_nodes) -> list[Node]:
|
@@ -161,7 +185,8 @@ class NodeExtension(FieldExtension):
|
|
161
185
|
|
162
186
|
# Resolve any generator to lists
|
163
187
|
resolved = {
|
164
|
-
node_t:
|
188
|
+
node_t: cast_nodes(node_t, nodes)
|
189
|
+
for node_t, nodes in resolved.items()
|
165
190
|
}
|
166
191
|
return [
|
167
192
|
resolved[index_map[gid][0]][index_map[gid][1]] for gid in ids
|
@@ -171,7 +196,7 @@ class NodeExtension(FieldExtension):
|
|
171
196
|
|
172
197
|
# Resolve any generator to lists
|
173
198
|
resolved = {
|
174
|
-
node_t:
|
199
|
+
node_t: cast_nodes(node_t, cast(Iterable[Node], nodes))
|
175
200
|
for node_t, nodes in resolved_nodes.items()
|
176
201
|
}
|
177
202
|
return [resolved[index_map[gid][0]][index_map[gid][1]] for gid in ids]
|
@@ -182,6 +207,9 @@ class NodeExtension(FieldExtension):
|
|
182
207
|
class ConnectionExtension(FieldExtension):
|
183
208
|
connection_type: type[Connection[Node]]
|
184
209
|
|
210
|
+
def __init__(self, max_results: Optional[int] = None) -> None:
|
211
|
+
self.max_results = max_results
|
212
|
+
|
185
213
|
def apply(self, field: StrawberryField) -> None:
|
186
214
|
field.arguments = [
|
187
215
|
*field.arguments,
|
@@ -288,6 +316,7 @@ class ConnectionExtension(FieldExtension):
|
|
288
316
|
after=after,
|
289
317
|
first=first,
|
290
318
|
last=last,
|
319
|
+
max_results=self.max_results,
|
291
320
|
)
|
292
321
|
|
293
322
|
async def resolve_async(
|
@@ -316,6 +345,7 @@ class ConnectionExtension(FieldExtension):
|
|
316
345
|
after=after,
|
317
346
|
first=first,
|
318
347
|
last=last,
|
348
|
+
max_results=self.max_results,
|
319
349
|
)
|
320
350
|
|
321
351
|
# If nodes was an AsyncIterable/AsyncIterator, resolve_connection
|
@@ -357,6 +387,7 @@ def connection(
|
|
357
387
|
metadata: Optional[Mapping[Any, Any]] = None,
|
358
388
|
directives: Optional[Sequence[object]] = (),
|
359
389
|
extensions: list[FieldExtension] = (), # type: ignore
|
390
|
+
max_results: Optional[int] = None,
|
360
391
|
# This init parameter is used by pyright to determine whether this field
|
361
392
|
# is added in the constructor or not. It is not used to change
|
362
393
|
# any behaviour at the moment.
|
@@ -389,6 +420,9 @@ def connection(
|
|
389
420
|
metadata: The metadata of the field.
|
390
421
|
directives: The directives to apply to the field.
|
391
422
|
extensions: The extensions to apply to the field.
|
423
|
+
max_results: The maximum number of results this connection can return.
|
424
|
+
Can be set to override the default value of 100 defined in the
|
425
|
+
schema configuration.
|
392
426
|
init: Used only for type checking purposes.
|
393
427
|
|
394
428
|
Examples:
|
@@ -451,7 +485,7 @@ def connection(
|
|
451
485
|
default_factory=default_factory,
|
452
486
|
metadata=metadata,
|
453
487
|
directives=directives or (),
|
454
|
-
extensions=[*extensions, ConnectionExtension()],
|
488
|
+
extensions=[*extensions, ConnectionExtension(max_results=max_results)],
|
455
489
|
)
|
456
490
|
if resolver is not None:
|
457
491
|
f = f(resolver)
|
strawberry/relay/types.py
CHANGED
@@ -717,6 +717,7 @@ class Connection(Generic[NodeType]):
|
|
717
717
|
after: Optional[str] = None,
|
718
718
|
first: Optional[int] = None,
|
719
719
|
last: Optional[int] = None,
|
720
|
+
max_results: Optional[int] = None,
|
720
721
|
**kwargs: Any,
|
721
722
|
) -> AwaitableOrValue[Self]:
|
722
723
|
"""Resolve a connection from nodes.
|
@@ -731,6 +732,7 @@ class Connection(Generic[NodeType]):
|
|
731
732
|
after: Returns the items in the list that come after the specified cursor.
|
732
733
|
first: Returns the first n items from the list.
|
733
734
|
last: Returns the items in the list that come after the specified cursor.
|
735
|
+
max_results: The maximum number of results to resolve.
|
734
736
|
kwargs: Additional arguments passed to the resolver.
|
735
737
|
|
736
738
|
Returns:
|
@@ -758,7 +760,7 @@ class ListConnection(Connection[NodeType]):
|
|
758
760
|
)
|
759
761
|
|
760
762
|
@classmethod
|
761
|
-
def resolve_connection(
|
763
|
+
def resolve_connection( # noqa: PLR0915
|
762
764
|
cls,
|
763
765
|
nodes: NodeIterableType[NodeType],
|
764
766
|
*,
|
@@ -767,6 +769,7 @@ class ListConnection(Connection[NodeType]):
|
|
767
769
|
after: Optional[str] = None,
|
768
770
|
first: Optional[int] = None,
|
769
771
|
last: Optional[int] = None,
|
772
|
+
max_results: Optional[int] = None,
|
770
773
|
**kwargs: Any,
|
771
774
|
) -> AwaitableOrValue[Self]:
|
772
775
|
"""Resolve a connection from the list of nodes.
|
@@ -780,6 +783,7 @@ class ListConnection(Connection[NodeType]):
|
|
780
783
|
after: Returns the items in the list that come after the specified cursor.
|
781
784
|
first: Returns the first n items from the list.
|
782
785
|
last: Returns the items in the list that come after the specified cursor.
|
786
|
+
max_results: The maximum number of results to resolve.
|
783
787
|
kwargs: Additional arguments passed to the resolver.
|
784
788
|
|
785
789
|
Returns:
|
@@ -794,6 +798,7 @@ class ListConnection(Connection[NodeType]):
|
|
794
798
|
after=after,
|
795
799
|
first=first,
|
796
800
|
last=last,
|
801
|
+
max_results=max_results,
|
797
802
|
)
|
798
803
|
|
799
804
|
type_def = get_object_definition(cls)
|
strawberry/relay/utils.py
CHANGED
@@ -131,11 +131,16 @@ class SliceMetadata:
|
|
131
131
|
after: str | None = None,
|
132
132
|
first: int | None = None,
|
133
133
|
last: int | None = None,
|
134
|
+
max_results: int | None = None,
|
134
135
|
) -> Self:
|
135
136
|
"""Get the slice metadata to use on ListConnection."""
|
136
137
|
from strawberry.relay.types import PREFIX
|
137
138
|
|
138
|
-
max_results =
|
139
|
+
max_results = (
|
140
|
+
max_results
|
141
|
+
if max_results is not None
|
142
|
+
else info.schema.config.relay_max_results
|
143
|
+
)
|
139
144
|
start = 0
|
140
145
|
end: int | None = None
|
141
146
|
|
strawberry/schema/base.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from abc import abstractmethod
|
4
|
-
from functools import lru_cache
|
5
4
|
from typing import TYPE_CHECKING, Any, Optional, Union
|
6
5
|
from typing_extensions import Protocol
|
7
6
|
|
@@ -88,7 +87,6 @@ class BaseSchema(Protocol):
|
|
88
87
|
raise NotImplementedError
|
89
88
|
|
90
89
|
@abstractmethod
|
91
|
-
@lru_cache
|
92
90
|
def get_directive_by_name(self, graphql_name: str) -> Optional[StrawberryDirective]:
|
93
91
|
raise NotImplementedError
|
94
92
|
|
strawberry/schema/execute.py
CHANGED
@@ -85,7 +85,7 @@ async def _parse_and_validate_async(
|
|
85
85
|
context: ExecutionContext, extensions_runner: SchemaExtensionsRunner
|
86
86
|
) -> Optional[PreExecutionError]:
|
87
87
|
if not context.query:
|
88
|
-
raise MissingQueryError
|
88
|
+
raise MissingQueryError
|
89
89
|
|
90
90
|
async with extensions_runner.parsing():
|
91
91
|
try:
|
@@ -96,7 +96,7 @@ async def _parse_and_validate_async(
|
|
96
96
|
context.errors = [error]
|
97
97
|
return PreExecutionError(data=None, errors=[error])
|
98
98
|
|
99
|
-
except Exception as error:
|
99
|
+
except Exception as error: # noqa: BLE001
|
100
100
|
error = GraphQLError(str(error), original_error=error)
|
101
101
|
context.errors = [error]
|
102
102
|
return PreExecutionError(data=None, errors=[error])
|
@@ -189,9 +189,9 @@ async def execute(
|
|
189
189
|
# only return a sanitised version to the client.
|
190
190
|
process_errors(result.errors, execution_context)
|
191
191
|
|
192
|
-
except (MissingQueryError, InvalidOperationTypeError)
|
193
|
-
raise
|
194
|
-
except Exception as exc:
|
192
|
+
except (MissingQueryError, InvalidOperationTypeError):
|
193
|
+
raise
|
194
|
+
except Exception as exc: # noqa: BLE001
|
195
195
|
return await _handle_execution_result(
|
196
196
|
execution_context,
|
197
197
|
PreExecutionError(data=None, errors=[_coerce_error(exc)]),
|
@@ -219,7 +219,7 @@ def execute_sync(
|
|
219
219
|
# Note: In graphql-core the schema would be validated here but in
|
220
220
|
# Strawberry we are validating it at initialisation time instead
|
221
221
|
if not execution_context.query:
|
222
|
-
raise MissingQueryError
|
222
|
+
raise MissingQueryError # noqa: TRY301
|
223
223
|
|
224
224
|
with extensions_runner.parsing():
|
225
225
|
try:
|
@@ -238,7 +238,7 @@ def execute_sync(
|
|
238
238
|
)
|
239
239
|
|
240
240
|
if execution_context.operation_type not in allowed_operation_types:
|
241
|
-
raise InvalidOperationTypeError(execution_context.operation_type)
|
241
|
+
raise InvalidOperationTypeError(execution_context.operation_type) # noqa: TRY301
|
242
242
|
|
243
243
|
with extensions_runner.validation():
|
244
244
|
_run_validation(execution_context)
|
@@ -266,7 +266,7 @@ def execute_sync(
|
|
266
266
|
if isawaitable(result):
|
267
267
|
result = cast(Awaitable[GraphQLExecutionResult], result) # type: ignore[redundant-cast]
|
268
268
|
ensure_future(result).cancel()
|
269
|
-
raise RuntimeError(
|
269
|
+
raise RuntimeError( # noqa: TRY301
|
270
270
|
"GraphQL execution failed to complete synchronously."
|
271
271
|
)
|
272
272
|
|
@@ -282,9 +282,9 @@ def execute_sync(
|
|
282
282
|
# extension). That way we can log the original errors but
|
283
283
|
# only return a sanitised version to the client.
|
284
284
|
process_errors(result.errors, execution_context)
|
285
|
-
except (MissingQueryError, InvalidOperationTypeError)
|
286
|
-
raise
|
287
|
-
except Exception as exc:
|
285
|
+
except (MissingQueryError, InvalidOperationTypeError):
|
286
|
+
raise
|
287
|
+
except Exception as exc: # noqa: BLE001
|
288
288
|
errors = [_coerce_error(exc)]
|
289
289
|
execution_context.errors = errors
|
290
290
|
process_errors(errors, execution_context)
|
@@ -47,18 +47,17 @@ class NameConverter:
|
|
47
47
|
return self.from_directive(type_)
|
48
48
|
if isinstance(type_, EnumDefinition): # TODO: Replace with StrawberryEnum
|
49
49
|
return self.from_enum(type_)
|
50
|
-
|
50
|
+
if isinstance(type_, StrawberryObjectDefinition):
|
51
51
|
if type_.is_input:
|
52
52
|
return self.from_input_object(type_)
|
53
53
|
if type_.is_interface:
|
54
54
|
return self.from_interface(type_)
|
55
55
|
return self.from_object(type_)
|
56
|
-
|
56
|
+
if isinstance(type_, StrawberryUnion):
|
57
57
|
return self.from_union(type_)
|
58
|
-
|
58
|
+
if isinstance(type_, ScalarDefinition): # TODO: Replace with StrawberryScalar
|
59
59
|
return self.from_scalar(type_)
|
60
|
-
|
61
|
-
return str(type_)
|
60
|
+
return str(type_)
|
62
61
|
|
63
62
|
def from_argument(self, argument: StrawberryArgument) -> str:
|
64
63
|
return self.get_graphql_name(argument)
|
strawberry/schema/schema.py
CHANGED
@@ -30,6 +30,7 @@ from strawberry.extensions.directives import (
|
|
30
30
|
DirectivesExtensionSync,
|
31
31
|
)
|
32
32
|
from strawberry.extensions.runner import SchemaExtensionsRunner
|
33
|
+
from strawberry.printer import print_schema
|
33
34
|
from strawberry.schema.schema_converter import GraphQLCoreConverter
|
34
35
|
from strawberry.schema.types.scalar import DEFAULT_SCALAR_REGISTRY
|
35
36
|
from strawberry.types import ExecutionContext
|
@@ -40,7 +41,6 @@ from strawberry.types.base import (
|
|
40
41
|
)
|
41
42
|
from strawberry.types.graphql import OperationType
|
42
43
|
|
43
|
-
from ..printer import print_schema
|
44
44
|
from . import compat
|
45
45
|
from .base import BaseSchema
|
46
46
|
from .config import StrawberryConfig
|
@@ -177,9 +177,11 @@ class Schema(BaseSchema):
|
|
177
177
|
self.schema_converter.from_schema_directive(type_)
|
178
178
|
)
|
179
179
|
else:
|
180
|
-
if
|
181
|
-
|
182
|
-
|
180
|
+
if (
|
181
|
+
has_object_definition(type_)
|
182
|
+
and type_.__strawberry_definition__.is_graphql_generic
|
183
|
+
):
|
184
|
+
type_ = StrawberryAnnotation(type_).resolve() # noqa: PLW2901
|
183
185
|
graphql_type = self.schema_converter.from_maybe_optional(type_)
|
184
186
|
if isinstance(graphql_type, GraphQLNonNull):
|
185
187
|
graphql_type = graphql_type.of_type
|
@@ -47,6 +47,7 @@ from strawberry.exceptions import (
|
|
47
47
|
ScalarAlreadyRegisteredError,
|
48
48
|
UnresolvedFieldTypeError,
|
49
49
|
)
|
50
|
+
from strawberry.extensions.field_extension import build_field_extension_resolvers
|
50
51
|
from strawberry.schema.types.scalar import _make_scalar_type
|
51
52
|
from strawberry.types.arguments import StrawberryArgument, convert_arguments
|
52
53
|
from strawberry.types.base import (
|
@@ -57,6 +58,7 @@ from strawberry.types.base import (
|
|
57
58
|
get_object_definition,
|
58
59
|
has_object_definition,
|
59
60
|
)
|
61
|
+
from strawberry.types.cast import get_strawberry_type_cast
|
60
62
|
from strawberry.types.enum import EnumDefinition
|
61
63
|
from strawberry.types.field import UNRESOLVED
|
62
64
|
from strawberry.types.lazy_type import LazyType
|
@@ -66,7 +68,6 @@ from strawberry.types.union import StrawberryUnion
|
|
66
68
|
from strawberry.types.unset import UNSET
|
67
69
|
from strawberry.utils.await_maybe import await_maybe
|
68
70
|
|
69
|
-
from ..extensions.field_extension import build_field_extension_resolvers
|
70
71
|
from . import compat
|
71
72
|
from .types.concrete_type import ConcreteType
|
72
73
|
|
@@ -91,7 +92,9 @@ if TYPE_CHECKING:
|
|
91
92
|
|
92
93
|
|
93
94
|
FieldType = TypeVar(
|
94
|
-
"FieldType",
|
95
|
+
"FieldType",
|
96
|
+
bound=Union[GraphQLField, GraphQLInputField],
|
97
|
+
covariant=True,
|
95
98
|
)
|
96
99
|
|
97
100
|
|
@@ -374,8 +377,6 @@ class GraphQLCoreConverter:
|
|
374
377
|
# self.from_resolver needs to be called before accessing field.type because
|
375
378
|
# in there a field extension might want to change the type during its apply
|
376
379
|
resolver = self.from_resolver(field)
|
377
|
-
# TODO: think more about this
|
378
|
-
field._resolver = resolver # type: ignore
|
379
380
|
field_type = cast(
|
380
381
|
"GraphQLOutputType",
|
381
382
|
self.from_maybe_optional(
|
@@ -619,6 +620,9 @@ class GraphQLCoreConverter:
|
|
619
620
|
)
|
620
621
|
|
621
622
|
def is_type_of(obj: Any, _info: GraphQLResolveInfo) -> bool:
|
623
|
+
if (type_cast := get_strawberry_type_cast(obj)) is not None:
|
624
|
+
return type_cast in possible_types
|
625
|
+
|
622
626
|
if object_type.concrete_of and (
|
623
627
|
has_object_definition(obj)
|
624
628
|
and obj.__strawberry_definition__.origin
|
@@ -758,9 +762,8 @@ class GraphQLCoreConverter:
|
|
758
762
|
if field.is_async:
|
759
763
|
_async_resolver._is_default = not field.base_resolver # type: ignore
|
760
764
|
return _async_resolver
|
761
|
-
|
762
|
-
|
763
|
-
return _resolver
|
765
|
+
_resolver._is_default = not field.base_resolver # type: ignore
|
766
|
+
return _resolver
|
764
767
|
|
765
768
|
def from_scalar(self, scalar: type) -> GraphQLScalarType:
|
766
769
|
scalar_definition: ScalarDefinition
|
@@ -810,10 +813,9 @@ class GraphQLCoreConverter:
|
|
810
813
|
NoneType = type(None)
|
811
814
|
if type_ is None or type_ is NoneType:
|
812
815
|
return self.from_type(type_)
|
813
|
-
|
816
|
+
if isinstance(type_, StrawberryOptional):
|
814
817
|
return self.from_type(type_.of_type)
|
815
|
-
|
816
|
-
return GraphQLNonNull(self.from_type(type_))
|
818
|
+
return GraphQLNonNull(self.from_type(type_))
|
817
819
|
|
818
820
|
def from_type(self, type_: Union[StrawberryType, type]) -> GraphQLNullableType:
|
819
821
|
if compat.is_graphql_generic(type_):
|
@@ -821,27 +823,27 @@ class GraphQLCoreConverter:
|
|
821
823
|
|
822
824
|
if isinstance(type_, EnumDefinition): # TODO: Replace with StrawberryEnum
|
823
825
|
return self.from_enum(type_)
|
824
|
-
|
826
|
+
if compat.is_input_type(type_): # TODO: Replace with StrawberryInputObject
|
825
827
|
return self.from_input_object(type_)
|
826
|
-
|
828
|
+
if isinstance(type_, StrawberryList):
|
827
829
|
return self.from_list(type_)
|
828
|
-
|
830
|
+
if compat.is_interface_type(type_): # TODO: Replace with StrawberryInterface
|
829
831
|
type_definition: StrawberryObjectDefinition = (
|
830
832
|
type_.__strawberry_definition__ # type: ignore
|
831
833
|
)
|
832
834
|
return self.from_interface(type_definition)
|
833
|
-
|
835
|
+
if has_object_definition(type_):
|
834
836
|
return self.from_object(type_.__strawberry_definition__)
|
835
|
-
|
837
|
+
if compat.is_enum(type_): # TODO: Replace with StrawberryEnum
|
836
838
|
enum_definition: EnumDefinition = type_._enum_definition # type: ignore
|
837
839
|
return self.from_enum(enum_definition)
|
838
|
-
|
840
|
+
if isinstance(type_, StrawberryObjectDefinition):
|
839
841
|
return self.from_object(type_)
|
840
|
-
|
842
|
+
if isinstance(type_, StrawberryUnion):
|
841
843
|
return self.from_union(type_)
|
842
|
-
|
844
|
+
if isinstance(type_, LazyType):
|
843
845
|
return self.from_type(type_.resolve_type())
|
844
|
-
|
846
|
+
if compat.is_scalar(
|
845
847
|
type_, self.scalar_registry
|
846
848
|
): # TODO: Replace with StrawberryScalar
|
847
849
|
return self.from_scalar(type_)
|
@@ -900,6 +902,9 @@ class GraphQLCoreConverter:
|
|
900
902
|
if object_type.interfaces:
|
901
903
|
|
902
904
|
def is_type_of(obj: Any, _info: GraphQLResolveInfo) -> bool:
|
905
|
+
if (type_cast := get_strawberry_type_cast(obj)) is not None:
|
906
|
+
return type_cast is object_type.origin
|
907
|
+
|
903
908
|
if object_type.concrete_of and (
|
904
909
|
has_object_definition(obj)
|
905
910
|
and obj.__strawberry_definition__.origin
|
strawberry/schema/subscribe.py
CHANGED
@@ -27,7 +27,7 @@ if TYPE_CHECKING:
|
|
27
27
|
from graphql.execution.middleware import MiddlewareManager
|
28
28
|
from graphql.type.schema import GraphQLSchema
|
29
29
|
|
30
|
-
from
|
30
|
+
from strawberry.extensions.runner import SchemaExtensionsRunner
|
31
31
|
|
32
32
|
SubscriptionResult: TypeAlias = Union[
|
33
33
|
PreExecutionError, AsyncGenerator[ExecutionResult, None]
|
@@ -80,7 +80,7 @@ async def _subscribe(
|
|
80
80
|
)
|
81
81
|
# graphql-core 3.2 doesn't handle some of the pre-execution errors.
|
82
82
|
# see `test_subscription_immediate_error`
|
83
|
-
except Exception as exc:
|
83
|
+
except Exception as exc: # noqa: BLE001
|
84
84
|
aiter_or_result = OriginalExecutionResult(
|
85
85
|
data=None, errors=[_coerce_error(exc)]
|
86
86
|
)
|
@@ -103,7 +103,7 @@ async def _subscribe(
|
|
103
103
|
process_errors,
|
104
104
|
)
|
105
105
|
# graphql-core doesn't handle exceptions raised while executing.
|
106
|
-
except Exception as exc:
|
106
|
+
except Exception as exc: # noqa: BLE001
|
107
107
|
yield await _handle_execution_result(
|
108
108
|
execution_context,
|
109
109
|
OriginalExecutionResult(data=None, errors=[_coerce_error(exc)]),
|
@@ -111,7 +111,7 @@ async def _subscribe(
|
|
111
111
|
process_errors,
|
112
112
|
)
|
113
113
|
# catch exceptions raised in `on_execute` hook.
|
114
|
-
except Exception as exc:
|
114
|
+
except Exception as exc: # noqa: BLE001
|
115
115
|
origin_result = OriginalExecutionResult(
|
116
116
|
data=None, errors=[_coerce_error(exc)]
|
117
117
|
)
|
@@ -15,7 +15,9 @@ def wrap_parser(parser: Callable, type_: str) -> Callable:
|
|
15
15
|
try:
|
16
16
|
return parser(value)
|
17
17
|
except ValueError as e:
|
18
|
-
raise GraphQLError(
|
18
|
+
raise GraphQLError( # noqa: B904
|
19
|
+
f'Value cannot represent a {type_}: "{value}". {e}'
|
20
|
+
)
|
19
21
|
|
20
22
|
return inner
|
21
23
|
|
@@ -24,7 +26,7 @@ def parse_decimal(value: object) -> decimal.Decimal:
|
|
24
26
|
try:
|
25
27
|
return decimal.Decimal(str(value))
|
26
28
|
except decimal.DecimalException:
|
27
|
-
raise GraphQLError(f'Value cannot represent a Decimal: "{value}".')
|
29
|
+
raise GraphQLError(f'Value cannot represent a Decimal: "{value}".') # noqa: B904
|
28
30
|
|
29
31
|
|
30
32
|
isoformat = methodcaller("isoformat")
|
@@ -62,7 +62,7 @@ DEFAULT_SCALAR_REGISTRY: dict[object, ScalarDefinition] = {
|
|
62
62
|
datetime.datetime: _get_scalar_definition(base_scalars.DateTime),
|
63
63
|
datetime.time: _get_scalar_definition(base_scalars.Time),
|
64
64
|
decimal.Decimal: _get_scalar_definition(base_scalars.Decimal),
|
65
|
-
# We can't wrap
|
65
|
+
# We can't wrap GlobalID with @scalar because it has custom attributes/methods
|
66
66
|
GlobalID: _get_scalar_definition(
|
67
67
|
scalar(
|
68
68
|
GlobalID,
|
@@ -115,7 +115,7 @@ def _get_field_type(
|
|
115
115
|
|
116
116
|
if isinstance(field_type, NonNullTypeNode):
|
117
117
|
return _get_field_type(field_type.type, was_non_nullable=True)
|
118
|
-
|
118
|
+
if isinstance(field_type, ListTypeNode):
|
119
119
|
expr = cst.Subscript(
|
120
120
|
value=cst.Name("list"),
|
121
121
|
slice=[
|
@@ -262,14 +262,13 @@ ArgumentValue: TypeAlias = Union[str, bool, list["ArgumentValue"]]
|
|
262
262
|
def _get_argument_value(argument_value: ConstValueNode) -> ArgumentValue:
|
263
263
|
if isinstance(argument_value, StringValueNode):
|
264
264
|
return argument_value.value
|
265
|
-
|
265
|
+
if isinstance(argument_value, EnumValueDefinitionNode):
|
266
266
|
return argument_value.name.value
|
267
|
-
|
267
|
+
if isinstance(argument_value, ListValueNode):
|
268
268
|
return [_get_argument_value(arg) for arg in argument_value.values]
|
269
|
-
|
269
|
+
if isinstance(argument_value, BooleanValueNode):
|
270
270
|
return argument_value.value
|
271
|
-
|
272
|
-
raise NotImplementedError(f"Unknown argument value {argument_value}")
|
271
|
+
raise NotImplementedError(f"Unknown argument value {argument_value}")
|
273
272
|
|
274
273
|
|
275
274
|
def _get_directives(
|
@@ -122,7 +122,7 @@ class BaseGraphQLTransportWSHandler(Generic[Context, RootValue]):
|
|
122
122
|
self.connection_timed_out = True
|
123
123
|
reason = "Connection initialisation timeout"
|
124
124
|
await self.websocket.close(code=4408, reason=reason)
|
125
|
-
except Exception as error:
|
125
|
+
except Exception as error: # noqa: BLE001
|
126
126
|
await self.handle_task_exception(error) # pragma: no cover
|
127
127
|
finally:
|
128
128
|
# do not clear self.connection_init_timeout_task
|
@@ -298,7 +298,7 @@ class BaseGraphQLTransportWSHandler(Generic[Context, RootValue]):
|
|
298
298
|
{"id": operation.id, "type": "complete"}
|
299
299
|
)
|
300
300
|
|
301
|
-
except BaseException
|
301
|
+
except BaseException: # pragma: no cover
|
302
302
|
self.operations.pop(operation.id, None)
|
303
303
|
raise
|
304
304
|
finally:
|
strawberry/test/client.py
CHANGED
@@ -188,8 +188,7 @@ class BaseGraphQLTestClient(ABC):
|
|
188
188
|
# Variables can be mixed files and other data, we don't want to map non-files
|
189
189
|
# vars so we need to remove them, we can't remove them before
|
190
190
|
# because they can be part of a list of files or folder
|
191
|
-
|
192
|
-
return map_without_vars
|
191
|
+
return {k: v for k, v in map.items() if k in files}
|
193
192
|
|
194
193
|
def _decode(self, response: Any, type: Literal["multipart", "json"]) -> Any:
|
195
194
|
if type == "multipart":
|
strawberry/types/arguments.py
CHANGED
@@ -23,8 +23,8 @@ from strawberry.types.base import (
|
|
23
23
|
)
|
24
24
|
from strawberry.types.enum import EnumDefinition
|
25
25
|
from strawberry.types.lazy_type import LazyType, StrawberryLazyReference
|
26
|
-
from strawberry.types.unset import UNSET as _deprecated_UNSET
|
27
|
-
from strawberry.types.unset import _deprecated_is_unset # noqa
|
26
|
+
from strawberry.types.unset import UNSET as _deprecated_UNSET # noqa: N811
|
27
|
+
from strawberry.types.unset import _deprecated_is_unset # noqa: F401
|
28
28
|
|
29
29
|
if TYPE_CHECKING:
|
30
30
|
from strawberry.schema.config import StrawberryConfig
|
strawberry/types/auto.py
CHANGED
@@ -23,8 +23,8 @@ class StrawberryAutoMeta(type):
|
|
23
23
|
|
24
24
|
"""
|
25
25
|
|
26
|
-
def __init__(
|
27
|
-
|
26
|
+
def __init__(cls, *args: str, **kwargs: Any) -> None:
|
27
|
+
cls._instance: Optional[StrawberryAuto] = None
|
28
28
|
super().__init__(*args, **kwargs)
|
29
29
|
|
30
30
|
def __call__(cls, *args: str, **kwargs: Any) -> Any:
|
@@ -34,7 +34,7 @@ class StrawberryAutoMeta(type):
|
|
34
34
|
return cls._instance
|
35
35
|
|
36
36
|
def __instancecheck__(
|
37
|
-
|
37
|
+
cls,
|
38
38
|
instance: Union[StrawberryAuto, StrawberryAnnotation, StrawberryType, type],
|
39
39
|
) -> bool:
|
40
40
|
if isinstance(instance, StrawberryAnnotation):
|