mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-25 19:13:57 +03:00
First stage separate interfaces
This commit is contained in:
parent
ff3968faea
commit
04492600e5
|
@ -4,7 +4,9 @@ from graphene import relay, resolve_only_args
|
|||
from .data import create_ship, get_empire, get_faction, get_rebels, get_ship
|
||||
|
||||
|
||||
class Ship(relay.Node, graphene.ObjectType):
|
||||
class Ship(graphene.ObjectType):
|
||||
class Meta:
|
||||
interfaces = [relay.Node]
|
||||
'''A ship in the Star Wars saga'''
|
||||
name = graphene.String(description='The name of the ship.')
|
||||
|
||||
|
|
|
@ -96,8 +96,8 @@ class IterableConnectionField(Field):
|
|||
@property
|
||||
def connection(self):
|
||||
from .node import Node
|
||||
if issubclass(self._type, Node):
|
||||
connection_type = self._type.get_default_connection()
|
||||
if Node in self._type._meta.interfaces:
|
||||
connection_type = self._type.Connection
|
||||
else:
|
||||
connection_type = self._type
|
||||
assert issubclass(connection_type, Connection), '{} type have to be a subclass of Connection'.format(str(self))
|
||||
|
|
|
@ -12,6 +12,15 @@ from ..utils.copy_fields import copy_fields
|
|||
from .connection import Connection
|
||||
|
||||
|
||||
def get_default_connection(cls):
|
||||
assert issubclass(cls, ObjectType), 'Can only get connection type on implemented Nodes.'
|
||||
|
||||
class Meta:
|
||||
node = cls
|
||||
|
||||
return type('{}Connection'.format(cls.__name__), (Connection,), {'Meta': Meta})
|
||||
|
||||
|
||||
# We inherit from ObjectTypeMeta as we want to allow
|
||||
# inheriting from Node, and also ObjectType.
|
||||
# Like class MyNode(Node): pass
|
||||
|
@ -24,17 +33,6 @@ class NodeMeta(ObjectTypeMeta):
|
|||
meta,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _create_objecttype(cls, name, bases, attrs):
|
||||
cls = super(NodeMeta, cls)._create_objecttype(cls, name, bases, attrs)
|
||||
require_get_node = Node._meta.graphql_type in cls._meta.graphql_type._provided_interfaces
|
||||
if require_get_node:
|
||||
assert hasattr(
|
||||
cls, 'get_node'), '{}.get_node method is required by the Node interface.'.format(
|
||||
cls.__name__)
|
||||
|
||||
return cls
|
||||
|
||||
@staticmethod
|
||||
def _create_interface(cls, name, bases, attrs):
|
||||
options = cls._get_interface_options(attrs.pop('Meta', None))
|
||||
|
@ -95,10 +93,14 @@ class Node(six.with_metaclass(NodeMeta, Interface)):
|
|||
return graphql_type.graphene_type.get_node(_id, context, info)
|
||||
|
||||
@classmethod
|
||||
def get_default_connection(cls):
|
||||
assert issubclass(cls, ObjectType), 'Can only get connection type on implemented Nodes.'
|
||||
if not cls._connection:
|
||||
class Meta:
|
||||
node = cls
|
||||
cls._connection = type('{}Connection'.format(cls.__name__), (Connection,), {'Meta': Meta})
|
||||
return cls._connection
|
||||
def implements(cls, objecttype):
|
||||
require_get_node = Node._meta.graphql_type in objecttype._meta.get_interfaces
|
||||
get_connection = getattr(objecttype, 'get_connection', None)
|
||||
if not get_connection:
|
||||
get_connection = partial(get_default_connection, objecttype)
|
||||
|
||||
objecttype.Connection = get_connection()
|
||||
if require_get_node:
|
||||
assert hasattr(
|
||||
objecttype, 'get_node'), '{}.get_node method is required by the Node interface.'.format(
|
||||
objecttype.__name__)
|
||||
|
|
|
@ -6,7 +6,9 @@ from ..connection import Connection
|
|||
from ..node import Node
|
||||
|
||||
|
||||
class MyObject(Node, ObjectType):
|
||||
class MyObject(ObjectType):
|
||||
class Meta:
|
||||
interfaces = [Node]
|
||||
field = String()
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -8,8 +8,9 @@ from ..connection import Connection
|
|||
from ..node import Node
|
||||
|
||||
|
||||
class MyNode(Node, ObjectType):
|
||||
|
||||
class MyNode(ObjectType):
|
||||
class Meta:
|
||||
interfaces = [Node]
|
||||
name = String()
|
||||
|
||||
@staticmethod
|
||||
|
@ -46,12 +47,12 @@ def test_node_good():
|
|||
|
||||
|
||||
def test_node_get_connection():
|
||||
connection = MyNode.get_default_connection()
|
||||
connection = MyNode.Connection
|
||||
assert issubclass(connection, Connection)
|
||||
|
||||
|
||||
def test_node_get_connection_dont_duplicate():
|
||||
assert MyNode.get_default_connection() == MyNode.get_default_connection()
|
||||
assert MyNode.Connection == MyNode.Connection
|
||||
|
||||
|
||||
def test_node_query():
|
||||
|
|
|
@ -24,12 +24,15 @@ class BasePhoto(Interface):
|
|||
width = Int()
|
||||
|
||||
|
||||
class User(CustomNode, ObjectType):
|
||||
class User(ObjectType):
|
||||
class Meta:
|
||||
interfaces = [CustomNode]
|
||||
name = String()
|
||||
|
||||
|
||||
class Photo(CustomNode, BasePhoto, ObjectType):
|
||||
pass
|
||||
class Photo(ObjectType):
|
||||
class Meta:
|
||||
interfaces = [CustomNode, BasePhoto]
|
||||
|
||||
|
||||
user_data = {
|
||||
|
@ -50,7 +53,6 @@ schema = Schema(query=RootQuery, types=[User, Photo])
|
|||
|
||||
|
||||
def test_str_schema_correct():
|
||||
print str(schema)
|
||||
assert str(schema) == '''schema {
|
||||
query: RootQuery
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
import inspect
|
||||
import six
|
||||
|
||||
from ..utils.copy_fields import copy_fields
|
||||
|
@ -97,12 +97,17 @@ 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))
|
||||
inherited_interfaces = tuple(b for b in bases if issubclass(b, Interface))
|
||||
options.get_fields = lambda: fields
|
||||
options.get_interfaces = tuple(get_interfaces(interfaces + base_interfaces))
|
||||
options.interfaces = interfaces + inherited_interfaces
|
||||
options.get_interfaces = tuple(get_interfaces(options.interfaces))
|
||||
options.graphql_type = generate_objecttype(cls)
|
||||
for i in options.interfaces:
|
||||
if inspect.isclass(i) and issubclass(i, Interface):
|
||||
i.implements(cls)
|
||||
else:
|
||||
assert not fields, "Can't mount Fields in an ObjectType with a defined graphql_type"
|
||||
assert not interfaces, "Can't have extra interfaces with a defined graphql_type"
|
||||
fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls)
|
||||
|
||||
options.get_fields = lambda: fields
|
||||
|
@ -175,3 +180,7 @@ class Interface(six.with_metaclass(ObjectTypeMeta)):
|
|||
if not isinstance(self, ObjectType):
|
||||
raise Exception("An interface cannot be intitialized")
|
||||
super(Interface, self).__init__(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def implements(cls, objecttype):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue
Block a user