strawberry-graphql 0.255.0__py3-none-any.whl → 0.256.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 +9 -9
- strawberry/aiohttp/test/client.py +10 -8
- strawberry/aiohttp/views.py +5 -7
- strawberry/annotation.py +12 -15
- strawberry/asgi/__init__.py +3 -6
- strawberry/asgi/test/client.py +9 -8
- strawberry/chalice/views.py +4 -2
- strawberry/channels/__init__.py +1 -1
- strawberry/channels/handlers/base.py +3 -7
- strawberry/channels/handlers/http_handler.py +5 -6
- strawberry/channels/handlers/ws_handler.py +3 -4
- strawberry/channels/testing.py +5 -9
- strawberry/cli/commands/codegen.py +9 -9
- strawberry/cli/commands/upgrade/__init__.py +2 -3
- strawberry/cli/commands/upgrade/_run_codemod.py +7 -5
- strawberry/codegen/exceptions.py +2 -2
- strawberry/codegen/plugins/print_operation.py +6 -6
- strawberry/codegen/plugins/python.py +6 -6
- strawberry/codegen/plugins/typescript.py +3 -3
- strawberry/codegen/query_codegen.py +29 -34
- strawberry/codegen/types.py +35 -34
- strawberry/codemods/annotated_unions.py +5 -2
- strawberry/dataloader.py +13 -20
- strawberry/directive.py +12 -5
- strawberry/django/test/client.py +4 -4
- strawberry/django/views.py +4 -5
- strawberry/exceptions/__init__.py +24 -24
- strawberry/exceptions/conflicting_arguments.py +2 -2
- strawberry/exceptions/duplicated_type_name.py +3 -3
- strawberry/exceptions/handler.py +7 -7
- strawberry/exceptions/invalid_union_type.py +2 -2
- strawberry/exceptions/missing_arguments_annotations.py +2 -2
- strawberry/exceptions/missing_field_annotation.py +2 -2
- strawberry/exceptions/object_is_not_an_enum.py +2 -2
- strawberry/exceptions/private_strawberry_field.py +2 -2
- strawberry/exceptions/syntax.py +4 -4
- strawberry/exceptions/utils/source_finder.py +7 -6
- strawberry/experimental/pydantic/__init__.py +3 -3
- strawberry/experimental/pydantic/_compat.py +14 -14
- strawberry/experimental/pydantic/conversion.py +2 -2
- strawberry/experimental/pydantic/conversion_types.py +3 -3
- strawberry/experimental/pydantic/error_type.py +18 -16
- strawberry/experimental/pydantic/exceptions.py +5 -5
- strawberry/experimental/pydantic/fields.py +2 -13
- strawberry/experimental/pydantic/object_type.py +20 -22
- strawberry/experimental/pydantic/utils.py +6 -10
- strawberry/ext/dataclasses/dataclasses.py +3 -3
- strawberry/ext/mypy_plugin.py +6 -9
- strawberry/extensions/__init__.py +7 -8
- strawberry/extensions/add_validation_rules.py +5 -3
- strawberry/extensions/base_extension.py +4 -4
- strawberry/extensions/context.py +15 -14
- strawberry/extensions/directives.py +2 -2
- strawberry/extensions/disable_validation.py +1 -1
- strawberry/extensions/field_extension.py +2 -1
- strawberry/extensions/mask_errors.py +3 -2
- strawberry/extensions/max_aliases.py +2 -2
- strawberry/extensions/max_tokens.py +1 -1
- strawberry/extensions/parser_cache.py +2 -1
- strawberry/extensions/pyinstrument.py +4 -1
- strawberry/extensions/query_depth_limiter.py +13 -13
- strawberry/extensions/runner.py +7 -7
- strawberry/extensions/tracing/apollo.py +11 -9
- strawberry/extensions/tracing/datadog.py +3 -1
- strawberry/extensions/tracing/opentelemetry.py +7 -10
- strawberry/extensions/utils.py +3 -3
- strawberry/extensions/validation_cache.py +2 -1
- strawberry/fastapi/context.py +3 -3
- strawberry/fastapi/router.py +9 -14
- strawberry/federation/__init__.py +4 -4
- strawberry/federation/argument.py +2 -1
- strawberry/federation/enum.py +8 -8
- strawberry/federation/field.py +25 -28
- strawberry/federation/object_type.py +24 -26
- strawberry/federation/scalar.py +7 -8
- strawberry/federation/schema.py +30 -36
- strawberry/federation/schema_directive.py +5 -5
- strawberry/federation/schema_directives.py +14 -14
- strawberry/federation/union.py +3 -2
- strawberry/field_extensions/input_mutation.py +1 -2
- strawberry/file_uploads/utils.py +4 -3
- strawberry/flask/views.py +3 -2
- strawberry/http/__init__.py +6 -6
- strawberry/http/async_base_view.py +9 -14
- strawberry/http/base.py +5 -4
- strawberry/http/ides.py +1 -1
- strawberry/http/parse_content_type.py +1 -2
- strawberry/http/sync_base_view.py +3 -5
- strawberry/http/temporal_response.py +1 -2
- strawberry/http/types.py +3 -2
- strawberry/litestar/controller.py +8 -14
- strawberry/parent.py +1 -2
- strawberry/permission.py +6 -8
- strawberry/printer/ast_from_value.py +2 -1
- strawberry/printer/printer.py +50 -30
- strawberry/quart/views.py +3 -3
- strawberry/relay/exceptions.py +4 -4
- strawberry/relay/fields.py +22 -24
- strawberry/relay/types.py +29 -27
- strawberry/relay/utils.py +4 -4
- strawberry/sanic/utils.py +4 -4
- strawberry/sanic/views.py +5 -7
- strawberry/scalars.py +2 -2
- strawberry/schema/base.py +16 -11
- strawberry/schema/compat.py +4 -4
- strawberry/schema/execute.py +6 -10
- strawberry/schema/name_converter.py +3 -3
- strawberry/schema/schema.py +37 -25
- strawberry/schema/schema_converter.py +22 -24
- strawberry/schema/subscribe.py +4 -3
- strawberry/schema/types/base_scalars.py +1 -1
- strawberry/schema/types/concrete_type.py +2 -2
- strawberry/schema/types/scalar.py +3 -4
- strawberry/schema_codegen/__init__.py +4 -4
- strawberry/schema_directive.py +8 -8
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +8 -9
- strawberry/subscriptions/protocols/graphql_transport_ws/types.py +16 -16
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +6 -5
- strawberry/subscriptions/protocols/graphql_ws/types.py +13 -13
- strawberry/test/__init__.py +1 -1
- strawberry/test/client.py +21 -19
- strawberry/tools/create_type.py +4 -3
- strawberry/tools/merge_types.py +1 -2
- strawberry/types/__init__.py +1 -1
- strawberry/types/arguments.py +10 -12
- strawberry/types/auto.py +2 -2
- strawberry/types/base.py +17 -21
- strawberry/types/enum.py +3 -5
- strawberry/types/execution.py +8 -12
- strawberry/types/field.py +26 -31
- strawberry/types/fields/resolver.py +15 -17
- strawberry/types/graphql.py +2 -2
- strawberry/types/info.py +5 -9
- strawberry/types/lazy_type.py +3 -5
- strawberry/types/mutation.py +25 -28
- strawberry/types/nodes.py +11 -9
- strawberry/types/object_type.py +14 -16
- strawberry/types/private.py +1 -2
- strawberry/types/scalar.py +2 -2
- strawberry/types/type_resolver.py +5 -5
- strawberry/types/union.py +8 -11
- strawberry/types/unset.py +3 -3
- strawberry/utils/aio.py +3 -8
- strawberry/utils/await_maybe.py +3 -2
- strawberry/utils/debug.py +2 -2
- strawberry/utils/deprecations.py +2 -2
- strawberry/utils/inspect.py +3 -5
- strawberry/utils/str_converters.py +1 -1
- strawberry/utils/typing.py +38 -67
- {strawberry_graphql-0.255.0.dist-info → strawberry_graphql-0.256.0.dist-info}/METADATA +3 -6
- strawberry_graphql-0.256.0.dist-info/RECORD +236 -0
- strawberry_graphql-0.255.0.dist-info/RECORD +0 -236
- {strawberry_graphql-0.255.0.dist-info → strawberry_graphql-0.256.0.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.255.0.dist-info → strawberry_graphql-0.256.0.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.255.0.dist-info → strawberry_graphql-0.256.0.dist-info}/entry_points.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import textwrap
|
4
|
-
from typing import TYPE_CHECKING,
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
5
5
|
|
6
6
|
from strawberry.codegen import CodegenFile, QueryCodegenPlugin
|
7
7
|
from strawberry.codegen.types import (
|
@@ -35,8 +35,8 @@ if TYPE_CHECKING:
|
|
35
35
|
|
36
36
|
class PrintOperationPlugin(QueryCodegenPlugin):
|
37
37
|
def generate_code(
|
38
|
-
self, types:
|
39
|
-
) ->
|
38
|
+
self, types: list[GraphQLType], operation: GraphQLOperation
|
39
|
+
) -> list[CodegenFile]:
|
40
40
|
code_lines = []
|
41
41
|
for t in types:
|
42
42
|
if not isinstance(t, GraphQLFragmentType):
|
@@ -139,7 +139,7 @@ class PrintOperationPlugin(QueryCodegenPlugin):
|
|
139
139
|
|
140
140
|
raise ValueError(f"not supported: {type(value)}") # pragma: no cover
|
141
141
|
|
142
|
-
def _print_arguments(self, arguments:
|
142
|
+
def _print_arguments(self, arguments: list[GraphQLArgument]) -> str:
|
143
143
|
if not arguments:
|
144
144
|
return ""
|
145
145
|
|
@@ -154,7 +154,7 @@ class PrintOperationPlugin(QueryCodegenPlugin):
|
|
154
154
|
+ ")"
|
155
155
|
)
|
156
156
|
|
157
|
-
def _print_directives(self, directives:
|
157
|
+
def _print_directives(self, directives: list[GraphQLDirective]) -> str:
|
158
158
|
if not directives:
|
159
159
|
return ""
|
160
160
|
|
@@ -204,7 +204,7 @@ class PrintOperationPlugin(QueryCodegenPlugin):
|
|
204
204
|
|
205
205
|
raise ValueError(f"Unsupported selection: {selection}") # pragma: no cover
|
206
206
|
|
207
|
-
def _print_selections(self, selections:
|
207
|
+
def _print_selections(self, selections: list[GraphQLSelection]) -> str:
|
208
208
|
selections_text = "\n".join(
|
209
209
|
[self._print_selection(selection) for selection in selections]
|
210
210
|
)
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
3
3
|
import textwrap
|
4
4
|
from collections import defaultdict
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import TYPE_CHECKING,
|
6
|
+
from typing import TYPE_CHECKING, Optional
|
7
7
|
|
8
8
|
from strawberry.codegen import CodegenFile, QueryCodegenPlugin
|
9
9
|
from strawberry.codegen.types import (
|
@@ -35,7 +35,7 @@ class PythonType:
|
|
35
35
|
|
36
36
|
|
37
37
|
class PythonPlugin(QueryCodegenPlugin):
|
38
|
-
SCALARS_TO_PYTHON_TYPES:
|
38
|
+
SCALARS_TO_PYTHON_TYPES: dict[str, PythonType] = {
|
39
39
|
"ID": PythonType("str"),
|
40
40
|
"Int": PythonType("int"),
|
41
41
|
"String": PythonType("str"),
|
@@ -49,13 +49,13 @@ class PythonPlugin(QueryCodegenPlugin):
|
|
49
49
|
}
|
50
50
|
|
51
51
|
def __init__(self, query: Path) -> None:
|
52
|
-
self.imports:
|
52
|
+
self.imports: dict[str, set[str]] = defaultdict(set)
|
53
53
|
self.outfile_name: str = query.with_suffix(".py").name
|
54
54
|
self.query = query
|
55
55
|
|
56
56
|
def generate_code(
|
57
|
-
self, types:
|
58
|
-
) ->
|
57
|
+
self, types: list[GraphQLType], operation: GraphQLOperation
|
58
|
+
) -> list[CodegenFile]:
|
59
59
|
printed_types = list(filter(None, (self._print_type(type) for type in types)))
|
60
60
|
imports = self._print_imports()
|
61
61
|
|
@@ -80,7 +80,7 @@ class PythonPlugin(QueryCodegenPlugin):
|
|
80
80
|
if isinstance(type_, GraphQLList):
|
81
81
|
self.imports["typing"].add("List")
|
82
82
|
|
83
|
-
return f"
|
83
|
+
return f"list[{self._get_type_name(type_.of_type)}]"
|
84
84
|
|
85
85
|
if isinstance(type_, GraphQLUnion):
|
86
86
|
# TODO: wrong place for this
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import textwrap
|
4
|
-
from typing import TYPE_CHECKING
|
4
|
+
from typing import TYPE_CHECKING
|
5
5
|
|
6
6
|
from strawberry.codegen import CodegenFile, QueryCodegenPlugin
|
7
7
|
from strawberry.codegen.types import (
|
@@ -40,8 +40,8 @@ class TypeScriptPlugin(QueryCodegenPlugin):
|
|
40
40
|
self.query = query
|
41
41
|
|
42
42
|
def generate_code(
|
43
|
-
self, types:
|
44
|
-
) ->
|
43
|
+
self, types: list[GraphQLType], operation: GraphQLOperation
|
44
|
+
) -> list[CodegenFile]:
|
45
45
|
printed_types = list(filter(None, (self._print_type(type) for type in types)))
|
46
46
|
|
47
47
|
return [CodegenFile(self.outfile_name, "\n\n".join(printed_types))]
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
from collections.abc import Iterable, Mapping, Sequence
|
3
4
|
from dataclasses import MISSING, dataclass
|
4
5
|
from enum import Enum
|
5
6
|
from functools import cmp_to_key, partial
|
@@ -8,13 +9,7 @@ from typing import (
|
|
8
9
|
TYPE_CHECKING,
|
9
10
|
Any,
|
10
11
|
Callable,
|
11
|
-
Iterable,
|
12
|
-
List,
|
13
|
-
Mapping,
|
14
12
|
Optional,
|
15
|
-
Sequence,
|
16
|
-
Tuple,
|
17
|
-
Type,
|
18
13
|
Union,
|
19
14
|
cast,
|
20
15
|
)
|
@@ -114,7 +109,7 @@ class CodegenFile:
|
|
114
109
|
|
115
110
|
@dataclass
|
116
111
|
class CodegenResult:
|
117
|
-
files:
|
112
|
+
files: list[CodegenFile]
|
118
113
|
|
119
114
|
def to_string(self) -> str:
|
120
115
|
return "\n".join(f.content for f in self.files) + "\n"
|
@@ -144,15 +139,15 @@ class QueryCodegenPlugin:
|
|
144
139
|
def on_end(self, result: CodegenResult) -> None: ...
|
145
140
|
|
146
141
|
def generate_code(
|
147
|
-
self, types:
|
148
|
-
) ->
|
142
|
+
self, types: list[GraphQLType], operation: GraphQLOperation
|
143
|
+
) -> list[CodegenFile]:
|
149
144
|
return []
|
150
145
|
|
151
146
|
|
152
147
|
class ConsolePlugin:
|
153
148
|
def __init__(self, output_dir: Path) -> None:
|
154
149
|
self.output_dir = output_dir
|
155
|
-
self.files_generated:
|
150
|
+
self.files_generated: list[Path] = []
|
156
151
|
|
157
152
|
def before_any_start(self) -> None:
|
158
153
|
rich.print(
|
@@ -238,13 +233,13 @@ def _py_to_graphql_value(obj: Any) -> GraphQLArgumentValue:
|
|
238
233
|
class QueryCodegenPluginManager:
|
239
234
|
def __init__(
|
240
235
|
self,
|
241
|
-
plugins:
|
236
|
+
plugins: list[QueryCodegenPlugin],
|
242
237
|
console_plugin: Optional[ConsolePlugin] = None,
|
243
238
|
) -> None:
|
244
239
|
self.plugins = plugins
|
245
240
|
self.console_plugin = console_plugin
|
246
241
|
|
247
|
-
def _sort_types(self, types:
|
242
|
+
def _sort_types(self, types: list[GraphQLType]) -> list[GraphQLType]:
|
248
243
|
"""Sort the types.
|
249
244
|
|
250
245
|
t1 < t2 iff t2 has a dependency on t1.
|
@@ -266,7 +261,7 @@ class QueryCodegenPluginManager:
|
|
266
261
|
return sorted(types, key=cmp_to_key(type_cmp))
|
267
262
|
|
268
263
|
def generate_code(
|
269
|
-
self, types:
|
264
|
+
self, types: list[GraphQLType], operation: GraphQLOperation
|
270
265
|
) -> CodegenResult:
|
271
266
|
result = CodegenResult(files=[])
|
272
267
|
|
@@ -301,12 +296,12 @@ class QueryCodegen:
|
|
301
296
|
def __init__(
|
302
297
|
self,
|
303
298
|
schema: Schema,
|
304
|
-
plugins:
|
299
|
+
plugins: list[QueryCodegenPlugin],
|
305
300
|
console_plugin: Optional[ConsolePlugin] = None,
|
306
301
|
) -> None:
|
307
302
|
self.schema = schema
|
308
303
|
self.plugin_manager = QueryCodegenPluginManager(plugins, console_plugin)
|
309
|
-
self.types:
|
304
|
+
self.types: list[GraphQLType] = []
|
310
305
|
|
311
306
|
def run(self, query: str) -> CodegenResult:
|
312
307
|
self.plugin_manager.on_start()
|
@@ -395,7 +390,7 @@ class QueryCodegen:
|
|
395
390
|
|
396
391
|
def _convert_selection_set(
|
397
392
|
self, selection_set: Optional[SelectionSetNode]
|
398
|
-
) ->
|
393
|
+
) -> list[GraphQLSelection]:
|
399
394
|
if selection_set is None:
|
400
395
|
return []
|
401
396
|
|
@@ -442,7 +437,7 @@ class QueryCodegen:
|
|
442
437
|
|
443
438
|
def _convert_arguments(
|
444
439
|
self, arguments: Iterable[ArgumentNode]
|
445
|
-
) ->
|
440
|
+
) -> list[GraphQLArgument]:
|
446
441
|
return [
|
447
442
|
GraphQLArgument(argument.name.value, self._convert_value(argument.value))
|
448
443
|
for argument in arguments
|
@@ -450,7 +445,7 @@ class QueryCodegen:
|
|
450
445
|
|
451
446
|
def _convert_directives(
|
452
447
|
self, directives: Iterable[DirectiveNode]
|
453
|
-
) ->
|
448
|
+
) -> list[GraphQLDirective]:
|
454
449
|
return [
|
455
450
|
GraphQLDirective(
|
456
451
|
directive.name.value,
|
@@ -500,7 +495,7 @@ class QueryCodegen:
|
|
500
495
|
self,
|
501
496
|
variable_definitions: Optional[Iterable[VariableDefinitionNode]],
|
502
497
|
operation_name: str,
|
503
|
-
) ->
|
498
|
+
) -> tuple[list[GraphQLVariable], Optional[GraphQLObjectType]]:
|
504
499
|
if not variable_definitions:
|
505
500
|
return [], None
|
506
501
|
|
@@ -508,7 +503,7 @@ class QueryCodegen:
|
|
508
503
|
|
509
504
|
self._collect_type(type_)
|
510
505
|
|
511
|
-
variables:
|
506
|
+
variables: list[GraphQLVariable] = []
|
512
507
|
|
513
508
|
for variable_definition in variable_definitions:
|
514
509
|
variable_type = self._collect_type_from_variable(variable_definition.type)
|
@@ -522,7 +517,7 @@ class QueryCodegen:
|
|
522
517
|
|
523
518
|
return variables, type_
|
524
519
|
|
525
|
-
def _get_operations(self, ast: DocumentNode) ->
|
520
|
+
def _get_operations(self, ast: DocumentNode) -> list[OperationDefinitionNode]:
|
526
521
|
return [
|
527
522
|
definition
|
528
523
|
for definition in ast.definitions
|
@@ -642,7 +637,7 @@ class QueryCodegen:
|
|
642
637
|
|
643
638
|
def _unwrap_type(
|
644
639
|
self, type_: Union[type, StrawberryType]
|
645
|
-
) ->
|
640
|
+
) -> tuple[
|
646
641
|
Union[type, StrawberryType], Optional[Callable[[GraphQLType], GraphQLType]]
|
647
642
|
]:
|
648
643
|
wrapper: Optional[Callable[[GraphQLType], GraphQLType]] = None
|
@@ -777,7 +772,7 @@ class QueryCodegen:
|
|
777
772
|
)
|
778
773
|
|
779
774
|
current_type = graph_ql_object_type_factory(class_name)
|
780
|
-
fields:
|
775
|
+
fields: list[Union[GraphQLFragmentSpread, GraphQLField]] = []
|
781
776
|
|
782
777
|
for sub_selection in selection_set.selections:
|
783
778
|
if isinstance(sub_selection, FragmentSpreadNode):
|
@@ -805,7 +800,7 @@ class QueryCodegen:
|
|
805
800
|
# `GraphQLField` or `GraphQLFragmentSpread`
|
806
801
|
# and the suite above will cause this statement to be
|
807
802
|
# skipped if there are any `GraphQLFragmentSpread`.
|
808
|
-
current_type.fields = cast(
|
803
|
+
current_type.fields = cast(list[GraphQLField], fields)
|
809
804
|
|
810
805
|
self._collect_type(current_type)
|
811
806
|
|
@@ -821,12 +816,12 @@ class QueryCodegen:
|
|
821
816
|
selection: HasSelectionSet,
|
822
817
|
parent_type: StrawberryObjectDefinition,
|
823
818
|
class_name: str,
|
824
|
-
) ->
|
819
|
+
) -> list[GraphQLObjectType]:
|
825
820
|
assert selection.selection_set
|
826
821
|
|
827
|
-
common_fields:
|
828
|
-
fragments:
|
829
|
-
sub_types:
|
822
|
+
common_fields: list[GraphQLField] = []
|
823
|
+
fragments: list[InlineFragmentNode] = []
|
824
|
+
sub_types: list[GraphQLObjectType] = []
|
830
825
|
|
831
826
|
for sub_selection in selection.selection_set.selections:
|
832
827
|
if isinstance(sub_selection, FieldNode):
|
@@ -848,7 +843,7 @@ class QueryCodegen:
|
|
848
843
|
list(common_fields),
|
849
844
|
graphql_typename=type_condition_name,
|
850
845
|
)
|
851
|
-
fields:
|
846
|
+
fields: list[Union[GraphQLFragmentSpread, GraphQLField]] = []
|
852
847
|
|
853
848
|
for sub_selection in fragment.selection_set.selections:
|
854
849
|
if isinstance(sub_selection, FragmentSpreadNode):
|
@@ -893,7 +888,7 @@ class QueryCodegen:
|
|
893
888
|
# `GraphQLField` or `GraphQLFragmentSpread`
|
894
889
|
# and the suite above will cause this statement to be
|
895
890
|
# skipped if there are any `GraphQLFragmentSpread`.
|
896
|
-
current_type.fields.extend(cast(
|
891
|
+
current_type.fields.extend(cast(list[GraphQLField], fields))
|
897
892
|
|
898
893
|
sub_types.append(current_type)
|
899
894
|
|
@@ -903,7 +898,7 @@ class QueryCodegen:
|
|
903
898
|
return sub_types
|
904
899
|
|
905
900
|
def _collect_scalar(
|
906
|
-
self, scalar_definition: ScalarDefinition, python_type: Optional[
|
901
|
+
self, scalar_definition: ScalarDefinition, python_type: Optional[type]
|
907
902
|
) -> GraphQLScalar:
|
908
903
|
graphql_scalar = GraphQLScalar(scalar_definition.name, python_type=python_type)
|
909
904
|
|
@@ -922,9 +917,9 @@ class QueryCodegen:
|
|
922
917
|
|
923
918
|
|
924
919
|
__all__ = [
|
925
|
-
"QueryCodegen",
|
926
|
-
"QueryCodegenPlugin",
|
927
|
-
"ConsolePlugin",
|
928
920
|
"CodegenFile",
|
929
921
|
"CodegenResult",
|
922
|
+
"ConsolePlugin",
|
923
|
+
"QueryCodegen",
|
924
|
+
"QueryCodegenPlugin",
|
930
925
|
]
|
strawberry/codegen/types.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from dataclasses import dataclass, field
|
4
|
-
from typing import TYPE_CHECKING,
|
4
|
+
from typing import TYPE_CHECKING, Optional, Union
|
5
5
|
|
6
6
|
if TYPE_CHECKING:
|
7
|
+
from collections.abc import Mapping
|
7
8
|
from enum import EnumMeta
|
8
9
|
from typing_extensions import Literal
|
9
10
|
|
@@ -23,7 +24,7 @@ class GraphQLList:
|
|
23
24
|
@dataclass
|
24
25
|
class GraphQLUnion:
|
25
26
|
name: str
|
26
|
-
types:
|
27
|
+
types: list[GraphQLObjectType]
|
27
28
|
|
28
29
|
|
29
30
|
@dataclass
|
@@ -42,7 +43,7 @@ class GraphQLFragmentSpread:
|
|
42
43
|
@dataclass
|
43
44
|
class GraphQLObjectType:
|
44
45
|
name: str
|
45
|
-
fields:
|
46
|
+
fields: list[GraphQLField] = field(default_factory=list)
|
46
47
|
graphql_typename: Optional[str] = None
|
47
48
|
|
48
49
|
|
@@ -52,7 +53,7 @@ class GraphQLObjectType:
|
|
52
53
|
@dataclass
|
53
54
|
class GraphQLFragmentType(GraphQLObjectType):
|
54
55
|
name: str
|
55
|
-
fields:
|
56
|
+
fields: list[GraphQLField] = field(default_factory=list)
|
56
57
|
graphql_typename: Optional[str] = None
|
57
58
|
on: str = ""
|
58
59
|
|
@@ -66,14 +67,14 @@ class GraphQLFragmentType(GraphQLObjectType):
|
|
66
67
|
@dataclass
|
67
68
|
class GraphQLEnum:
|
68
69
|
name: str
|
69
|
-
values:
|
70
|
+
values: list[str]
|
70
71
|
python_type: EnumMeta
|
71
72
|
|
72
73
|
|
73
74
|
@dataclass
|
74
75
|
class GraphQLScalar:
|
75
76
|
name: str
|
76
|
-
python_type: Optional[
|
77
|
+
python_type: Optional[type]
|
77
78
|
|
78
79
|
|
79
80
|
GraphQLType = Union[
|
@@ -90,15 +91,15 @@ GraphQLType = Union[
|
|
90
91
|
class GraphQLFieldSelection:
|
91
92
|
field: str
|
92
93
|
alias: Optional[str]
|
93
|
-
selections:
|
94
|
-
directives:
|
95
|
-
arguments:
|
94
|
+
selections: list[GraphQLSelection]
|
95
|
+
directives: list[GraphQLDirective]
|
96
|
+
arguments: list[GraphQLArgument]
|
96
97
|
|
97
98
|
|
98
99
|
@dataclass
|
99
100
|
class GraphQLInlineFragment:
|
100
101
|
type_condition: str
|
101
|
-
selections:
|
102
|
+
selections: list[GraphQLSelection]
|
102
103
|
|
103
104
|
|
104
105
|
GraphQLSelection = Union[
|
@@ -141,7 +142,7 @@ class GraphQLNullValue:
|
|
141
142
|
|
142
143
|
@dataclass
|
143
144
|
class GraphQLListValue:
|
144
|
-
values:
|
145
|
+
values: list[GraphQLArgumentValue]
|
145
146
|
|
146
147
|
|
147
148
|
@dataclass
|
@@ -176,7 +177,7 @@ class GraphQLArgument:
|
|
176
177
|
@dataclass
|
177
178
|
class GraphQLDirective:
|
178
179
|
name: str
|
179
|
-
arguments:
|
180
|
+
arguments: list[GraphQLArgument]
|
180
181
|
|
181
182
|
|
182
183
|
@dataclass
|
@@ -189,39 +190,39 @@ class GraphQLVariable:
|
|
189
190
|
class GraphQLOperation:
|
190
191
|
name: str
|
191
192
|
kind: Literal["query", "mutation", "subscription"]
|
192
|
-
selections:
|
193
|
-
directives:
|
194
|
-
variables:
|
193
|
+
selections: list[GraphQLSelection]
|
194
|
+
directives: list[GraphQLDirective]
|
195
|
+
variables: list[GraphQLVariable]
|
195
196
|
type: GraphQLObjectType
|
196
197
|
variables_type: Optional[GraphQLObjectType]
|
197
198
|
|
198
199
|
|
199
200
|
__all__ = [
|
200
|
-
"
|
201
|
-
"
|
202
|
-
"
|
201
|
+
"GraphQLArgument",
|
202
|
+
"GraphQLArgumentValue",
|
203
|
+
"GraphQLBoolValue",
|
204
|
+
"GraphQLDirective",
|
205
|
+
"GraphQLEnum",
|
206
|
+
"GraphQLEnumValue",
|
203
207
|
"GraphQLField",
|
208
|
+
"GraphQLFieldSelection",
|
209
|
+
"GraphQLFloatValue",
|
204
210
|
"GraphQLFragmentSpread",
|
205
|
-
"GraphQLObjectType",
|
206
211
|
"GraphQLFragmentType",
|
207
|
-
"GraphQLEnum",
|
208
|
-
"GraphQLScalar",
|
209
|
-
"GraphQLType",
|
210
|
-
"GraphQLFieldSelection",
|
211
212
|
"GraphQLInlineFragment",
|
212
|
-
"GraphQLSelection",
|
213
|
-
"GraphQLStringValue",
|
214
213
|
"GraphQLIntValue",
|
215
|
-
"
|
216
|
-
"GraphQLEnumValue",
|
217
|
-
"GraphQLBoolValue",
|
218
|
-
"GraphQLNullValue",
|
214
|
+
"GraphQLList",
|
219
215
|
"GraphQLListValue",
|
216
|
+
"GraphQLNullValue",
|
217
|
+
"GraphQLObjectType",
|
220
218
|
"GraphQLObjectValue",
|
221
|
-
"GraphQLVariableReference",
|
222
|
-
"GraphQLArgumentValue",
|
223
|
-
"GraphQLArgument",
|
224
|
-
"GraphQLDirective",
|
225
|
-
"GraphQLVariable",
|
226
219
|
"GraphQLOperation",
|
220
|
+
"GraphQLOptional",
|
221
|
+
"GraphQLScalar",
|
222
|
+
"GraphQLSelection",
|
223
|
+
"GraphQLStringValue",
|
224
|
+
"GraphQLType",
|
225
|
+
"GraphQLUnion",
|
226
|
+
"GraphQLVariable",
|
227
|
+
"GraphQLVariableReference",
|
227
228
|
]
|
@@ -1,13 +1,16 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from typing import
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
4
4
|
|
5
5
|
import libcst as cst
|
6
6
|
import libcst.matchers as m
|
7
|
-
from libcst._nodes.expression import BaseExpression, Call # noqa:
|
7
|
+
from libcst._nodes.expression import BaseExpression, Call # noqa: TC002
|
8
8
|
from libcst.codemod import CodemodContext, VisitorBasedCodemodCommand
|
9
9
|
from libcst.codemod.visitors import AddImportsVisitor, RemoveImportsVisitor
|
10
10
|
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from collections.abc import Sequence
|
13
|
+
|
11
14
|
|
12
15
|
def _find_named_argument(args: Sequence[cst.Arg], name: str) -> cst.Arg | None:
|
13
16
|
return next(
|
strawberry/dataloader.py
CHANGED
@@ -8,16 +8,9 @@ from dataclasses import dataclass
|
|
8
8
|
from typing import (
|
9
9
|
TYPE_CHECKING,
|
10
10
|
Any,
|
11
|
-
Awaitable,
|
12
11
|
Callable,
|
13
|
-
Dict,
|
14
12
|
Generic,
|
15
|
-
Hashable,
|
16
|
-
Iterable,
|
17
|
-
List,
|
18
|
-
Mapping,
|
19
13
|
Optional,
|
20
|
-
Sequence,
|
21
14
|
TypeVar,
|
22
15
|
Union,
|
23
16
|
overload,
|
@@ -27,6 +20,7 @@ from .exceptions import WrongNumberOfResultsReturned
|
|
27
20
|
|
28
21
|
if TYPE_CHECKING:
|
29
22
|
from asyncio.events import AbstractEventLoop
|
23
|
+
from collections.abc import Awaitable, Hashable, Iterable, Mapping, Sequence
|
30
24
|
|
31
25
|
|
32
26
|
T = TypeVar("T")
|
@@ -41,7 +35,7 @@ class LoaderTask(Generic[K, T]):
|
|
41
35
|
|
42
36
|
@dataclass
|
43
37
|
class Batch(Generic[K, T]):
|
44
|
-
tasks:
|
38
|
+
tasks: list[LoaderTask] = dataclasses.field(default_factory=list)
|
45
39
|
dispatched: bool = False
|
46
40
|
|
47
41
|
def add_task(self, key: Any, future: Future) -> None:
|
@@ -75,7 +69,7 @@ class DefaultCache(AbstractCache[K, T]):
|
|
75
69
|
self.cache_key_fn: Callable[[K], Hashable] = (
|
76
70
|
cache_key_fn if cache_key_fn is not None else lambda x: x
|
77
71
|
)
|
78
|
-
self.cache_map:
|
72
|
+
self.cache_map: dict[Hashable, Future[T]] = {}
|
79
73
|
|
80
74
|
def get(self, key: K) -> Union[Future[T], None]:
|
81
75
|
return self.cache_map.get(self.cache_key_fn(key))
|
@@ -99,7 +93,7 @@ class DataLoader(Generic[K, T]):
|
|
99
93
|
def __init__(
|
100
94
|
self,
|
101
95
|
# any BaseException is rethrown in 'load', so should be excluded from the T type
|
102
|
-
load_fn: Callable[[
|
96
|
+
load_fn: Callable[[list[K]], Awaitable[Sequence[Union[T, BaseException]]]],
|
103
97
|
max_batch_size: Optional[int] = None,
|
104
98
|
cache: bool = True,
|
105
99
|
loop: Optional[AbstractEventLoop] = None,
|
@@ -111,7 +105,7 @@ class DataLoader(Generic[K, T]):
|
|
111
105
|
@overload
|
112
106
|
def __init__(
|
113
107
|
self: DataLoader[K, Any],
|
114
|
-
load_fn: Callable[[
|
108
|
+
load_fn: Callable[[list[K]], Awaitable[list[Any]]],
|
115
109
|
max_batch_size: Optional[int] = None,
|
116
110
|
cache: bool = True,
|
117
111
|
loop: Optional[AbstractEventLoop] = None,
|
@@ -121,7 +115,7 @@ class DataLoader(Generic[K, T]):
|
|
121
115
|
|
122
116
|
def __init__(
|
123
117
|
self,
|
124
|
-
load_fn: Callable[[
|
118
|
+
load_fn: Callable[[list[K]], Awaitable[Sequence[Union[T, BaseException]]]],
|
125
119
|
max_batch_size: Optional[int] = None,
|
126
120
|
cache: bool = True,
|
127
121
|
loop: Optional[AbstractEventLoop] = None,
|
@@ -164,7 +158,7 @@ class DataLoader(Generic[K, T]):
|
|
164
158
|
|
165
159
|
return future
|
166
160
|
|
167
|
-
def load_many(self, keys: Iterable[K]) -> Awaitable[
|
161
|
+
def load_many(self, keys: Iterable[K]) -> Awaitable[list[T]]:
|
168
162
|
return gather(*map(self.load, keys))
|
169
163
|
|
170
164
|
def clear(self, key: K) -> None:
|
@@ -210,8 +204,7 @@ class DataLoader(Generic[K, T]):
|
|
210
204
|
def should_create_new_batch(loader: DataLoader, batch: Batch) -> bool:
|
211
205
|
return bool(
|
212
206
|
batch.dispatched
|
213
|
-
or loader.max_batch_size
|
214
|
-
and len(batch) >= loader.max_batch_size
|
207
|
+
or (loader.max_batch_size and len(batch) >= loader.max_batch_size)
|
215
208
|
)
|
216
209
|
|
217
210
|
|
@@ -267,13 +260,13 @@ async def dispatch_batch(loader: DataLoader, batch: Batch) -> None:
|
|
267
260
|
|
268
261
|
|
269
262
|
__all__ = [
|
270
|
-
"DataLoader",
|
271
|
-
"Batch",
|
272
|
-
"LoaderTask",
|
273
263
|
"AbstractCache",
|
264
|
+
"Batch",
|
265
|
+
"DataLoader",
|
274
266
|
"DefaultCache",
|
275
|
-
"
|
276
|
-
"get_current_batch",
|
267
|
+
"LoaderTask",
|
277
268
|
"dispatch",
|
278
269
|
"dispatch_batch",
|
270
|
+
"get_current_batch",
|
271
|
+
"should_create_new_batch",
|
279
272
|
]
|
strawberry/directive.py
CHANGED
@@ -2,8 +2,15 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import dataclasses
|
4
4
|
from functools import cached_property
|
5
|
-
from typing import
|
6
|
-
|
5
|
+
from typing import (
|
6
|
+
TYPE_CHECKING,
|
7
|
+
Annotated,
|
8
|
+
Any,
|
9
|
+
Callable,
|
10
|
+
Generic,
|
11
|
+
Optional,
|
12
|
+
TypeVar,
|
13
|
+
)
|
7
14
|
|
8
15
|
from graphql import DirectiveLocation
|
9
16
|
|
@@ -84,17 +91,17 @@ class StrawberryDirective(Generic[T]):
|
|
84
91
|
python_name: str
|
85
92
|
graphql_name: Optional[str]
|
86
93
|
resolver: StrawberryDirectiveResolver[T]
|
87
|
-
locations:
|
94
|
+
locations: list[DirectiveLocation]
|
88
95
|
description: Optional[str] = None
|
89
96
|
|
90
97
|
@cached_property
|
91
|
-
def arguments(self) ->
|
98
|
+
def arguments(self) -> list[StrawberryArgument]:
|
92
99
|
return self.resolver.arguments
|
93
100
|
|
94
101
|
|
95
102
|
def directive(
|
96
103
|
*,
|
97
|
-
locations:
|
104
|
+
locations: list[DirectiveLocation],
|
98
105
|
description: Optional[str] = None,
|
99
106
|
name: Optional[str] = None,
|
100
107
|
) -> Callable[[Callable[..., T]], StrawberryDirective[T]]:
|
strawberry/django/test/client.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any,
|
1
|
+
from typing import Any, Optional
|
2
2
|
|
3
3
|
from strawberry.test import BaseGraphQLTestClient
|
4
4
|
|
@@ -6,9 +6,9 @@ from strawberry.test import BaseGraphQLTestClient
|
|
6
6
|
class GraphQLTestClient(BaseGraphQLTestClient):
|
7
7
|
def request(
|
8
8
|
self,
|
9
|
-
body:
|
10
|
-
headers: Optional[
|
11
|
-
files: Optional[
|
9
|
+
body: dict[str, object],
|
10
|
+
headers: Optional[dict[str, object]] = None,
|
11
|
+
files: Optional[dict[str, object]] = None,
|
12
12
|
) -> Any:
|
13
13
|
if files:
|
14
14
|
return self._client.post(
|