strawberry-graphql 0.279.0.dev1754159379__py3-none-any.whl → 0.281.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.
Potentially problematic release.
This version of strawberry-graphql might be problematic. Click here for more details.
- strawberry/__init__.py +1 -2
- strawberry/aiohttp/views.py +2 -50
- strawberry/asgi/__init__.py +2 -39
- strawberry/chalice/views.py +7 -75
- strawberry/channels/handlers/http_handler.py +30 -6
- strawberry/channels/handlers/ws_handler.py +0 -2
- strawberry/cli/commands/server.py +1 -11
- strawberry/cli/commands/upgrade/__init__.py +2 -0
- strawberry/cli/constants.py +0 -1
- strawberry/cli/debug_server.py +2 -6
- strawberry/codemods/__init__.py +9 -0
- strawberry/codemods/maybe_optional.py +118 -0
- strawberry/django/views.py +4 -73
- strawberry/experimental/pydantic/_compat.py +1 -0
- strawberry/experimental/pydantic/error_type.py +1 -0
- strawberry/experimental/pydantic/fields.py +1 -0
- strawberry/experimental/pydantic/utils.py +1 -0
- strawberry/fastapi/router.py +8 -6
- strawberry/flask/views.py +4 -74
- strawberry/http/async_base_view.py +5 -34
- strawberry/http/base.py +2 -1
- strawberry/http/exceptions.py +5 -7
- strawberry/http/sync_base_view.py +1 -34
- strawberry/litestar/controller.py +1 -42
- strawberry/quart/views.py +3 -35
- strawberry/relay/utils.py +9 -21
- strawberry/sanic/views.py +4 -43
- strawberry/schema/schema.py +2 -0
- strawberry/schema/schema_converter.py +15 -38
- strawberry/schema/validation_rules/maybe_null.py +136 -0
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +0 -10
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +0 -6
- strawberry/types/arguments.py +16 -2
- strawberry/types/maybe.py +1 -1
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.281.0.dist-info}/METADATA +2 -1
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.281.0.dist-info}/RECORD +39 -42
- strawberry/pydantic/__init__.py +0 -22
- strawberry/pydantic/error.py +0 -51
- strawberry/pydantic/fields.py +0 -202
- strawberry/pydantic/object_type.py +0 -348
- strawberry/utils/debug.py +0 -46
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.281.0.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.281.0.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.281.0.dist-info}/entry_points.txt +0 -0
strawberry/relay/utils.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Any, Union
|
|
|
7
7
|
from typing_extensions import Self, assert_never
|
|
8
8
|
|
|
9
9
|
from strawberry.types.base import StrawberryObjectDefinition
|
|
10
|
-
from strawberry.types.nodes import InlineFragment
|
|
10
|
+
from strawberry.types.nodes import InlineFragment
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
13
|
from strawberry.types.info import Info
|
|
@@ -83,31 +83,19 @@ def should_resolve_list_connection_edges(info: Info) -> bool:
|
|
|
83
83
|
|
|
84
84
|
"""
|
|
85
85
|
resolve_for_field_names = {"edges", "pageInfo"}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
Returns:
|
|
94
|
-
bool: True if the user requested to resolve the `edges` field of a connection, False otherwise.
|
|
95
|
-
"""
|
|
86
|
+
# Recursively inspect the selection to check if the user requested to resolve the `edges` field.
|
|
87
|
+
stack = []
|
|
88
|
+
for selection_field in info.selected_fields:
|
|
89
|
+
stack.extend(selection_field.selections)
|
|
90
|
+
while stack:
|
|
91
|
+
selection = stack.pop()
|
|
96
92
|
if (
|
|
97
93
|
not isinstance(selection, InlineFragment)
|
|
98
94
|
and selection.name in resolve_for_field_names
|
|
99
95
|
):
|
|
100
96
|
return True
|
|
101
|
-
if selection
|
|
102
|
-
|
|
103
|
-
_check_selection(selection) for selection in selection.selections
|
|
104
|
-
)
|
|
105
|
-
return False
|
|
106
|
-
|
|
107
|
-
for selection_field in info.selected_fields:
|
|
108
|
-
for selection in selection_field.selections:
|
|
109
|
-
if _check_selection(selection):
|
|
110
|
-
return True
|
|
97
|
+
if nested_selections := getattr(selection, "selections", None):
|
|
98
|
+
stack.extend(nested_selections)
|
|
111
99
|
return False
|
|
112
100
|
|
|
113
101
|
|
strawberry/sanic/views.py
CHANGED
|
@@ -8,68 +8,29 @@ from typing import (
|
|
|
8
8
|
Callable,
|
|
9
9
|
Optional,
|
|
10
10
|
Union,
|
|
11
|
-
cast,
|
|
12
11
|
)
|
|
13
12
|
from typing_extensions import TypeGuard
|
|
14
13
|
|
|
14
|
+
from lia import HTTPException, SanicHTTPRequestAdapter
|
|
15
|
+
|
|
15
16
|
from sanic.request import Request
|
|
16
17
|
from sanic.response import HTTPResponse, html
|
|
17
18
|
from sanic.views import HTTPMethodView
|
|
18
|
-
from strawberry.http.async_base_view import AsyncBaseHTTPView
|
|
19
|
-
from strawberry.http.exceptions import HTTPException
|
|
19
|
+
from strawberry.http.async_base_view import AsyncBaseHTTPView
|
|
20
20
|
from strawberry.http.temporal_response import TemporalResponse
|
|
21
|
-
from strawberry.http.types import FormData, HTTPMethod, QueryParams
|
|
22
21
|
from strawberry.http.typevars import (
|
|
23
22
|
Context,
|
|
24
23
|
RootValue,
|
|
25
24
|
)
|
|
26
|
-
from strawberry.sanic.utils import convert_request_to_files_dict
|
|
27
25
|
|
|
28
26
|
if TYPE_CHECKING:
|
|
29
|
-
from collections.abc import AsyncGenerator
|
|
27
|
+
from collections.abc import AsyncGenerator
|
|
30
28
|
|
|
31
29
|
from strawberry.http import GraphQLHTTPResponse
|
|
32
30
|
from strawberry.http.ides import GraphQL_IDE
|
|
33
31
|
from strawberry.schema import BaseSchema
|
|
34
32
|
|
|
35
33
|
|
|
36
|
-
class SanicHTTPRequestAdapter(AsyncHTTPRequestAdapter):
|
|
37
|
-
def __init__(self, request: Request) -> None:
|
|
38
|
-
self.request = request
|
|
39
|
-
|
|
40
|
-
@property
|
|
41
|
-
def query_params(self) -> QueryParams:
|
|
42
|
-
# Just a heads up, Sanic's request.args uses urllib.parse.parse_qs
|
|
43
|
-
# to parse query string parameters. This returns a dictionary where
|
|
44
|
-
# the keys are the unique variable names and the values are lists
|
|
45
|
-
# of values for each variable name. To ensure consistency, we're
|
|
46
|
-
# enforcing the use of the first value in each list.
|
|
47
|
-
args = self.request.get_args(keep_blank_values=True)
|
|
48
|
-
return {k: args.get(k, None) for k in args}
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def method(self) -> HTTPMethod:
|
|
52
|
-
return cast("HTTPMethod", self.request.method.upper())
|
|
53
|
-
|
|
54
|
-
@property
|
|
55
|
-
def headers(self) -> Mapping[str, str]:
|
|
56
|
-
return self.request.headers
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def content_type(self) -> Optional[str]:
|
|
60
|
-
return self.request.content_type
|
|
61
|
-
|
|
62
|
-
async def get_body(self) -> str:
|
|
63
|
-
return self.request.body.decode()
|
|
64
|
-
|
|
65
|
-
async def get_form_data(self) -> FormData:
|
|
66
|
-
assert self.request.form is not None
|
|
67
|
-
|
|
68
|
-
files = convert_request_to_files_dict(self.request)
|
|
69
|
-
|
|
70
|
-
return FormData(form=self.request.form, files=files)
|
|
71
|
-
|
|
72
|
-
|
|
73
34
|
class GraphQLView(
|
|
74
35
|
AsyncBaseHTTPView[
|
|
75
36
|
Request,
|
strawberry/schema/schema.py
CHANGED
|
@@ -50,6 +50,7 @@ from strawberry.extensions.directives import (
|
|
|
50
50
|
from strawberry.extensions.runner import SchemaExtensionsRunner
|
|
51
51
|
from strawberry.printer import print_schema
|
|
52
52
|
from strawberry.schema.schema_converter import GraphQLCoreConverter
|
|
53
|
+
from strawberry.schema.validation_rules.maybe_null import MaybeNullValidationRule
|
|
53
54
|
from strawberry.schema.validation_rules.one_of import OneOfInputValidationRule
|
|
54
55
|
from strawberry.types.base import (
|
|
55
56
|
StrawberryObjectDefinition,
|
|
@@ -124,6 +125,7 @@ def validate_document(
|
|
|
124
125
|
) -> list[GraphQLError]:
|
|
125
126
|
validation_rules = (
|
|
126
127
|
*validation_rules,
|
|
128
|
+
MaybeNullValidationRule,
|
|
127
129
|
OneOfInputValidationRule,
|
|
128
130
|
)
|
|
129
131
|
return validate(
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import contextlib
|
|
4
3
|
import dataclasses
|
|
5
4
|
import sys
|
|
6
5
|
from functools import partial, reduce
|
|
@@ -732,27 +731,14 @@ class GraphQLCoreConverter:
|
|
|
732
731
|
) -> Any:
|
|
733
732
|
# parse field arguments into Strawberry input types and convert
|
|
734
733
|
# field names to Python equivalents
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
)
|
|
744
|
-
except Exception as exc:
|
|
745
|
-
# Try to import Pydantic ValidationError
|
|
746
|
-
with contextlib.suppress(ImportError):
|
|
747
|
-
from pydantic import ValidationError
|
|
748
|
-
|
|
749
|
-
if isinstance(
|
|
750
|
-
exc, ValidationError
|
|
751
|
-
) and self._should_convert_validation_error(field):
|
|
752
|
-
from strawberry.pydantic import Error
|
|
753
|
-
|
|
754
|
-
return Error.from_validation_error(exc)
|
|
755
|
-
raise
|
|
734
|
+
field_args, field_kwargs = get_arguments(
|
|
735
|
+
field=field,
|
|
736
|
+
source=_source,
|
|
737
|
+
info=info,
|
|
738
|
+
kwargs=kwargs,
|
|
739
|
+
config=self.config,
|
|
740
|
+
scalar_registry=self.scalar_registry,
|
|
741
|
+
)
|
|
756
742
|
|
|
757
743
|
resolver_requested_info = False
|
|
758
744
|
if "info" in field_kwargs:
|
|
@@ -813,22 +799,6 @@ class GraphQLCoreConverter:
|
|
|
813
799
|
_resolver._is_default = not field.base_resolver # type: ignore
|
|
814
800
|
return _resolver
|
|
815
801
|
|
|
816
|
-
def _should_convert_validation_error(self, field: StrawberryField) -> bool:
|
|
817
|
-
"""Check if field return type is a Union containing strawberry.pydantic.Error."""
|
|
818
|
-
from strawberry.types.union import StrawberryUnion
|
|
819
|
-
|
|
820
|
-
field_type = field.type
|
|
821
|
-
if isinstance(field_type, StrawberryUnion):
|
|
822
|
-
# Import Error dynamically to avoid circular imports
|
|
823
|
-
try:
|
|
824
|
-
from strawberry.pydantic import Error
|
|
825
|
-
|
|
826
|
-
return any(union_type is Error for union_type in field_type.types)
|
|
827
|
-
except ImportError:
|
|
828
|
-
# If strawberry.pydantic doesn't exist or Error isn't available
|
|
829
|
-
return False
|
|
830
|
-
return False
|
|
831
|
-
|
|
832
802
|
def from_scalar(self, scalar: type) -> GraphQLScalarType:
|
|
833
803
|
from strawberry.relay.types import GlobalID
|
|
834
804
|
|
|
@@ -884,6 +854,13 @@ class GraphQLCoreConverter:
|
|
|
884
854
|
NoneType = type(None)
|
|
885
855
|
if type_ is None or type_ is NoneType:
|
|
886
856
|
return self.from_type(type_)
|
|
857
|
+
if isinstance(type_, StrawberryMaybe):
|
|
858
|
+
# StrawberryMaybe should always generate optional types
|
|
859
|
+
# because Maybe[T] = Union[Some[T], None] (field can be absent)
|
|
860
|
+
# But we need to handle the case where of_type is itself optional
|
|
861
|
+
if isinstance(type_.of_type, StrawberryOptional):
|
|
862
|
+
return self.from_type(type_.of_type.of_type)
|
|
863
|
+
return self.from_type(type_.of_type)
|
|
887
864
|
if isinstance(type_, StrawberryOptional):
|
|
888
865
|
return self.from_type(type_.of_type)
|
|
889
866
|
return GraphQLNonNull(self.from_type(type_))
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from graphql import (
|
|
4
|
+
ArgumentNode,
|
|
5
|
+
GraphQLError,
|
|
6
|
+
GraphQLNamedType,
|
|
7
|
+
ObjectValueNode,
|
|
8
|
+
ValidationContext,
|
|
9
|
+
ValidationRule,
|
|
10
|
+
get_named_type,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from strawberry.types.base import StrawberryMaybe, StrawberryOptional
|
|
14
|
+
from strawberry.utils.str_converters import to_camel_case
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MaybeNullValidationRule(ValidationRule):
|
|
18
|
+
"""Validates that Maybe[T] fields do not receive explicit null values.
|
|
19
|
+
|
|
20
|
+
This rule ensures that:
|
|
21
|
+
- Maybe[T] fields can only be omitted or have non-null values
|
|
22
|
+
- Maybe[T | None] fields can be omitted, null, or have non-null values
|
|
23
|
+
|
|
24
|
+
This provides clear semantics where Maybe[T] means "either present with value or absent"
|
|
25
|
+
and Maybe[T | None] means "present with value, present but null, or absent".
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, validation_context: ValidationContext) -> None:
|
|
29
|
+
super().__init__(validation_context)
|
|
30
|
+
|
|
31
|
+
def enter_argument(self, node: ArgumentNode, *_args: Any) -> None:
|
|
32
|
+
# Check if this is a null value
|
|
33
|
+
if node.value.kind != "null_value":
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
# Get the argument definition from the schema
|
|
37
|
+
argument_def = self.context.get_argument()
|
|
38
|
+
if not argument_def:
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
# Check if this argument corresponds to a Maybe[T] (not Maybe[T | None])
|
|
42
|
+
# The argument type extensions should contain the Strawberry type info
|
|
43
|
+
strawberry_arg_info = argument_def.extensions.get("strawberry-definition")
|
|
44
|
+
if not strawberry_arg_info:
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
# Get the Strawberry type from the argument info
|
|
48
|
+
field_type = getattr(strawberry_arg_info, "type", None)
|
|
49
|
+
if not field_type:
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
if isinstance(field_type, StrawberryMaybe) and not isinstance(
|
|
53
|
+
field_type.of_type, StrawberryOptional
|
|
54
|
+
):
|
|
55
|
+
# This is Maybe[T] - should not accept null values
|
|
56
|
+
type_name = self._get_type_name(field_type.of_type)
|
|
57
|
+
|
|
58
|
+
self.report_error(
|
|
59
|
+
GraphQLError(
|
|
60
|
+
f"Expected value of type '{type_name}', found null. "
|
|
61
|
+
f"Argument '{node.name.value}' of type 'Maybe[{type_name}]' cannot be explicitly set to null. "
|
|
62
|
+
f"Use 'Maybe[{type_name} | None]' if you need to allow null values.",
|
|
63
|
+
nodes=[node],
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def enter_object_value(self, node: ObjectValueNode, *_args: Any) -> None:
|
|
68
|
+
# Get the input type for this object
|
|
69
|
+
input_type = get_named_type(self.context.get_input_type())
|
|
70
|
+
if not input_type:
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
# Get the Strawberry type definition from extensions
|
|
74
|
+
strawberry_type = input_type.extensions.get("strawberry-definition")
|
|
75
|
+
if not strawberry_type:
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
# Check each field in the object for null Maybe[T] violations
|
|
79
|
+
self.validate_maybe_fields(node, input_type, strawberry_type)
|
|
80
|
+
|
|
81
|
+
def validate_maybe_fields(
|
|
82
|
+
self, node: ObjectValueNode, input_type: GraphQLNamedType, strawberry_type: Any
|
|
83
|
+
) -> None:
|
|
84
|
+
# Create a map of field names to field nodes for easy lookup
|
|
85
|
+
field_node_map = {field.name.value: field for field in node.fields}
|
|
86
|
+
|
|
87
|
+
# Check each field in the Strawberry type definition
|
|
88
|
+
if not hasattr(strawberry_type, "fields"):
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
for field_def in strawberry_type.fields:
|
|
92
|
+
# Resolve the actual GraphQL field name using the same logic as NameConverter
|
|
93
|
+
if field_def.graphql_name is not None:
|
|
94
|
+
field_name = field_def.graphql_name
|
|
95
|
+
else:
|
|
96
|
+
# Apply auto_camel_case conversion if enabled (default behavior)
|
|
97
|
+
field_name = to_camel_case(field_def.python_name)
|
|
98
|
+
|
|
99
|
+
# Check if this field is present in the input and has a null value
|
|
100
|
+
if field_name in field_node_map:
|
|
101
|
+
field_node = field_node_map[field_name]
|
|
102
|
+
|
|
103
|
+
# Check if this field has a null value
|
|
104
|
+
if field_node.value.kind == "null_value":
|
|
105
|
+
# Check if this is a Maybe[T] (not Maybe[T | None])
|
|
106
|
+
field_type = field_def.type
|
|
107
|
+
if isinstance(field_type, StrawberryMaybe) and not isinstance(
|
|
108
|
+
field_type.of_type, StrawberryOptional
|
|
109
|
+
):
|
|
110
|
+
# This is Maybe[T] - should not accept null values
|
|
111
|
+
type_name = self._get_type_name(field_type.of_type)
|
|
112
|
+
self.report_error(
|
|
113
|
+
GraphQLError(
|
|
114
|
+
f"Expected value of type '{type_name}', found null. "
|
|
115
|
+
f"Field '{field_name}' of type 'Maybe[{type_name}]' cannot be explicitly set to null. "
|
|
116
|
+
f"Use 'Maybe[{type_name} | None]' if you need to allow null values.",
|
|
117
|
+
nodes=[field_node],
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
def _get_type_name(self, type_: Any) -> str:
|
|
122
|
+
"""Get a readable type name for error messages."""
|
|
123
|
+
if hasattr(type_, "__name__"):
|
|
124
|
+
return type_.__name__
|
|
125
|
+
# Handle Strawberry types that don't have __name__
|
|
126
|
+
if hasattr(type_, "of_type") and hasattr(type_.of_type, "__name__"):
|
|
127
|
+
# For StrawberryList, StrawberryOptional, etc.
|
|
128
|
+
return (
|
|
129
|
+
f"list[{type_.of_type.__name__}]"
|
|
130
|
+
if "List" in str(type_.__class__)
|
|
131
|
+
else type_.of_type.__name__
|
|
132
|
+
)
|
|
133
|
+
return str(type_)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
__all__ = ["MaybeNullValidationRule"]
|
|
@@ -34,7 +34,6 @@ from strawberry.types import ExecutionResult
|
|
|
34
34
|
from strawberry.types.execution import PreExecutionError
|
|
35
35
|
from strawberry.types.graphql import OperationType
|
|
36
36
|
from strawberry.types.unset import UnsetType
|
|
37
|
-
from strawberry.utils.debug import pretty_print_graphql_operation
|
|
38
37
|
from strawberry.utils.operation import get_operation_type
|
|
39
38
|
|
|
40
39
|
if TYPE_CHECKING:
|
|
@@ -55,7 +54,6 @@ class BaseGraphQLTransportWSHandler(Generic[Context, RootValue]):
|
|
|
55
54
|
context: Context,
|
|
56
55
|
root_value: Optional[RootValue],
|
|
57
56
|
schema: BaseSchema,
|
|
58
|
-
debug: bool,
|
|
59
57
|
connection_init_wait_timeout: timedelta,
|
|
60
58
|
) -> None:
|
|
61
59
|
self.view = view
|
|
@@ -63,7 +61,6 @@ class BaseGraphQLTransportWSHandler(Generic[Context, RootValue]):
|
|
|
63
61
|
self.context = context
|
|
64
62
|
self.root_value = root_value
|
|
65
63
|
self.schema = schema
|
|
66
|
-
self.debug = debug
|
|
67
64
|
self.connection_init_wait_timeout = connection_init_wait_timeout
|
|
68
65
|
self.connection_init_timeout_task: Optional[asyncio.Task] = None
|
|
69
66
|
self.connection_init_received = False
|
|
@@ -237,13 +234,6 @@ class BaseGraphQLTransportWSHandler(Generic[Context, RootValue]):
|
|
|
237
234
|
await self.websocket.close(code=4409, reason=reason)
|
|
238
235
|
return
|
|
239
236
|
|
|
240
|
-
if self.debug: # pragma: no cover
|
|
241
|
-
pretty_print_graphql_operation(
|
|
242
|
-
message["payload"].get("operationName"),
|
|
243
|
-
message["payload"]["query"],
|
|
244
|
-
message["payload"].get("variables"),
|
|
245
|
-
)
|
|
246
|
-
|
|
247
237
|
operation = Operation(
|
|
248
238
|
self,
|
|
249
239
|
message["id"],
|
|
@@ -27,7 +27,6 @@ from strawberry.subscriptions.protocols.graphql_ws.types import (
|
|
|
27
27
|
)
|
|
28
28
|
from strawberry.types.execution import ExecutionResult, PreExecutionError
|
|
29
29
|
from strawberry.types.unset import UnsetType
|
|
30
|
-
from strawberry.utils.debug import pretty_print_graphql_operation
|
|
31
30
|
|
|
32
31
|
if TYPE_CHECKING:
|
|
33
32
|
from collections.abc import AsyncGenerator
|
|
@@ -44,7 +43,6 @@ class BaseGraphQLWSHandler(Generic[Context, RootValue]):
|
|
|
44
43
|
context: Context,
|
|
45
44
|
root_value: Optional[RootValue],
|
|
46
45
|
schema: BaseSchema,
|
|
47
|
-
debug: bool,
|
|
48
46
|
keep_alive: bool,
|
|
49
47
|
keep_alive_interval: Optional[float],
|
|
50
48
|
) -> None:
|
|
@@ -53,7 +51,6 @@ class BaseGraphQLWSHandler(Generic[Context, RootValue]):
|
|
|
53
51
|
self.context = context
|
|
54
52
|
self.root_value = root_value
|
|
55
53
|
self.schema = schema
|
|
56
|
-
self.debug = debug
|
|
57
54
|
self.keep_alive = keep_alive
|
|
58
55
|
self.keep_alive_interval = keep_alive_interval
|
|
59
56
|
self.keep_alive_task: Optional[asyncio.Task] = None
|
|
@@ -139,9 +136,6 @@ class BaseGraphQLWSHandler(Generic[Context, RootValue]):
|
|
|
139
136
|
operation_name = payload.get("operationName")
|
|
140
137
|
variables = payload.get("variables")
|
|
141
138
|
|
|
142
|
-
if self.debug:
|
|
143
|
-
pretty_print_graphql_operation(operation_name, query, variables)
|
|
144
|
-
|
|
145
139
|
result_handler = self.handle_async_results(
|
|
146
140
|
operation_id, query, operation_name, variables
|
|
147
141
|
)
|
strawberry/types/arguments.py
CHANGED
|
@@ -191,10 +191,24 @@ def convert_argument(
|
|
|
191
191
|
from strawberry.relay.types import GlobalID
|
|
192
192
|
|
|
193
193
|
# TODO: move this somewhere else and make it first class
|
|
194
|
-
|
|
194
|
+
# Handle StrawberryMaybe first, since it extends StrawberryOptional
|
|
195
|
+
if isinstance(type_, StrawberryMaybe):
|
|
196
|
+
# Check if this is Maybe[T | None] (has StrawberryOptional as of_type)
|
|
197
|
+
if isinstance(type_.of_type, StrawberryOptional):
|
|
198
|
+
# This is Maybe[T | None] - allows null values
|
|
199
|
+
res = convert_argument(value, type_.of_type, scalar_registry, config)
|
|
200
|
+
|
|
201
|
+
return Some(res)
|
|
202
|
+
|
|
203
|
+
# This is Maybe[T] - validation for null values is handled by MaybeNullValidationRule
|
|
204
|
+
# Convert the value and wrap in Some()
|
|
195
205
|
res = convert_argument(value, type_.of_type, scalar_registry, config)
|
|
196
206
|
|
|
197
|
-
return Some(res)
|
|
207
|
+
return Some(res)
|
|
208
|
+
|
|
209
|
+
# Handle regular StrawberryOptional (not Maybe)
|
|
210
|
+
if isinstance(type_, StrawberryOptional):
|
|
211
|
+
return convert_argument(value, type_.of_type, scalar_registry, config)
|
|
198
212
|
|
|
199
213
|
if value is None:
|
|
200
214
|
return None
|
strawberry/types/maybe.py
CHANGED
{strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.281.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: strawberry-graphql
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.281.0
|
|
4
4
|
Summary: A library for creating GraphQL APIs
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: graphql,api,rest,starlette,async
|
|
@@ -37,6 +37,7 @@ Requires-Dist: channels (>=3.0.5) ; extra == "channels"
|
|
|
37
37
|
Requires-Dist: fastapi (>=0.65.2) ; extra == "fastapi"
|
|
38
38
|
Requires-Dist: flask (>=1.1) ; extra == "flask"
|
|
39
39
|
Requires-Dist: graphql-core (>=3.2.0,<3.4.0)
|
|
40
|
+
Requires-Dist: lia-web (>=0.2.1)
|
|
40
41
|
Requires-Dist: libcst ; extra == "cli"
|
|
41
42
|
Requires-Dist: libcst ; extra == "debug"
|
|
42
43
|
Requires-Dist: libcst ; extra == "debug-server"
|