From b772499b9b9f4878420ad7c91515f2c45ea1e0d2 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Sun, 19 Jun 2016 14:29:41 -0700 Subject: [PATCH] Improved Interface/ObjectType is_type_of abstraction --- graphene/types/interface.py | 20 ++++++++++++------- graphene/types/objecttype.py | 37 ++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/graphene/types/interface.py b/graphene/types/interface.py index 190d9f66..37218d8c 100644 --- a/graphene/types/interface.py +++ b/graphene/types/interface.py @@ -16,6 +16,16 @@ class GrapheneInterfaceType(GrapheneGraphQLType, GraphQLInterfaceType): class InterfaceTypeMeta(type): + @staticmethod + def _get_interface_options(meta): + return Options( + meta, + name=None, + description=None, + graphql_type=None, + abstract=False + ) + def __new__(cls, name, bases, attrs): super_new = super(InterfaceTypeMeta, cls).__new__ @@ -24,13 +34,7 @@ class InterfaceTypeMeta(type): if not is_base_type(bases, InterfaceTypeMeta): return super_new(cls, name, bases, attrs) - options = Options( - attrs.pop('Meta', None), - name=None, - description=None, - graphql_type=None, - abstract=False - ) + options = cls._get_interface_options(attrs.pop('Meta', None)) fields = get_fields(Interface, attrs, bases) attrs = attrs_without_fields(attrs, fields) @@ -41,6 +45,7 @@ class InterfaceTypeMeta(type): 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, ) @@ -59,6 +64,7 @@ def attrs_without_fields(attrs, fields): class Interface(six.with_metaclass(InterfaceTypeMeta)): + resolve_type = None def __init__(self, *args, **kwargs): from .objecttype import ObjectType diff --git a/graphene/types/objecttype.py b/graphene/types/objecttype.py index e4518145..6892936b 100644 --- a/graphene/types/objecttype.py +++ b/graphene/types/objecttype.py @@ -26,22 +26,6 @@ class GrapheneObjectType(GrapheneGraphQLType, GraphQLObjectType): if isinstance(interface, GrapheneInterfaceType): interface.graphene_type.implements(self.graphene_type) - @property - def is_type_of(self): - return self._is_type_of or self.default_is_type_of - - @is_type_of.setter - def is_type_of(self, is_type_of): - self._is_type_of = is_type_of - - def default_is_type_of(self, interface, context, info): - from ..utils.get_graphql_type import get_graphql_type - try: - graphql_type = get_graphql_type(type(interface)) - return graphql_type.name == self.name - except: - return False - def get_interfaces(interfaces): from ..utils.get_graphql_type import get_graphql_type @@ -51,6 +35,13 @@ def get_interfaces(interfaces): yield graphql_type +def is_objecttype(bases): + for base in bases: + if issubclass(base, ObjectType): + return True + return False + + # We inherit from InterfaceTypeMeta instead of type for being able # to have ObjectTypes extending Interfaces using Python syntax, like: # class MyObjectType(ObjectType, MyInterface) @@ -61,9 +52,13 @@ class ObjectTypeMeta(InterfaceTypeMeta): # Also ensure initialization is only performed for subclasses of Model # (excluding Model class itself). + if not is_base_type(bases, ObjectTypeMeta): return super_new(cls, name, bases, attrs) + if not is_objecttype(bases): + return super(ObjectTypeMeta, cls).__new__(cls, name, bases, attrs) + options = Options( attrs.pop('Meta', None), name=None, @@ -86,6 +81,7 @@ class ObjectTypeMeta(InterfaceTypeMeta): 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)) ) else: @@ -147,3 +143,12 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta)): raise TypeError( "'%s' is an invalid keyword argument for this function" % list(kwargs)[0]) + + @classmethod + def is_type_of(cls, interface, context, info): + from ..utils.get_graphql_type import get_graphql_type + try: + graphql_type = get_graphql_type(type(interface)) + return graphql_type.name == cls._meta.graphql_type.name + except: + return False