From 9dcbfc89c1be34ed668a1fa7c966cd34c114d47a Mon Sep 17 00:00:00 2001 From: Cadu Date: Thu, 10 Nov 2022 14:53:32 -0300 Subject: [PATCH] Changed InputObjectType's default builder-from-dict argument to be `Undefined` instead of `None` (or else we can't catch "null" inputs in InputObjectTypes, as both would coerce to `None`) --- graphene/types/inputobjecttype.py | 10 +++++++++- graphene/types/tests/test_type_map.py | 16 +++++++++++++++- graphene/validation/depth_limit.py | 6 +++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/graphene/types/inputobjecttype.py b/graphene/types/inputobjecttype.py index 5d278510..585dfe80 100644 --- a/graphene/types/inputobjecttype.py +++ b/graphene/types/inputobjecttype.py @@ -14,6 +14,14 @@ class InputObjectTypeOptions(BaseOptions): container = None # type: InputObjectTypeContainer +_INPUT_OBJECT_TYPE_DEFAULT_VALUE = None + + +def set_input_object_type_default_value(default_value): + global _INPUT_OBJECT_TYPE_DEFAULT_VALUE + _INPUT_OBJECT_TYPE_DEFAULT_VALUE = default_value + + class InputObjectTypeContainer(dict, BaseType): # type: ignore class Meta: abstract = True @@ -21,7 +29,7 @@ class InputObjectTypeContainer(dict, BaseType): # type: ignore def __init__(self, *args, **kwargs): dict.__init__(self, *args, **kwargs) for key in self._meta.fields: - setattr(self, key, self.get(key, None)) + setattr(self, key, self.get(key, _INPUT_OBJECT_TYPE_DEFAULT_VALUE)) def __init_subclass__(cls, *args, **kwargs): pass diff --git a/graphene/types/tests/test_type_map.py b/graphene/types/tests/test_type_map.py index 55b1706e..726c8a4d 100644 --- a/graphene/types/tests/test_type_map.py +++ b/graphene/types/tests/test_type_map.py @@ -16,7 +16,7 @@ from ..dynamic import Dynamic from ..enum import Enum from ..field import Field from ..inputfield import InputField -from ..inputobjecttype import InputObjectType +from ..inputobjecttype import InputObjectType, set_input_object_type_default_value from ..interface import Interface from ..objecttype import ObjectType from ..scalars import Int, String @@ -227,6 +227,20 @@ def test_inputobject(): assert foo_field.description == "Field description" +def test_inputobject_undefined(): + set_input_object_type_default_value(Undefined) + + class OtherObjectType(InputObjectType): + optional_field = String() + + type_map = create_type_map([OtherObjectType]) + assert "OtherObjectType" in type_map + graphql_type = type_map["OtherObjectType"] + + container = graphql_type.out_type({}) + assert container.optional_field is Undefined + + def test_objecttype_camelcase(): class MyObjectType(ObjectType): """Description""" diff --git a/graphene/validation/depth_limit.py b/graphene/validation/depth_limit.py index b4599e66..e0f28663 100644 --- a/graphene/validation/depth_limit.py +++ b/graphene/validation/depth_limit.py @@ -30,7 +30,7 @@ try: except ImportError: # backwards compatibility for v3.6 from typing import Pattern -from typing import Callable, Dict, List, Optional, Union +from typing import Callable, Dict, List, Optional, Union, Tuple from graphql import GraphQLError from graphql.validation import ValidationContext, ValidationRule @@ -82,7 +82,7 @@ def depth_limit_validator( def get_fragments( - definitions: List[DefinitionNode], + definitions: Tuple[DefinitionNode, ...], ) -> Dict[str, FragmentDefinitionNode]: fragments = {} for definition in definitions: @@ -94,7 +94,7 @@ def get_fragments( # This will actually get both queries and mutations. # We can basically treat those the same def get_queries_and_mutations( - definitions: List[DefinitionNode], + definitions: Tuple[DefinitionNode, ...], ) -> Dict[str, OperationDefinitionNode]: operations = {}