mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-26 19:43:56 +03:00
Added InputObjectType and InputField
This commit is contained in:
parent
8cf5b1d9ab
commit
70a9de63f9
17
graphene/new_types/inputfield.py
Normal file
17
graphene/new_types/inputfield.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from ..utils.orderedtype import OrderedType
|
||||||
|
from .structures import NonNull
|
||||||
|
|
||||||
|
|
||||||
|
class InputField(OrderedType):
|
||||||
|
|
||||||
|
def __init__(self, type, name=None, default_value=None,
|
||||||
|
deprecation_reason=None, description=None,
|
||||||
|
required=False, _creation_counter=None, **extra_args):
|
||||||
|
super(InputField, self).__init__(_creation_counter=_creation_counter)
|
||||||
|
self.name = name
|
||||||
|
if required:
|
||||||
|
type = NonNull(type)
|
||||||
|
self.type = type
|
||||||
|
self.deprecation_reason = deprecation_reason
|
||||||
|
self.default_value = default_value
|
||||||
|
self.description = description
|
36
graphene/new_types/inputobjecttype.py
Normal file
36
graphene/new_types/inputobjecttype.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import six
|
||||||
|
|
||||||
|
from ..utils.is_base_type import is_base_type
|
||||||
|
from .options import Options
|
||||||
|
|
||||||
|
from .abstracttype import AbstractTypeMeta
|
||||||
|
from .utils import get_fields_in_type, yank_fields_from_attrs, merge_fields_in_attrs
|
||||||
|
|
||||||
|
|
||||||
|
class InputObjectTypeMeta(AbstractTypeMeta):
|
||||||
|
|
||||||
|
def __new__(cls, name, bases, attrs):
|
||||||
|
# Also ensure initialization is only performed for subclasses of
|
||||||
|
# InputObjectType
|
||||||
|
if not is_base_type(bases, InputObjectTypeMeta):
|
||||||
|
return type.__new__(cls, name, bases, attrs)
|
||||||
|
|
||||||
|
options = Options(
|
||||||
|
attrs.pop('Meta', None),
|
||||||
|
name=name,
|
||||||
|
description=attrs.get('__doc__'),
|
||||||
|
)
|
||||||
|
|
||||||
|
attrs = merge_fields_in_attrs(bases, attrs)
|
||||||
|
options.fields = get_fields_in_type(InputObjectType, attrs)
|
||||||
|
yank_fields_from_attrs(attrs, options.fields)
|
||||||
|
|
||||||
|
return type.__new__(cls, name, bases, dict(attrs, _meta=options))
|
||||||
|
|
||||||
|
def __str__(cls):
|
||||||
|
return cls._meta.name
|
||||||
|
|
||||||
|
|
||||||
|
class InputObjectType(six.with_metaclass(InputObjectTypeMeta)):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
raise Exception("An InputObjectType cannot be intitialized")
|
|
@ -19,7 +19,6 @@ class InterfaceMeta(AbstractTypeMeta):
|
||||||
attrs.pop('Meta', None),
|
attrs.pop('Meta', None),
|
||||||
name=name,
|
name=name,
|
||||||
description=attrs.get('__doc__'),
|
description=attrs.get('__doc__'),
|
||||||
interfaces=(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
attrs = merge_fields_in_attrs(bases, attrs)
|
attrs = merge_fields_in_attrs(bases, attrs)
|
||||||
|
|
83
graphene/new_types/tests/test_inputobjecttype.py
Normal file
83
graphene/new_types/tests/test_inputobjecttype.py
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..field import Field
|
||||||
|
from ..inputfield import InputField
|
||||||
|
from ..inputobjecttype import InputObjectType
|
||||||
|
from ..unmountedtype import UnmountedType
|
||||||
|
from ..abstracttype import AbstractType
|
||||||
|
|
||||||
|
|
||||||
|
class MyType(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MyScalar(UnmountedType):
|
||||||
|
def get_type(self):
|
||||||
|
return MyType
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_inputobjecttype():
|
||||||
|
class MyInputObjectType(InputObjectType):
|
||||||
|
'''Documentation'''
|
||||||
|
|
||||||
|
assert MyInputObjectType._meta.name == "MyInputObjectType"
|
||||||
|
assert MyInputObjectType._meta.description == "Documentation"
|
||||||
|
assert MyInputObjectType._meta.fields == {}
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_inputobjecttype_with_meta():
|
||||||
|
class MyInputObjectType(InputObjectType):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
name = 'MyOtherInputObjectType'
|
||||||
|
description = 'Documentation'
|
||||||
|
|
||||||
|
assert MyInputObjectType._meta.name == "MyOtherInputObjectType"
|
||||||
|
assert MyInputObjectType._meta.description == "Documentation"
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_inputobjecttype_with_fields():
|
||||||
|
class MyInputObjectType(InputObjectType):
|
||||||
|
field = Field(MyType)
|
||||||
|
|
||||||
|
assert 'field' in MyInputObjectType._meta.fields
|
||||||
|
|
||||||
|
|
||||||
|
def test_ordered_fields_in_inputobjecttype():
|
||||||
|
class MyInputObjectType(InputObjectType):
|
||||||
|
b = InputField(MyType)
|
||||||
|
a = InputField(MyType)
|
||||||
|
field = MyScalar()
|
||||||
|
asa = InputField(MyType)
|
||||||
|
|
||||||
|
assert list(MyInputObjectType._meta.fields.keys()) == ['b', 'a', 'field', 'asa']
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_inputobjecttype_unmountedtype():
|
||||||
|
class MyInputObjectType(InputObjectType):
|
||||||
|
field = MyScalar(MyType)
|
||||||
|
|
||||||
|
assert 'field' in MyInputObjectType._meta.fields
|
||||||
|
assert isinstance(MyInputObjectType._meta.fields['field'], InputField)
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_inputobjecttype_inherit_abstracttype():
|
||||||
|
class MyAbstractType(AbstractType):
|
||||||
|
field1 = MyScalar(MyType)
|
||||||
|
|
||||||
|
class MyInputObjectType(InputObjectType, MyAbstractType):
|
||||||
|
field2 = MyScalar(MyType)
|
||||||
|
|
||||||
|
assert MyInputObjectType._meta.fields.keys() == ['field1', 'field2']
|
||||||
|
assert [type(x) for x in MyInputObjectType._meta.fields.values()] == [InputField, InputField]
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_inputobjecttype_inherit_abstracttype_reversed():
|
||||||
|
class MyAbstractType(AbstractType):
|
||||||
|
field1 = MyScalar(MyType)
|
||||||
|
|
||||||
|
class MyInputObjectType(MyAbstractType, InputObjectType):
|
||||||
|
field2 = MyScalar(MyType)
|
||||||
|
|
||||||
|
assert MyInputObjectType._meta.fields.keys() == ['field1', 'field2']
|
||||||
|
assert [type(x) for x in MyInputObjectType._meta.fields.values()] == [InputField, InputField]
|
|
@ -37,16 +37,17 @@ class UnmountedType(OrderedType):
|
||||||
**self.kwargs
|
**self.kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
# def as_inputfield(self):
|
def as_inputfield(self):
|
||||||
# '''
|
'''
|
||||||
# Mount the UnmountedType as InputField
|
Mount the UnmountedType as InputField
|
||||||
# '''
|
'''
|
||||||
# return InputField(
|
from .inputfield import InputField
|
||||||
# self.get_type(),
|
return InputField(
|
||||||
# *self.args,
|
self.get_type(),
|
||||||
# _creation_counter=self.creation_counter,
|
*self.args,
|
||||||
# **self.kwargs
|
_creation_counter=self.creation_counter,
|
||||||
# )
|
**self.kwargs
|
||||||
|
)
|
||||||
|
|
||||||
# def as_argument(self):
|
# def as_argument(self):
|
||||||
# '''
|
# '''
|
||||||
|
|
|
@ -2,6 +2,7 @@ from collections import OrderedDict
|
||||||
|
|
||||||
from .unmountedtype import UnmountedType
|
from .unmountedtype import UnmountedType
|
||||||
from .field import Field
|
from .field import Field
|
||||||
|
from .inputfield import InputField
|
||||||
|
|
||||||
|
|
||||||
def merge_fields_in_attrs(bases, attrs):
|
def merge_fields_in_attrs(bases, attrs):
|
||||||
|
@ -28,14 +29,15 @@ def unmounted_field_in_type(attname, unmounted_field, type):
|
||||||
from ..new_types.objecttype import ObjectType
|
from ..new_types.objecttype import ObjectType
|
||||||
from ..new_types.interface import Interface
|
from ..new_types.interface import Interface
|
||||||
from ..new_types.abstracttype import AbstractType
|
from ..new_types.abstracttype import AbstractType
|
||||||
|
from ..new_types.inputobjecttype import InputObjectType
|
||||||
|
|
||||||
if issubclass(type, (ObjectType, Interface)):
|
if issubclass(type, (ObjectType, Interface)):
|
||||||
return unmounted_field.as_field()
|
return unmounted_field.as_field()
|
||||||
|
|
||||||
elif issubclass(type, (AbstractType)):
|
elif issubclass(type, (AbstractType)):
|
||||||
return unmounted_field
|
return unmounted_field
|
||||||
# elif issubclass(type, (InputObjectType)):
|
elif issubclass(type, (InputObjectType)):
|
||||||
# return unmounted_field.as_inputfield()
|
return unmounted_field.as_inputfield()
|
||||||
|
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Unmounted field "{}" cannot be mounted in {}.{}.'.format(
|
'Unmounted field "{}" cannot be mounted in {}.{}.'.format(
|
||||||
|
@ -47,7 +49,7 @@ def unmounted_field_in_type(attname, unmounted_field, type):
|
||||||
def get_fields_in_type(in_type, attrs):
|
def get_fields_in_type(in_type, attrs):
|
||||||
fields_with_names = []
|
fields_with_names = []
|
||||||
for attname, value in list(attrs.items()):
|
for attname, value in list(attrs.items()):
|
||||||
if isinstance(value, (Field)): # , InputField
|
if isinstance(value, (Field, InputField)):
|
||||||
fields_with_names.append(
|
fields_with_names.append(
|
||||||
(attname, value)
|
(attname, value)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user