Handle complex input types

This commit is contained in:
Nathaniel Parrish 2017-11-07 09:06:36 -08:00
parent b5abccb1dc
commit 9c27db7ed5
2 changed files with 44 additions and 5 deletions

View File

@ -1,11 +1,14 @@
from collections import OrderedDict from collections import OrderedDict
from .base import BaseOptions, BaseType from .base import BaseOptions, BaseType
from .field import Field
from .inputfield import InputField from .inputfield import InputField
from .objecttype import ObjectType
from .scalars import Scalar
from .structures import List, NonNull
from .unmountedtype import UnmountedType from .unmountedtype import UnmountedType
from .utils import yank_fields_from_attrs from .utils import yank_fields_from_attrs
# For static type checking with Mypy # For static type checking with Mypy
MYPY = False MYPY = False
if MYPY: if MYPY:
@ -24,11 +27,29 @@ class InputObjectTypeContainer(dict, BaseType):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs) dict.__init__(self, *args, **kwargs)
for key in self._meta.fields.keys(): for key in self._meta.fields.keys():
setattr(self, key, self.get(key, None)) field = getattr(self, key, None)
if field is None or self.get(key, None) is None:
value = None
else:
value = InputObjectTypeContainer._get_typed_field_value(field, self[key])
setattr(self, key, value)
def __init_subclass__(cls, *args, **kwargs): def __init_subclass__(cls, *args, **kwargs):
pass pass
@staticmethod
def _get_typed_field_value(field_or_type, value):
if isinstance(field_or_type, NonNull):
return InputObjectTypeContainer._get_typed_field_value(field_or_type.of_type, value)
elif isinstance(field_or_type, List):
return [
InputObjectTypeContainer._get_typed_field_value(field_or_type.of_type, v)
for v in value
]
elif hasattr(field_or_type, '_meta') and hasattr(field_or_type._meta, 'container'):
return field_or_type._meta.container(value)
else:
return value
class InputObjectType(UnmountedType, BaseType): class InputObjectType(UnmountedType, BaseType):
''' '''

View File

@ -4,6 +4,7 @@ from graphql.type import (GraphQLArgument, GraphQLEnumType, GraphQLEnumValue,
GraphQLInputObjectType, GraphQLInterfaceType, GraphQLInputObjectType, GraphQLInterfaceType,
GraphQLObjectType, GraphQLString) GraphQLObjectType, GraphQLString)
from ..structures import List, NonNull
from ..dynamic import Dynamic from ..dynamic import Dynamic
from ..enum import Enum from ..enum import Enum
from ..field import Field from ..field import Field
@ -11,7 +12,7 @@ from ..inputfield import InputField
from ..inputobjecttype import InputObjectType from ..inputobjecttype import InputObjectType
from ..interface import Interface from ..interface import Interface
from ..objecttype import ObjectType from ..objecttype import ObjectType
from ..scalars import String from ..scalars import String, Int
from ..typemap import TypeMap from ..typemap import TypeMap
@ -119,10 +120,18 @@ def test_interface():
def test_inputobject(): def test_inputobject():
class OtherObjectType(InputObjectType):
thingy = NonNull(Int)
class MyInnerObjectType(InputObjectType):
some_field = String()
some_other_field = List(OtherObjectType)
class MyInputObjectType(InputObjectType): class MyInputObjectType(InputObjectType):
'''Description''' '''Description'''
foo_bar = String(description='Field description') foo_bar = String(description='Field description')
bar = String(name='gizmo') bar = String(name='gizmo')
baz = NonNull(MyInnerObjectType)
own = InputField(lambda: MyInputObjectType) own = InputField(lambda: MyInputObjectType)
def resolve_foo_bar(self, args, info): def resolve_foo_bar(self, args, info):
@ -136,14 +145,23 @@ def test_inputobject():
assert graphql_type.description == 'Description' assert graphql_type.description == 'Description'
# Container # Container
container = graphql_type.create_container({'bar': 'oh!'}) container = graphql_type.create_container({
'bar': 'oh!',
'baz': {
'some_other_field': [{'thingy': 1}, {'thingy': 2}]
}
})
assert isinstance(container, MyInputObjectType) assert isinstance(container, MyInputObjectType)
assert 'bar' in container assert 'bar' in container
assert container.bar == 'oh!' assert container.bar == 'oh!'
assert 'foo_bar' not in container assert 'foo_bar' not in container
assert container.foo_bar is None
assert container.baz.some_field is None
assert container.baz.some_other_field[0].thingy == 1
assert container.baz.some_other_field[1].thingy == 2
fields = graphql_type.fields fields = graphql_type.fields
assert list(fields.keys()) == ['fooBar', 'gizmo', 'own'] assert list(fields.keys()) == ['fooBar', 'gizmo', 'baz', 'own']
own_field = fields['own'] own_field = fields['own']
assert own_field.type == graphql_type assert own_field.type == graphql_type
foo_field = fields['fooBar'] foo_field = fields['fooBar']