strawberry-graphql 0.263.0.dev1743582446__py3-none-any.whl → 0.263.2__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 +0 -2
- strawberry/aiohttp/views.py +1 -1
- strawberry/annotation.py +9 -13
- strawberry/asgi/__init__.py +1 -1
- strawberry/chalice/views.py +2 -2
- strawberry/channels/handlers/http_handler.py +4 -2
- strawberry/cli/commands/codegen.py +1 -1
- strawberry/codegen/query_codegen.py +6 -6
- strawberry/django/views.py +2 -2
- strawberry/exceptions/handler.py +1 -1
- strawberry/experimental/pydantic/_compat.py +34 -4
- strawberry/experimental/pydantic/conversion.py +1 -1
- strawberry/experimental/pydantic/error_type.py +1 -1
- strawberry/experimental/pydantic/object_type.py +7 -3
- strawberry/experimental/pydantic/utils.py +8 -2
- strawberry/ext/mypy_plugin.py +3 -3
- strawberry/extensions/tracing/opentelemetry.py +2 -1
- strawberry/fastapi/router.py +1 -1
- strawberry/federation/schema.py +1 -1
- strawberry/flask/views.py +2 -2
- strawberry/http/__init__.py +4 -9
- strawberry/http/async_base_view.py +6 -82
- strawberry/litestar/controller.py +1 -1
- strawberry/printer/printer.py +9 -9
- strawberry/quart/views.py +1 -1
- strawberry/relay/exceptions.py +3 -2
- strawberry/relay/fields.py +7 -7
- strawberry/relay/types.py +31 -28
- strawberry/sanic/utils.py +2 -4
- strawberry/sanic/views.py +1 -1
- strawberry/schema/config.py +0 -1
- strawberry/schema/schema.py +23 -54
- strawberry/static/graphiql.html +5 -5
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +1 -1
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +1 -1
- strawberry/types/arguments.py +5 -4
- strawberry/types/auto.py +1 -1
- strawberry/types/field.py +1 -1
- strawberry/types/fields/resolver.py +1 -1
- strawberry/types/lazy_type.py +1 -1
- strawberry/types/type_resolver.py +1 -1
- strawberry/types/union.py +1 -1
- strawberry/utils/aio.py +20 -1
- strawberry/utils/operation.py +1 -1
- strawberry/utils/typing.py +5 -5
- {strawberry_graphql-0.263.0.dev1743582446.dist-info → strawberry_graphql-0.263.2.dist-info}/METADATA +1 -1
- {strawberry_graphql-0.263.0.dev1743582446.dist-info → strawberry_graphql-0.263.2.dist-info}/RECORD +50 -52
- strawberry/schema/_graphql_core.py +0 -46
- strawberry/streamable.py +0 -36
- {strawberry_graphql-0.263.0.dev1743582446.dist-info → strawberry_graphql-0.263.2.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.263.0.dev1743582446.dist-info → strawberry_graphql-0.263.2.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.263.0.dev1743582446.dist-info → strawberry_graphql-0.263.2.dist-info}/entry_points.txt +0 -0
strawberry/__init__.py
CHANGED
@@ -11,7 +11,6 @@ from .permission import BasePermission
|
|
11
11
|
from .scalars import ID
|
12
12
|
from .schema import Schema
|
13
13
|
from .schema_directive import schema_directive
|
14
|
-
from .streamable import Streamable
|
15
14
|
from .types.arguments import argument
|
16
15
|
from .types.auto import auto
|
17
16
|
from .types.cast import cast
|
@@ -35,7 +34,6 @@ __all__ = [
|
|
35
34
|
"Parent",
|
36
35
|
"Private",
|
37
36
|
"Schema",
|
38
|
-
"Streamable",
|
39
37
|
"argument",
|
40
38
|
"asdict",
|
41
39
|
"auto",
|
strawberry/aiohttp/views.py
CHANGED
@@ -56,7 +56,7 @@ class AioHTTPRequestAdapter(AsyncHTTPRequestAdapter):
|
|
56
56
|
|
57
57
|
@property
|
58
58
|
def method(self) -> HTTPMethod:
|
59
|
-
return cast(HTTPMethod, self.request.method.upper())
|
59
|
+
return cast("HTTPMethod", self.request.method.upper())
|
60
60
|
|
61
61
|
@property
|
62
62
|
def headers(self) -> Mapping[str, str]:
|
strawberry/annotation.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import logging
|
4
3
|
import sys
|
5
4
|
import typing
|
5
|
+
import warnings
|
6
6
|
from collections import abc
|
7
7
|
from enum import Enum
|
8
8
|
from typing import (
|
@@ -17,7 +17,6 @@ from typing import (
|
|
17
17
|
)
|
18
18
|
from typing_extensions import Self, get_args, get_origin
|
19
19
|
|
20
|
-
from strawberry.streamable import StrawberryStreamable
|
21
20
|
from strawberry.types.base import (
|
22
21
|
StrawberryList,
|
23
22
|
StrawberryObjectDefinition,
|
@@ -131,7 +130,7 @@ class StrawberryAnnotation:
|
|
131
130
|
return self.__resolve_cache__
|
132
131
|
|
133
132
|
def _resolve(self) -> Union[StrawberryType, type]:
|
134
|
-
evaled_type = cast(Any, self.evaluate())
|
133
|
+
evaled_type = cast("Any", self.evaluate())
|
135
134
|
|
136
135
|
if is_private(evaled_type):
|
137
136
|
return evaled_type
|
@@ -142,8 +141,6 @@ class StrawberryAnnotation:
|
|
142
141
|
|
143
142
|
if self._is_lazy_type(evaled_type):
|
144
143
|
return evaled_type
|
145
|
-
if self._is_streamable(evaled_type, args):
|
146
|
-
return self.create_list(list[evaled_type])
|
147
144
|
if self._is_list(evaled_type):
|
148
145
|
return self.create_list(evaled_type)
|
149
146
|
|
@@ -161,7 +158,7 @@ class StrawberryAnnotation:
|
|
161
158
|
if self._is_union(evaled_type, args):
|
162
159
|
return self.create_union(evaled_type, args)
|
163
160
|
if is_type_var(evaled_type) or evaled_type is Self:
|
164
|
-
return self.create_type_var(cast(TypeVar, evaled_type))
|
161
|
+
return self.create_type_var(cast("TypeVar", evaled_type))
|
165
162
|
if self._is_strawberry_type(evaled_type):
|
166
163
|
# Simply return objects that are already StrawberryTypes
|
167
164
|
return evaled_type
|
@@ -245,9 +242,12 @@ class StrawberryAnnotation:
|
|
245
242
|
|
246
243
|
union_args = [arg for arg in args if isinstance(arg, StrawberryUnion)]
|
247
244
|
if len(union_args) > 1:
|
248
|
-
|
249
|
-
|
250
|
-
|
245
|
+
warnings.warn(
|
246
|
+
(
|
247
|
+
"Duplicate union definition detected. "
|
248
|
+
"Only the first definition will be considered"
|
249
|
+
),
|
250
|
+
stacklevel=2,
|
251
251
|
)
|
252
252
|
|
253
253
|
if union_args:
|
@@ -313,10 +313,6 @@ class StrawberryAnnotation:
|
|
313
313
|
or is_list
|
314
314
|
)
|
315
315
|
|
316
|
-
@classmethod
|
317
|
-
def _is_streamable(cls, annotation: Any, args: list[Any]) -> bool:
|
318
|
-
return any(isinstance(arg, StrawberryStreamable) for arg in args)
|
319
|
-
|
320
316
|
@classmethod
|
321
317
|
def _is_strawberry_type(cls, evaled_type: Any) -> bool:
|
322
318
|
# Prevent import cycles
|
strawberry/asgi/__init__.py
CHANGED
@@ -60,7 +60,7 @@ class ASGIRequestAdapter(AsyncHTTPRequestAdapter):
|
|
60
60
|
|
61
61
|
@property
|
62
62
|
def method(self) -> HTTPMethod:
|
63
|
-
return cast(HTTPMethod, self.request.method.upper())
|
63
|
+
return cast("HTTPMethod", self.request.method.upper())
|
64
64
|
|
65
65
|
@property
|
66
66
|
def headers(self) -> Mapping[str, str]:
|
strawberry/chalice/views.py
CHANGED
@@ -7,7 +7,6 @@ from chalice.app import Request, Response
|
|
7
7
|
from strawberry.http.exceptions import HTTPException
|
8
8
|
from strawberry.http.sync_base_view import SyncBaseHTTPView, SyncHTTPRequestAdapter
|
9
9
|
from strawberry.http.temporal_response import TemporalResponse
|
10
|
-
from strawberry.http.types import HTTPMethod, QueryParams
|
11
10
|
from strawberry.http.typevars import Context, RootValue
|
12
11
|
|
13
12
|
if TYPE_CHECKING:
|
@@ -15,6 +14,7 @@ if TYPE_CHECKING:
|
|
15
14
|
|
16
15
|
from strawberry.http import GraphQLHTTPResponse
|
17
16
|
from strawberry.http.ides import GraphQL_IDE
|
17
|
+
from strawberry.http.types import HTTPMethod, QueryParams
|
18
18
|
from strawberry.schema import BaseSchema
|
19
19
|
|
20
20
|
|
@@ -32,7 +32,7 @@ class ChaliceHTTPRequestAdapter(SyncHTTPRequestAdapter):
|
|
32
32
|
|
33
33
|
@property
|
34
34
|
def method(self) -> HTTPMethod:
|
35
|
-
return cast(HTTPMethod, self.request.method.upper())
|
35
|
+
return cast("HTTPMethod", self.request.method.upper())
|
36
36
|
|
37
37
|
@property
|
38
38
|
def headers(self) -> Mapping[str, str]:
|
@@ -293,7 +293,8 @@ class GraphQLHTTPConsumer(
|
|
293
293
|
|
294
294
|
async def render_graphql_ide(self, request: ChannelsRequest) -> ChannelsResponse:
|
295
295
|
return ChannelsResponse(
|
296
|
-
content=self.graphql_ide_html.encode(),
|
296
|
+
content=self.graphql_ide_html.encode(),
|
297
|
+
content_type="text/html; charset=utf-8",
|
297
298
|
)
|
298
299
|
|
299
300
|
def is_websocket_request(
|
@@ -348,7 +349,8 @@ class SyncGraphQLHTTPConsumer(
|
|
348
349
|
|
349
350
|
def render_graphql_ide(self, request: ChannelsRequest) -> ChannelsResponse:
|
350
351
|
return ChannelsResponse(
|
351
|
-
content=self.graphql_ide_html.encode(),
|
352
|
+
content=self.graphql_ide_html.encode(),
|
353
|
+
content_type="text/html; charset=utf-8",
|
352
354
|
)
|
353
355
|
|
354
356
|
# Sync channels is actually async, but it uses database_sync_to_async to call
|
@@ -133,7 +133,7 @@ def codegen(
|
|
133
133
|
console_plugin.before_any_start()
|
134
134
|
|
135
135
|
for q in query:
|
136
|
-
plugins = cast(list[QueryCodegenPlugin], _load_plugins(selected_plugins, q))
|
136
|
+
plugins = cast("list[QueryCodegenPlugin]", _load_plugins(selected_plugins, q))
|
137
137
|
|
138
138
|
code_generator = QueryCodegen(
|
139
139
|
schema_symbol, plugins=plugins, console_plugin=console_plugin
|
@@ -362,7 +362,7 @@ class QueryCodegen:
|
|
362
362
|
# The FragmentDefinitionNode has a non-Optional `SelectionSetNode` but
|
363
363
|
# the Protocol wants an `Optional[SelectionSetNode]` so this doesn't
|
364
364
|
# quite conform.
|
365
|
-
cast(HasSelectionSet, fd),
|
365
|
+
cast("HasSelectionSet", fd),
|
366
366
|
parent_type=query_type,
|
367
367
|
class_name=fd.name.value,
|
368
368
|
graph_ql_object_type_factory=graph_ql_object_type_factory,
|
@@ -468,13 +468,13 @@ class QueryCodegen:
|
|
468
468
|
result_class_name = f"{operation_name}Result"
|
469
469
|
|
470
470
|
operation_type = self._collect_types(
|
471
|
-
cast(HasSelectionSet, operation_definition),
|
471
|
+
cast("HasSelectionSet", operation_definition),
|
472
472
|
parent_type=query_type,
|
473
473
|
class_name=result_class_name,
|
474
474
|
)
|
475
475
|
|
476
476
|
operation_kind = cast(
|
477
|
-
Literal[
|
477
|
+
"Literal['query', 'mutation', 'subscription']",
|
478
478
|
operation_definition.operation.value,
|
479
479
|
)
|
480
480
|
|
@@ -801,7 +801,7 @@ class QueryCodegen:
|
|
801
801
|
# `GraphQLField` or `GraphQLFragmentSpread`
|
802
802
|
# and the suite above will cause this statement to be
|
803
803
|
# skipped if there are any `GraphQLFragmentSpread`.
|
804
|
-
current_type.fields = cast(list[GraphQLField], fields)
|
804
|
+
current_type.fields = cast("list[GraphQLField]", fields)
|
805
805
|
|
806
806
|
self._collect_type(current_type)
|
807
807
|
|
@@ -854,7 +854,7 @@ class QueryCodegen:
|
|
854
854
|
assert isinstance(sub_selection, FieldNode)
|
855
855
|
|
856
856
|
parent_type = cast(
|
857
|
-
StrawberryObjectDefinition,
|
857
|
+
"StrawberryObjectDefinition",
|
858
858
|
self.schema.get_type_by_name(type_condition_name),
|
859
859
|
)
|
860
860
|
|
@@ -889,7 +889,7 @@ class QueryCodegen:
|
|
889
889
|
# `GraphQLField` or `GraphQLFragmentSpread`
|
890
890
|
# and the suite above will cause this statement to be
|
891
891
|
# skipped if there are any `GraphQLFragmentSpread`.
|
892
|
-
current_type.fields.extend(cast(list[GraphQLField], fields))
|
892
|
+
current_type.fields.extend(cast("list[GraphQLField]", fields))
|
893
893
|
|
894
894
|
sub_types.append(current_type)
|
895
895
|
|
strawberry/django/views.py
CHANGED
@@ -83,7 +83,7 @@ class DjangoHTTPRequestAdapter(SyncHTTPRequestAdapter):
|
|
83
83
|
def method(self) -> HTTPMethod:
|
84
84
|
assert self.request.method is not None
|
85
85
|
|
86
|
-
return cast(HTTPMethod, self.request.method.upper())
|
86
|
+
return cast("HTTPMethod", self.request.method.upper())
|
87
87
|
|
88
88
|
@property
|
89
89
|
def headers(self) -> Mapping[str, str]:
|
@@ -114,7 +114,7 @@ class AsyncDjangoHTTPRequestAdapter(AsyncHTTPRequestAdapter):
|
|
114
114
|
def method(self) -> HTTPMethod:
|
115
115
|
assert self.request.method is not None
|
116
116
|
|
117
|
-
return cast(HTTPMethod, self.request.method.upper())
|
117
|
+
return cast("HTTPMethod", self.request.method.upper())
|
118
118
|
|
119
119
|
@property
|
120
120
|
def headers(self) -> Mapping[str, str]:
|
strawberry/exceptions/handler.py
CHANGED
@@ -70,7 +70,7 @@ def strawberry_threading_exception_handler(
|
|
70
70
|
# (we'd need to do type ignore for python 3.8 and above, but mypy
|
71
71
|
# doesn't seem to be able to handle that and will complain in python 3.7)
|
72
72
|
|
73
|
-
cast(Any, original_threading_exception_hook)(args)
|
73
|
+
cast("Any", original_threading_exception_hook)(args)
|
74
74
|
|
75
75
|
return
|
76
76
|
|
@@ -12,7 +12,7 @@ from pydantic.version import VERSION as PYDANTIC_VERSION
|
|
12
12
|
from strawberry.experimental.pydantic.exceptions import UnsupportedTypeError
|
13
13
|
|
14
14
|
if TYPE_CHECKING:
|
15
|
-
from pydantic.fields import FieldInfo
|
15
|
+
from pydantic.fields import ComputedFieldInfo, FieldInfo
|
16
16
|
|
17
17
|
IS_PYDANTIC_V2: bool = PYDANTIC_VERSION.startswith("2.")
|
18
18
|
IS_PYDANTIC_V1: bool = not IS_PYDANTIC_V2
|
@@ -128,7 +128,33 @@ class PydanticV2Compat:
|
|
128
128
|
|
129
129
|
return PydanticUndefined
|
130
130
|
|
131
|
-
def
|
131
|
+
def get_model_computed_fields(
|
132
|
+
self, model: type[BaseModel]
|
133
|
+
) -> dict[str, CompatModelField]:
|
134
|
+
computed_field_info: dict[str, ComputedFieldInfo] = model.model_computed_fields
|
135
|
+
new_fields = {}
|
136
|
+
# Convert it into CompatModelField
|
137
|
+
for name, field in computed_field_info.items():
|
138
|
+
new_fields[name] = CompatModelField(
|
139
|
+
name=name,
|
140
|
+
type_=field.return_type,
|
141
|
+
outer_type_=field.return_type,
|
142
|
+
default=None,
|
143
|
+
default_factory=None,
|
144
|
+
required=False,
|
145
|
+
alias=field.alias,
|
146
|
+
# v2 doesn't have allow_none
|
147
|
+
allow_none=False,
|
148
|
+
has_alias=field is not None,
|
149
|
+
description=field.description,
|
150
|
+
_missing_type=self.PYDANTIC_MISSING_TYPE,
|
151
|
+
is_v1=False,
|
152
|
+
)
|
153
|
+
return new_fields
|
154
|
+
|
155
|
+
def get_model_fields(
|
156
|
+
self, model: type[BaseModel], include_computed: bool = False
|
157
|
+
) -> dict[str, CompatModelField]:
|
132
158
|
field_info: dict[str, FieldInfo] = model.model_fields
|
133
159
|
new_fields = {}
|
134
160
|
# Convert it into CompatModelField
|
@@ -148,6 +174,8 @@ class PydanticV2Compat:
|
|
148
174
|
_missing_type=self.PYDANTIC_MISSING_TYPE,
|
149
175
|
is_v1=False,
|
150
176
|
)
|
177
|
+
if include_computed:
|
178
|
+
new_fields |= self.get_model_computed_fields(model)
|
151
179
|
return new_fields
|
152
180
|
|
153
181
|
@cached_property
|
@@ -175,7 +203,10 @@ class PydanticV1Compat:
|
|
175
203
|
def PYDANTIC_MISSING_TYPE(self) -> Any: # noqa: N802
|
176
204
|
return dataclasses.MISSING
|
177
205
|
|
178
|
-
def get_model_fields(
|
206
|
+
def get_model_fields(
|
207
|
+
self, model: type[BaseModel], include_computed: bool = False
|
208
|
+
) -> dict[str, CompatModelField]:
|
209
|
+
"""`include_computed` is a noop for PydanticV1Compat."""
|
179
210
|
new_fields = {}
|
180
211
|
# Convert it into CompatModelField
|
181
212
|
for name, field in model.__fields__.items(): # type: ignore[attr-defined]
|
@@ -284,7 +315,6 @@ else:
|
|
284
315
|
smart_deepcopy,
|
285
316
|
)
|
286
317
|
|
287
|
-
|
288
318
|
__all__ = [
|
289
319
|
"PydanticCompat",
|
290
320
|
"get_args",
|
@@ -35,7 +35,7 @@ def _convert_from_pydantic_to_strawberry_type(
|
|
35
35
|
if hasattr(option_type, "_pydantic_type"):
|
36
36
|
source_type = option_type._pydantic_type
|
37
37
|
else:
|
38
|
-
source_type = cast(type, option_type)
|
38
|
+
source_type = cast("type", option_type)
|
39
39
|
if isinstance(data, source_type):
|
40
40
|
return _convert_from_pydantic_to_strawberry_type(
|
41
41
|
option_type, data_from_model=data, extra=extra
|
@@ -116,7 +116,7 @@ def error_type(
|
|
116
116
|
]
|
117
117
|
|
118
118
|
wrapped: type[WithStrawberryObjectDefinition] = _wrap_dataclass(cls)
|
119
|
-
extra_fields = cast(list[dataclasses.Field], _get_fields(wrapped, {}))
|
119
|
+
extra_fields = cast("list[dataclasses.Field]", _get_fields(wrapped, {}))
|
120
120
|
private_fields = get_private_fields(wrapped)
|
121
121
|
|
122
122
|
all_model_fields.extend(
|
@@ -126,11 +126,12 @@ def type( # noqa: PLR0915
|
|
126
126
|
description: Optional[str] = None,
|
127
127
|
directives: Optional[Sequence[object]] = (),
|
128
128
|
all_fields: bool = False,
|
129
|
+
include_computed: bool = False,
|
129
130
|
use_pydantic_alias: bool = True,
|
130
131
|
) -> Callable[..., builtins.type[StrawberryTypeFromPydantic[PydanticModel]]]:
|
131
132
|
def wrap(cls: Any) -> builtins.type[StrawberryTypeFromPydantic[PydanticModel]]: # noqa: PLR0915
|
132
133
|
compat = PydanticCompat.from_model(model)
|
133
|
-
model_fields = compat.get_model_fields(model)
|
134
|
+
model_fields = compat.get_model_fields(model, include_computed=include_computed)
|
134
135
|
original_fields_set = set(fields) if fields else set()
|
135
136
|
|
136
137
|
if fields:
|
@@ -171,12 +172,15 @@ def type( # noqa: PLR0915
|
|
171
172
|
raise MissingFieldsListError(cls)
|
172
173
|
|
173
174
|
ensure_all_auto_fields_in_pydantic(
|
174
|
-
model=model,
|
175
|
+
model=model,
|
176
|
+
auto_fields=auto_fields_set,
|
177
|
+
cls_name=cls.__name__,
|
178
|
+
include_computed=include_computed,
|
175
179
|
)
|
176
180
|
|
177
181
|
wrapped = _wrap_dataclass(cls)
|
178
182
|
extra_strawberry_fields = _get_fields(wrapped, {})
|
179
|
-
extra_fields = cast(list[dataclasses.Field], extra_strawberry_fields)
|
183
|
+
extra_fields = cast("list[dataclasses.Field]", extra_strawberry_fields)
|
180
184
|
private_fields = get_private_fields(wrapped)
|
181
185
|
|
182
186
|
extra_fields_dict = {field.name: field for field in extra_strawberry_fields}
|
@@ -117,11 +117,17 @@ def get_default_factory_for_field(
|
|
117
117
|
|
118
118
|
|
119
119
|
def ensure_all_auto_fields_in_pydantic(
|
120
|
-
model: type[BaseModel],
|
120
|
+
model: type[BaseModel],
|
121
|
+
auto_fields: set[str],
|
122
|
+
cls_name: str,
|
123
|
+
include_computed: bool = False,
|
121
124
|
) -> None:
|
122
125
|
compat = PydanticCompat.from_model(model)
|
123
126
|
# Raise error if user defined a strawberry.auto field not present in the model
|
124
|
-
non_existing_fields = list(
|
127
|
+
non_existing_fields = list(
|
128
|
+
auto_fields
|
129
|
+
- compat.get_model_fields(model, include_computed=include_computed).keys()
|
130
|
+
)
|
125
131
|
|
126
132
|
if non_existing_fields:
|
127
133
|
raise AutoFieldsNotInBaseModelError(
|
strawberry/ext/mypy_plugin.py
CHANGED
@@ -65,7 +65,7 @@ try:
|
|
65
65
|
from pydantic.mypy import METADATA_KEY as PYDANTIC_METADATA_KEY
|
66
66
|
from pydantic.mypy import PydanticModelField
|
67
67
|
|
68
|
-
PYDANTIC_VERSION = tuple(map(int, pydantic.__version__.split(".")))
|
68
|
+
PYDANTIC_VERSION = tuple(map(int, pydantic.__version__.split("."))) # noqa: RUF048
|
69
69
|
|
70
70
|
from strawberry.experimental.pydantic._compat import IS_PYDANTIC_V1
|
71
71
|
except ImportError:
|
@@ -397,7 +397,7 @@ def strawberry_pydantic_class_callback(ctx: ClassDefContext) -> None:
|
|
397
397
|
]
|
398
398
|
add_method(ctx, "__init__", init_args, NoneType())
|
399
399
|
|
400
|
-
model_type = cast(Instance, _get_type_for_expr(model_expression, ctx.api))
|
400
|
+
model_type = cast("Instance", _get_type_for_expr(model_expression, ctx.api))
|
401
401
|
|
402
402
|
# these are the fields that the user added to the strawberry type
|
403
403
|
new_strawberry_fields: set[str] = set()
|
@@ -405,7 +405,7 @@ def strawberry_pydantic_class_callback(ctx: ClassDefContext) -> None:
|
|
405
405
|
# TODO: think about inheritance for strawberry?
|
406
406
|
for stmt in ctx.cls.defs.body:
|
407
407
|
if isinstance(stmt, AssignmentStmt):
|
408
|
-
lhs = cast(NameExpr, stmt.lvalues[0])
|
408
|
+
lhs = cast("NameExpr", stmt.lvalues[0])
|
409
409
|
new_strawberry_fields.add(lhs.name)
|
410
410
|
|
411
411
|
pydantic_fields: set[PydanticModelField] = set()
|
@@ -42,9 +42,10 @@ class OpenTelemetryExtension(SchemaExtension):
|
|
42
42
|
*,
|
43
43
|
execution_context: Optional[ExecutionContext] = None,
|
44
44
|
arg_filter: Optional[ArgFilter] = None,
|
45
|
+
tracer_provider: Optional[trace.TracerProvider] = None,
|
45
46
|
) -> None:
|
46
47
|
self._arg_filter = arg_filter
|
47
|
-
self._tracer = trace.get_tracer("strawberry")
|
48
|
+
self._tracer = trace.get_tracer("strawberry", tracer_provider=tracer_provider)
|
48
49
|
self._span_holder = {}
|
49
50
|
if execution_context:
|
50
51
|
self.execution_context = execution_context
|
strawberry/fastapi/router.py
CHANGED
@@ -76,7 +76,7 @@ class GraphQLRouter(
|
|
76
76
|
connection: HTTPConnection,
|
77
77
|
response: Response = None, # type: ignore
|
78
78
|
) -> MergedContext:
|
79
|
-
request = cast(Union[Request, WebSocket], connection)
|
79
|
+
request = cast("Union[Request, WebSocket]", connection)
|
80
80
|
if isinstance(custom_context, BaseContext):
|
81
81
|
custom_context.request = request
|
82
82
|
custom_context.background_tasks = background_tasks
|
strawberry/federation/schema.py
CHANGED
@@ -158,7 +158,7 @@ class Schema(BaseSchema):
|
|
158
158
|
type_name = representation.pop("__typename")
|
159
159
|
type_ = self.schema_converter.type_map[type_name]
|
160
160
|
|
161
|
-
definition = cast(StrawberryObjectDefinition, type_.definition)
|
161
|
+
definition = cast("StrawberryObjectDefinition", type_.definition)
|
162
162
|
|
163
163
|
if hasattr(definition.origin, "resolve_reference"):
|
164
164
|
resolve_reference = definition.origin.resolve_reference
|
strawberry/flask/views.py
CHANGED
@@ -45,7 +45,7 @@ class FlaskHTTPRequestAdapter(SyncHTTPRequestAdapter):
|
|
45
45
|
|
46
46
|
@property
|
47
47
|
def method(self) -> HTTPMethod:
|
48
|
-
return cast(HTTPMethod, self.request.method.upper())
|
48
|
+
return cast("HTTPMethod", self.request.method.upper())
|
49
49
|
|
50
50
|
@property
|
51
51
|
def headers(self) -> Mapping[str, str]:
|
@@ -139,7 +139,7 @@ class AsyncFlaskHTTPRequestAdapter(AsyncHTTPRequestAdapter):
|
|
139
139
|
|
140
140
|
@property
|
141
141
|
def method(self) -> HTTPMethod:
|
142
|
-
return cast(HTTPMethod, self.request.method.upper())
|
142
|
+
return cast("HTTPMethod", self.request.method.upper())
|
143
143
|
|
144
144
|
@property
|
145
145
|
def content_type(self) -> Optional[str]:
|
strawberry/http/__init__.py
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import Any, Optional
|
4
|
+
from typing import TYPE_CHECKING, Any, Optional
|
5
5
|
from typing_extensions import Literal, TypedDict
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
ResultType,
|
10
|
-
)
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from strawberry.types import ExecutionResult
|
11
9
|
|
12
10
|
|
13
11
|
class GraphQLHTTPResponse(TypedDict, total=False):
|
@@ -16,10 +14,7 @@ class GraphQLHTTPResponse(TypedDict, total=False):
|
|
16
14
|
extensions: Optional[dict[str, object]]
|
17
15
|
|
18
16
|
|
19
|
-
def process_result(result:
|
20
|
-
if isinstance(result, GraphQLIncrementalExecutionResults):
|
21
|
-
return result
|
22
|
-
|
17
|
+
def process_result(result: ExecutionResult) -> GraphQLHTTPResponse:
|
23
18
|
data: GraphQLHTTPResponse = {"data": result.data}
|
24
19
|
|
25
20
|
if result.errors:
|
@@ -25,9 +25,6 @@ from strawberry.http import (
|
|
25
25
|
process_result,
|
26
26
|
)
|
27
27
|
from strawberry.http.ides import GraphQL_IDE
|
28
|
-
from strawberry.schema._graphql_core import (
|
29
|
-
GraphQLIncrementalExecutionResults,
|
30
|
-
)
|
31
28
|
from strawberry.schema.base import BaseSchema
|
32
29
|
from strawberry.schema.exceptions import InvalidOperationTypeError
|
33
30
|
from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
|
@@ -261,7 +258,7 @@ class AsyncBaseHTTPView(
|
|
261
258
|
root_value: Optional[RootValue] = UNSET,
|
262
259
|
) -> WebSocketResponse: ...
|
263
260
|
|
264
|
-
async def run(
|
261
|
+
async def run(
|
265
262
|
self,
|
266
263
|
request: Union[Request, WebSocketRequest],
|
267
264
|
context: Optional[Context] = UNSET,
|
@@ -309,7 +306,7 @@ class AsyncBaseHTTPView(
|
|
309
306
|
await websocket.close(4406, "Subprotocol not acceptable")
|
310
307
|
|
311
308
|
return websocket_response
|
312
|
-
request = cast(Request, request)
|
309
|
+
request = cast("Request", request)
|
313
310
|
|
314
311
|
request_adapter = self.request_adapter_class(request)
|
315
312
|
sub_response = await self.get_sub_response(request)
|
@@ -352,75 +349,6 @@ class AsyncBaseHTTPView(
|
|
352
349
|
"Content-Type": "multipart/mixed;boundary=graphql;subscriptionSpec=1.0,application/json",
|
353
350
|
},
|
354
351
|
)
|
355
|
-
if isinstance(result, GraphQLIncrementalExecutionResults):
|
356
|
-
|
357
|
-
async def stream() -> AsyncGenerator[str, None]:
|
358
|
-
yield "---"
|
359
|
-
|
360
|
-
response = await self.process_result(request, result.initial_result)
|
361
|
-
|
362
|
-
response["hasNext"] = result.initial_result.has_next
|
363
|
-
response["pending"] = [
|
364
|
-
p.formatted for p in result.initial_result.pending
|
365
|
-
]
|
366
|
-
response["extensions"] = result.initial_result.extensions
|
367
|
-
|
368
|
-
yield self.encode_multipart_data(response, "-")
|
369
|
-
|
370
|
-
all_pending = result.initial_result.pending
|
371
|
-
|
372
|
-
async for value in result.subsequent_results:
|
373
|
-
response = {
|
374
|
-
"hasNext": value.has_next,
|
375
|
-
"extensions": value.extensions,
|
376
|
-
}
|
377
|
-
|
378
|
-
if value.pending:
|
379
|
-
response["pending"] = [p.formatted for p in value.pending]
|
380
|
-
|
381
|
-
if value.completed:
|
382
|
-
response["completed"] = [p.formatted for p in value.completed]
|
383
|
-
|
384
|
-
if value.incremental:
|
385
|
-
incremental = []
|
386
|
-
|
387
|
-
all_pending.extend(value.pending)
|
388
|
-
|
389
|
-
for incremental_value in value.incremental:
|
390
|
-
pending_value = next(
|
391
|
-
(
|
392
|
-
v
|
393
|
-
for v in all_pending
|
394
|
-
if v.id == incremental_value.id
|
395
|
-
),
|
396
|
-
None,
|
397
|
-
)
|
398
|
-
|
399
|
-
assert pending_value
|
400
|
-
|
401
|
-
incremental.append(
|
402
|
-
{
|
403
|
-
**incremental_value.formatted,
|
404
|
-
"path": pending_value.path,
|
405
|
-
"label": pending_value.label,
|
406
|
-
}
|
407
|
-
)
|
408
|
-
|
409
|
-
response["incremental"] = incremental
|
410
|
-
|
411
|
-
yield self.encode_multipart_data(response, "-")
|
412
|
-
|
413
|
-
yield "--\r\n"
|
414
|
-
|
415
|
-
return await self.create_streaming_response(
|
416
|
-
request,
|
417
|
-
stream,
|
418
|
-
sub_response,
|
419
|
-
headers={
|
420
|
-
"Transfer-Encoding": "chunked",
|
421
|
-
"Content-Type": 'multipart/mixed; boundary="-"',
|
422
|
-
},
|
423
|
-
)
|
424
352
|
|
425
353
|
response_data = await self.process_result(request=request, result=result)
|
426
354
|
|
@@ -432,16 +360,12 @@ class AsyncBaseHTTPView(
|
|
432
360
|
)
|
433
361
|
|
434
362
|
def encode_multipart_data(self, data: Any, separator: str) -> str:
|
435
|
-
encoded_data = self.encode_json(data)
|
436
|
-
|
437
363
|
return "".join(
|
438
364
|
[
|
439
|
-
"\r\n",
|
440
|
-
"Content-Type: application/json
|
441
|
-
|
442
|
-
"\
|
443
|
-
encoded_data,
|
444
|
-
f"\r\n--{separator}",
|
365
|
+
f"\r\n--{separator}\r\n",
|
366
|
+
"Content-Type: application/json\r\n\r\n",
|
367
|
+
self.encode_json(data),
|
368
|
+
"\n",
|
445
369
|
]
|
446
370
|
)
|
447
371
|
|
@@ -163,7 +163,7 @@ class LitestarRequestAdapter(AsyncHTTPRequestAdapter):
|
|
163
163
|
|
164
164
|
@property
|
165
165
|
def method(self) -> HTTPMethod:
|
166
|
-
return cast(HTTPMethod, self.request.method.upper())
|
166
|
+
return cast("HTTPMethod", self.request.method.upper())
|
167
167
|
|
168
168
|
@property
|
169
169
|
def headers(self) -> Mapping[str, str]:
|