Improved classtypes relay support

This commit is contained in:
Syrus Akbary 2015-12-02 22:47:37 -08:00
parent 8abcaff02b
commit 5b3000f734
4 changed files with 57 additions and 48 deletions

View File

@ -40,9 +40,6 @@ class Interface(six.with_metaclass(InterfaceMeta, ObjectType)):
@classmethod
def internal_type(cls, schema):
if cls._meta.abstract:
raise Exception("Abstract Interfaces don't have a specific type.")
if not cls._meta.interface:
return super(Interface, cls).internal_type(schema)

View File

@ -90,11 +90,5 @@ class GlobalIDField(Field):
def __init__(self, *args, **kwargs):
super(GlobalIDField, self).__init__(NonNull(ID()), *args, **kwargs)
def contribute_to_class(self, cls, name):
from graphene.relay.utils import is_node, is_node_type
in_node = is_node(cls) or is_node_type(cls)
assert in_node, 'GlobalIDField could only be inside a Node, but got %r' % cls
super(GlobalIDField, self).contribute_to_class(cls, name)
def resolver(self, instance, args, info):
return instance.to_global_id()

View File

@ -1,4 +1,5 @@
import inspect
import six
import warnings
from collections import Iterable
from functools import wraps
@ -6,8 +7,10 @@ from functools import wraps
from graphql_relay.connection.arrayconnection import connection_from_list
from graphql_relay.node.node import to_global_id
from ..core.types import (Boolean, Field, InputObjectType, Interface, List,
Mutation, ObjectType, String)
from ..core.classtypes import InputObjectType, Interface, Mutation, ObjectType
from ..core.classtypes.mutation import MutationMeta
from ..core.classtypes.interface import InterfaceMeta
from ..core.types import Boolean, Field, List, String
from ..core.types.argument import ArgumentsGroup
from ..core.types.definitions import NonNull
from ..utils import memoize
@ -83,13 +86,9 @@ class Connection(ObjectType):
return self._connection_data
class BaseNode(object):
@classmethod
def _prepare_class(cls):
from graphene.relay.utils import is_node
if is_node(cls):
get_node = getattr(cls, 'get_node')
class NodeMeta(InterfaceMeta):
def construct_get_node(cls):
get_node = getattr(cls, 'get_node', None)
assert get_node, 'get_node classmethod not found in %s Node' % cls
assert callable(get_node), 'get_node have to be callable'
args = 3
@ -111,6 +110,20 @@ class BaseNode(object):
setattr(cls, 'get_node', wrapped_node)
def construct(cls, *args, **kwargs):
cls = super(NodeMeta, cls).construct(*args, **kwargs)
if not cls._meta.abstract:
cls.construct_get_node()
return cls
class Node(six.with_metaclass(NodeMeta, Interface)):
'''An object with an ID'''
id = GlobalIDField()
class Meta:
abstract = True
def to_global_id(self):
type_name = self._meta.type_name
return to_global_id(type_name, self.id)
@ -127,27 +140,31 @@ class BaseNode(object):
return cls.edge_type
class Node(BaseNode, Interface):
'''An object with an ID'''
id = GlobalIDField()
class MutationInputType(InputObjectType):
client_mutation_id = String(required=True)
class ClientIDMutation(Mutation):
client_mutation_id = String(required=True)
@classmethod
def _construct_arguments(cls, items):
class RelayMutationMeta(MutationMeta):
def construct(cls, *args, **kwargs):
cls = super(RelayMutationMeta, cls).construct(*args, **kwargs)
if not cls._meta.abstract:
assert hasattr(
cls, 'mutate_and_get_payload'), 'You have to implement mutate_and_get_payload'
return cls
def construct_arguments(cls, items):
new_input_type = type('{}Input'.format(
cls._meta.type_name), (MutationInputType, ), items)
cls.add_to_class('input_type', new_input_type)
return ArgumentsGroup(input=NonNull(new_input_type))
class ClientIDMutation(six.with_metaclass(RelayMutationMeta, Mutation)):
client_mutation_id = String(required=True)
class Meta:
abstract = True
@classmethod
def mutate(cls, instance, args, info):
input = args.get('input')

View File

@ -1,10 +1,11 @@
from .types import BaseNode
from .types import Node
def is_node(object_type):
return object_type and issubclass(
object_type, BaseNode) and not is_node_type(object_type)
object_type, Node) and not object_type._meta.abstract
def is_node_type(object_type):
return BaseNode in object_type.__bases__
return object_type and issubclass(
object_type, Node) and object_type._meta.abstract