diff --git a/graphene-django/graphene_django/types.py b/graphene-django/graphene_django/types.py index 62f279fb..55d4f1b5 100644 --- a/graphene-django/graphene_django/types.py +++ b/graphene-django/graphene_django/types.py @@ -3,7 +3,7 @@ from functools import partial import six from graphene import Field, Interface -from graphene.types.objecttype import ObjectType, ObjectTypeMeta, attrs_without_fields, GrapheneObjectType, get_interfaces +from graphene.types.objecttype import ObjectType, ObjectTypeMeta, attrs_without_fields, get_interfaces from graphene.relay import Node from graphene.relay.node import NodeMeta from .converter import convert_django_field_with_choices @@ -15,6 +15,8 @@ from graphene.utils.copy_fields import copy_fields from graphene.utils.get_graphql_type import get_graphql_type from graphene.utils.get_fields import get_fields from graphene.utils.as_field import as_field +from graphene.generators import generate_objecttype +from graphene.generators.definitions import GrapheneObjectType class DjangoObjectTypeMeta(ObjectTypeMeta): @@ -81,14 +83,16 @@ class DjangoObjectTypeMeta(ObjectTypeMeta): cls = super_new(cls, name, bases, dict(attrs, _meta=options)) base_interfaces = tuple(b for b in bases if issubclass(b, Interface)) + options.get_fields = partial(cls._construct_fields, fields, options) + options.get_interfaces = tuple(get_interfaces(interfaces + base_interfaces)) + options.graphql_type = GrapheneObjectType( graphene_type=cls, name=options.name or cls.__name__, description=options.description or cls.__doc__, - fields=partial(cls._construct_fields, fields, options), - interfaces=tuple(get_interfaces(interfaces + base_interfaces)) + fields=options.get_fields, + interfaces=options.get_interfaces ) - options.get_fields = partial(cls._construct_fields, fields, options) if issubclass(cls, DjangoObjectType): options.registry.register(cls) diff --git a/graphene/generators/__init__.py b/graphene/generators/__init__.py new file mode 100644 index 00000000..f7f48ccc --- /dev/null +++ b/graphene/generators/__init__.py @@ -0,0 +1,22 @@ +from .definitions import GrapheneInterfaceType, GrapheneObjectType + + +def generate_interface(interface): + return GrapheneInterfaceType( + graphene_type=interface, + name=interface._meta.name or interface.__name__, + resolve_type=interface.resolve_type, + description=interface._meta.description or interface.__doc__, + fields=interface._meta.get_fields, + ) + + +def generate_objecttype(objecttype): + return GrapheneObjectType( + graphene_type=objecttype, + name=objecttype._meta.name or objecttype.__name__, + description=objecttype._meta.description or objecttype.__doc__, + fields=objecttype._meta.get_fields, + is_type_of=objecttype.is_type_of, + interfaces=objecttype._meta.get_interfaces + ) diff --git a/graphene/generators/definitions.py b/graphene/generators/definitions.py new file mode 100644 index 00000000..04633aa1 --- /dev/null +++ b/graphene/generators/definitions.py @@ -0,0 +1,29 @@ +from graphql import GraphQLObjectType, GraphQLInterfaceType + + +class GrapheneGraphQLType(object): + ''' + A class for extending the base GraphQLType with the related + graphene_type + ''' + def __init__(self, *args, **kwargs): + self.graphene_type = kwargs.pop('graphene_type') + super(GrapheneGraphQLType, self).__init__(*args, **kwargs) + + +class GrapheneInterfaceType(GrapheneGraphQLType, GraphQLInterfaceType): + pass + + +class GrapheneObjectType(GrapheneGraphQLType, GraphQLObjectType): + + def __init__(self, *args, **kwargs): + super(GrapheneObjectType, self).__init__(*args, **kwargs) + self.check_interfaces() + + def check_interfaces(self): + if not self._provided_interfaces: + return + for interface in self._provided_interfaces: + if isinstance(interface, GrapheneInterfaceType): + interface.graphene_type.implements(self.graphene_type) diff --git a/graphene/relay/mutation.py b/graphene/relay/mutation.py index 24a828a0..60b84c17 100644 --- a/graphene/relay/mutation.py +++ b/graphene/relay/mutation.py @@ -59,6 +59,4 @@ class ClientIDMutationMeta(MutationMeta): class ClientIDMutation(six.with_metaclass(ClientIDMutationMeta, Mutation)): - - class Meta: - abstract = True + pass diff --git a/graphene/types/definitions.py b/graphene/types/definitions.py index 978cdf01..a71cf6e7 100644 --- a/graphene/types/definitions.py +++ b/graphene/types/definitions.py @@ -1,5 +1 @@ -class GrapheneGraphQLType(object): - - def __init__(self, *args, **kwargs): - self.graphene_type = kwargs.pop('graphene_type') - super(GrapheneGraphQLType, self).__init__(*args, **kwargs) +from ..generators.definitions import GrapheneGraphQLType diff --git a/graphene/types/interface.py b/graphene/types/interface.py index d7b4127b..fac33216 100644 --- a/graphene/types/interface.py +++ b/graphene/types/interface.py @@ -1 +1 @@ -from .objecttype import Interface, GrapheneInterfaceType +from .objecttype import Interface diff --git a/graphene/types/objecttype.py b/graphene/types/objecttype.py index cc92bcd3..cb073e8e 100644 --- a/graphene/types/objecttype.py +++ b/graphene/types/objecttype.py @@ -1,32 +1,14 @@ import six -from graphql import GraphQLObjectType, GraphQLInterfaceType - from ..utils.copy_fields import copy_fields from ..utils.get_fields import get_fields from ..utils.is_base_type import is_base_type -from .definitions import GrapheneGraphQLType from .field import Field from .options import Options -class GrapheneInterfaceType(GrapheneGraphQLType, GraphQLInterfaceType): - pass - - -class GrapheneObjectType(GrapheneGraphQLType, GraphQLObjectType): - - def __init__(self, *args, **kwargs): - super(GrapheneObjectType, self).__init__(*args, **kwargs) - self.check_interfaces() - - def check_interfaces(self): - if not self._provided_interfaces: - return - for interface in self._provided_interfaces: - if isinstance(interface, GrapheneInterfaceType): - interface.graphene_type.implements(self.graphene_type) +from ..generators import generate_interface, generate_objecttype def get_interfaces(interfaces): @@ -47,14 +29,13 @@ def is_objecttype(bases): def attrs_without_fields(attrs, fields): return {k: v for k, v in attrs.items() if k not in fields} + # We inherit from InterfaceTypeMeta instead of type for being able # to have ObjectTypes extending Interfaces using Python syntax, like: # class MyObjectType(ObjectType, MyInterface) class ObjectTypeMeta(type): def __new__(cls, name, bases, attrs): - super_new = type.__new__ - # Also ensure initialization is only performed for subclasses of # ObjectType,or Interfaces if not is_base_type(bases, ObjectTypeMeta): @@ -90,18 +71,12 @@ class ObjectTypeMeta(type): if not options.graphql_type: fields = copy_fields(Field, fields, parent=cls) - options.graphql_type = GrapheneInterfaceType( - graphene_type=cls, - name=options.name or cls.__name__, - resolve_type=cls.resolve_type, - description=options.description or cls.__doc__, - fields=fields, - ) + options.get_fields = lambda: fields + options.graphql_type = generate_interface(cls) else: assert not fields, "Can't mount Fields in an Interface with a defined graphql_type" fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls) - - options.get_fields = lambda: fields + options.get_fields = lambda: fields for name, field in fields.items(): setattr(cls, field.attname or name, field) @@ -126,19 +101,14 @@ class ObjectTypeMeta(type): if not options.graphql_type: fields = copy_fields(Field, fields, parent=cls) base_interfaces = tuple(b for b in bases if issubclass(b, Interface)) - options.graphql_type = GrapheneObjectType( - graphene_type=cls, - name=options.name or cls.__name__, - description=options.description or cls.__doc__, - fields=fields, - is_type_of=cls.is_type_of, - interfaces=tuple(get_interfaces(interfaces + base_interfaces)) - ) + options.get_fields = lambda: fields + options.get_interfaces = tuple(get_interfaces(interfaces + base_interfaces)) + options.graphql_type = generate_objecttype(cls) else: assert not fields, "Can't mount Fields in an ObjectType with a defined graphql_type" fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls) - options.get_fields = lambda: fields + options.get_fields = lambda: fields for name, field in fields.items(): setattr(cls, field.attname or name, field)