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