mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 20:54:16 +03:00
Improved InputObjectType abstraction
This commit is contained in:
parent
a6346664a3
commit
8078937359
|
@ -4,8 +4,9 @@ from graphql_relay import mutation_with_client_mutation_id
|
||||||
|
|
||||||
from ..types.mutation import Mutation, MutationMeta
|
from ..types.mutation import Mutation, MutationMeta
|
||||||
from ..types.inputobjecttype import InputObjectType
|
from ..types.inputobjecttype import InputObjectType
|
||||||
from ..types.field import Field
|
from ..types.field import Field, InputField
|
||||||
|
from ..utils.get_fields import get_fields
|
||||||
|
from ..utils.copy_fields import copy_fields
|
||||||
from ..utils.props import props
|
from ..utils.props import props
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ class ClientIDMutationMeta(MutationMeta):
|
||||||
|
|
||||||
cls.mutate_and_get_payload = attrs.pop('mutate_and_get_payload', None)
|
cls.mutate_and_get_payload = attrs.pop('mutate_and_get_payload', None)
|
||||||
|
|
||||||
input_local_fields = {f.name: f for f in InputObjectType._extract_local_fields(input_fields)}
|
input_local_fields = copy_fields(InputField, get_fields(InputObjectType, input_fields, ()))
|
||||||
local_fields = cls._extract_local_fields(attrs)
|
local_fields = cls._extract_local_fields(attrs)
|
||||||
assert cls.mutate_and_get_payload, "{}.mutate_and_get_payload method is required in a ClientIDMutation ObjectType.".format(cls.__name__)
|
assert cls.mutate_and_get_payload, "{}.mutate_and_get_payload method is required in a ClientIDMutation ObjectType.".format(cls.__name__)
|
||||||
field = mutation_with_client_mutation_id(
|
field = mutation_with_client_mutation_id(
|
||||||
|
|
|
@ -129,9 +129,7 @@ class Field(AbstractField, GraphQLField, OrderedType):
|
||||||
# If is a GraphQLField
|
# If is a GraphQLField
|
||||||
type = type or field.type
|
type = type or field.type
|
||||||
resolver = resolver or field.resolver
|
resolver = resolver or field.resolver
|
||||||
source = None
|
|
||||||
name = field.name
|
name = field.name
|
||||||
required = None
|
|
||||||
_creation_counter = None
|
_creation_counter = None
|
||||||
attname = attname or name
|
attname = attname or name
|
||||||
parent = parent
|
parent = parent
|
||||||
|
@ -187,22 +185,19 @@ class InputField(AbstractField, GraphQLInputObjectField, OrderedType):
|
||||||
return self.copy_and_extend(self)
|
return self.copy_and_extend(self)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def copy_and_extend(cls, field, type=None, default_value=None, description=None, name=None, required=False, _creation_counter=False):
|
def copy_and_extend(cls, field, type=None, default_value=None, description=None, name=None, required=False, parent=None, attname=None, _creation_counter=False):
|
||||||
if isinstance(field, Field):
|
if isinstance(field, Field):
|
||||||
type = type or field._type
|
type = type or field._type
|
||||||
name = name or field._name
|
name = name or field._name
|
||||||
required = required or field.required
|
required = required or field.required
|
||||||
_creation_counter = field.creation_counter if _creation_counter is False else None
|
_creation_counter = field.creation_counter if _creation_counter is False else None
|
||||||
attname = field.attname
|
attname = attname or field.attname
|
||||||
parent = field.parent
|
parent = parent or field.parent
|
||||||
else:
|
else:
|
||||||
# If is a GraphQLField
|
# If is a GraphQLField
|
||||||
type = type or field.type
|
type = type or field.type
|
||||||
name = field.name
|
name = field.name
|
||||||
required = None
|
|
||||||
_creation_counter = None
|
_creation_counter = None
|
||||||
attname = None
|
|
||||||
parent = None
|
|
||||||
|
|
||||||
new_field = cls(
|
new_field = cls(
|
||||||
type=type,
|
type=type,
|
||||||
|
|
|
@ -3,39 +3,58 @@ import six
|
||||||
from graphql import GraphQLInputObjectType
|
from graphql import GraphQLInputObjectType
|
||||||
|
|
||||||
from .definitions import FieldsMeta, ClassTypeMeta, GrapheneGraphQLType
|
from .definitions import FieldsMeta, ClassTypeMeta, GrapheneGraphQLType
|
||||||
|
from .interface import attrs_without_fields
|
||||||
from .unmountedtype import UnmountedType
|
from .unmountedtype import UnmountedType
|
||||||
|
from .options import Options
|
||||||
|
from ..utils.is_base_type import is_base_type
|
||||||
|
from ..utils.get_fields import get_fields
|
||||||
|
from ..utils.copy_fields import copy_fields
|
||||||
|
from .field import InputField
|
||||||
|
|
||||||
|
|
||||||
class GrapheneInputObjectType(GrapheneGraphQLType, GraphQLInputObjectType):
|
class GrapheneInputObjectType(GrapheneGraphQLType, GraphQLInputObjectType):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class InputObjectTypeMeta(FieldsMeta, ClassTypeMeta):
|
class InputObjectTypeMeta(type):
|
||||||
|
|
||||||
def get_options(cls, meta):
|
def __new__(cls, name, bases, attrs):
|
||||||
return cls.options_class(
|
super_new = super(InputObjectTypeMeta, cls).__new__
|
||||||
meta,
|
|
||||||
|
# Also ensure initialization is only performed for subclasses of Model
|
||||||
|
# (excluding Model class itself).
|
||||||
|
if not is_base_type(bases, InputObjectTypeMeta):
|
||||||
|
return super_new(cls, name, bases, attrs)
|
||||||
|
|
||||||
|
options = Options(
|
||||||
|
attrs.pop('Meta', None),
|
||||||
name=None,
|
name=None,
|
||||||
description=None,
|
description=None,
|
||||||
graphql_type=None,
|
graphql_type=None,
|
||||||
abstract=False
|
abstract=False
|
||||||
)
|
)
|
||||||
|
|
||||||
def construct(cls, bases, attrs):
|
fields = get_fields(InputObjectType, attrs, bases)
|
||||||
if not cls._meta.abstract:
|
attrs = attrs_without_fields(attrs, fields)
|
||||||
local_fields = cls._extract_local_fields(attrs)
|
cls = super_new(cls, name, bases, dict(attrs, _meta=options))
|
||||||
if not cls._meta.graphql_type:
|
|
||||||
cls._meta.graphql_type = GrapheneInputObjectType(
|
if not options.graphql_type:
|
||||||
graphene_type=cls,
|
fields = copy_fields(InputField, fields, parent=cls)
|
||||||
name=cls._meta.name or cls.__name__,
|
options.graphql_type = GrapheneInputObjectType(
|
||||||
description=cls._meta.description or cls.__doc__,
|
graphene_type=cls,
|
||||||
fields=cls._fields(bases, attrs, local_fields),
|
name=options.name or cls.__name__,
|
||||||
)
|
description=options.description or cls.__doc__,
|
||||||
else:
|
fields=fields,
|
||||||
assert not local_fields, "Can't mount Fields in an InputObjectType with a defined graphql_type"
|
)
|
||||||
return super(InputObjectTypeMeta, cls).construct(bases, attrs)
|
else:
|
||||||
|
assert not fields, "Can't mount InputFields in an InputObjectType with a defined graphql_type"
|
||||||
|
fields = copy_fields(options.graphql_type.get_fields(), parent=cls)
|
||||||
|
|
||||||
|
for name, field in fields.items():
|
||||||
|
setattr(cls, field.attname or name, field)
|
||||||
|
|
||||||
|
return cls
|
||||||
|
|
||||||
|
|
||||||
class InputObjectType(six.with_metaclass(InputObjectTypeMeta, UnmountedType)):
|
class InputObjectType(six.with_metaclass(InputObjectTypeMeta, UnmountedType)):
|
||||||
class Meta:
|
pass
|
||||||
abstract = True
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ from .options import Options
|
||||||
from ..utils.is_base_type import is_base_type
|
from ..utils.is_base_type import is_base_type
|
||||||
from ..utils.get_fields import get_fields
|
from ..utils.get_fields import get_fields
|
||||||
from ..utils.copy_fields import copy_fields
|
from ..utils.copy_fields import copy_fields
|
||||||
|
from .field import Field
|
||||||
|
|
||||||
|
|
||||||
class GrapheneInterfaceType(GrapheneGraphQLType, GraphQLInterfaceType):
|
class GrapheneInterfaceType(GrapheneGraphQLType, GraphQLInterfaceType):
|
||||||
|
@ -35,7 +36,7 @@ class InterfaceTypeMeta(type):
|
||||||
cls = super_new(cls, name, bases, dict(attrs, _meta=options))
|
cls = super_new(cls, name, bases, dict(attrs, _meta=options))
|
||||||
|
|
||||||
if not options.graphql_type:
|
if not options.graphql_type:
|
||||||
fields = copy_fields(fields, parent=cls)
|
fields = copy_fields(Field, fields, parent=cls)
|
||||||
options.graphql_type = GrapheneInterfaceType(
|
options.graphql_type = GrapheneInterfaceType(
|
||||||
graphene_type=cls,
|
graphene_type=cls,
|
||||||
name=options.name or cls.__name__,
|
name=options.name or cls.__name__,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from ..types.field import Field
|
from ..types.field import Field, InputField
|
||||||
|
|
||||||
|
|
||||||
def copy_fields(fields, **extra):
|
def copy_fields(like, fields, **extra):
|
||||||
_fields = []
|
_fields = []
|
||||||
for attname, field in fields.items():
|
for attname, field in fields.items():
|
||||||
field = Field.copy_and_extend(field, attname=attname, **extra)
|
field = like.copy_and_extend(field, attname=attname, **extra)
|
||||||
_fields.append(field)
|
_fields.append(field)
|
||||||
|
|
||||||
return OrderedDict((f.name, f) for f in _fields)
|
return OrderedDict((f.name, f) for f in _fields)
|
||||||
|
|
|
@ -8,7 +8,7 @@ def is_graphene_type(_type):
|
||||||
from ..types.scalars import Scalar
|
from ..types.scalars import Scalar
|
||||||
from ..types.enum import Enum
|
from ..types.enum import Enum
|
||||||
|
|
||||||
if _type in [Interface]:
|
if _type in [Interface, InputObjectType]:
|
||||||
return False
|
return False
|
||||||
return inspect.isclass(_type) and issubclass(_type, (
|
return inspect.isclass(_type) and issubclass(_type, (
|
||||||
Interface,
|
Interface,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user