From a2904fe33b0dc8c3c3804fa533e1324eaf60e6cc Mon Sep 17 00:00:00 2001 From: Matt Gilson Date: Wed, 23 Aug 2023 16:11:53 -0400 Subject: [PATCH] Handle UNSET values in the strawberry schema. The codegen currently chokes on `strawberry.UNSET` default values. This PR updates the codegen to stop raising an exception and instead pass a `GraphQLNullValue(value=UNSET)` to the plugins. The default python plugin writes a `None` as the default value because there really isn't a well understood concept of UNSET in the python eco system. User defined plugins have all the information that they need to handle this differently if they choose to do so. --- strawberry/codegen/plugins/python.py | 3 +++ strawberry/codegen/query_codegen.py | 6 ++++-- strawberry/codegen/types.py | 3 ++- tests/codegen/conftest.py | 1 + tests/codegen/snapshots/python/variables.py | 1 + tests/codegen/snapshots/typescript/variables.ts | 1 + 6 files changed, 12 insertions(+), 3 deletions(-) diff --git a/strawberry/codegen/plugins/python.py b/strawberry/codegen/plugins/python.py index 3ad598b857..41b17d4543 100644 --- a/strawberry/codegen/plugins/python.py +++ b/strawberry/codegen/plugins/python.py @@ -10,6 +10,7 @@ GraphQLEnum, GraphQLEnumValue, GraphQLList, + GraphQLNullValue, GraphQLObjectType, GraphQLOptional, GraphQLScalar, @@ -141,6 +142,8 @@ def _print_argument_value(self, argval: GraphQLArgumentValue) -> str: "GraphQLEnumValue must have a type for python code gen. {argval}" ) return f"{argval.enum_type}.{argval.name}" + if isinstance(argval, GraphQLNullValue): + return "None" if not hasattr(argval, "value"): raise TypeError(f"Unrecognized values type: {argval}") return repr(argval.value) diff --git a/strawberry/codegen/query_codegen.py b/strawberry/codegen/query_codegen.py index 7b9df2b756..a3628324d2 100644 --- a/strawberry/codegen/query_codegen.py +++ b/strawberry/codegen/query_codegen.py @@ -52,6 +52,7 @@ ) from strawberry.types.types import StrawberryObjectDefinition from strawberry.union import StrawberryUnion +from strawberry.unset import UNSET from strawberry.utils.str_converters import capitalize_first, to_camel_case from .exceptions import ( @@ -178,8 +179,9 @@ def _get_deps(t: GraphQLType) -> Iterable[GraphQLType]: def _py_to_graphql_value(obj: Any) -> GraphQLArgumentValue: """Convert a python object to a GraphQLArgumentValue.""" - if obj is None: - return GraphQLNullValue() + if obj is None or obj is UNSET: + return GraphQLNullValue(value=obj) + obj_type = type(obj) if obj_type in _TYPE_TO_GRAPHQL_TYPE: return _TYPE_TO_GRAPHQL_TYPE[obj_type](obj) diff --git a/strawberry/codegen/types.py b/strawberry/codegen/types.py index 37fbec7f66..ac58f5368b 100644 --- a/strawberry/codegen/types.py +++ b/strawberry/codegen/types.py @@ -6,6 +6,7 @@ if TYPE_CHECKING: from enum import EnumMeta from typing_extensions import Literal + from strawberry.unset import UnsetType @dataclass @@ -134,7 +135,7 @@ class GraphQLBoolValue: class GraphQLNullValue: """A class that represents a GraphQLNull value.""" - value: None = None + value: None | UnsetType = None @dataclass diff --git a/tests/codegen/conftest.py b/tests/codegen/conftest.py index 624f57016a..977d761fc9 100644 --- a/tests/codegen/conftest.py +++ b/tests/codegen/conftest.py @@ -60,6 +60,7 @@ class Image(Node): @strawberry.input class PersonInput: name: str + age: Optional[int] = strawberry.UNSET @strawberry.input diff --git a/tests/codegen/snapshots/python/variables.py b/tests/codegen/snapshots/python/variables.py index 0bf72745aa..a19d010717 100644 --- a/tests/codegen/snapshots/python/variables.py +++ b/tests/codegen/snapshots/python/variables.py @@ -5,6 +5,7 @@ class OperationNameResult: class PersonInput: name: str + age: Optional[int] = None class ExampleInput: id: str diff --git a/tests/codegen/snapshots/typescript/variables.ts b/tests/codegen/snapshots/typescript/variables.ts index cf1df65308..88a3d04d21 100644 --- a/tests/codegen/snapshots/typescript/variables.ts +++ b/tests/codegen/snapshots/typescript/variables.ts @@ -4,6 +4,7 @@ type OperationNameResult = { type PersonInput = { name: string + age: number | undefined } type ExampleInput = {