mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-16 19:40:39 +03:00
Improved extend interfaces syntax
This commit is contained in:
parent
d67b7bc6a1
commit
d8d884c9be
|
@ -21,17 +21,11 @@ class Character(graphene.Interface):
|
||||||
return [get_character(f) for f in self.friends]
|
return [get_character(f) for f in self.friends]
|
||||||
|
|
||||||
|
|
||||||
# @graphene.implements(Character)
|
class Human(graphene.ObjectType, Character):
|
||||||
class Human(graphene.ObjectType):
|
|
||||||
class Meta:
|
|
||||||
interfaces = [Character]
|
|
||||||
home_planet = graphene.String()
|
home_planet = graphene.String()
|
||||||
|
|
||||||
|
|
||||||
# @graphene.implements(Character)
|
class Droid(graphene.ObjectType, Character):
|
||||||
class Droid(graphene.ObjectType):
|
|
||||||
class Meta:
|
|
||||||
interfaces = [Character]
|
|
||||||
primary_function = graphene.String()
|
primary_function = graphene.String()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,7 @@ from graphene import implements, 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
|
||||||
|
|
||||||
|
|
||||||
# @implements(relay.Node)
|
class Ship(graphene.ObjectType, relay.Node):
|
||||||
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.')
|
||||||
|
|
||||||
|
@ -16,10 +13,7 @@ class Ship(graphene.ObjectType):
|
||||||
return get_ship(id)
|
return get_ship(id)
|
||||||
|
|
||||||
|
|
||||||
# @implements(relay.Node)
|
class Faction(graphene.ObjectType, relay.Node):
|
||||||
class Faction(graphene.ObjectType):
|
|
||||||
class Meta:
|
|
||||||
interfaces = [relay.Node]
|
|
||||||
'''A faction in the Star Wars saga'''
|
'''A faction in the Star Wars saga'''
|
||||||
name = graphene.String(description='The name of the faction.')
|
name = graphene.String(description='The name of the faction.')
|
||||||
# ships = relay.ConnectionField(
|
# ships = relay.ConnectionField(
|
||||||
|
|
|
@ -4,25 +4,24 @@ import six
|
||||||
from graphql_relay import node_definitions, from_global_id, to_global_id
|
from graphql_relay import node_definitions, from_global_id, to_global_id
|
||||||
|
|
||||||
from ..types.field import Field
|
from ..types.field import Field
|
||||||
|
from ..types.objecttype import ObjectTypeMeta
|
||||||
from ..types.interface import GrapheneInterfaceType, Interface, InterfaceTypeMeta
|
from ..types.interface import GrapheneInterfaceType, Interface, InterfaceTypeMeta
|
||||||
|
|
||||||
|
|
||||||
class NodeMeta(InterfaceTypeMeta):
|
class NodeMeta(ObjectTypeMeta):
|
||||||
|
|
||||||
def construct_graphql_type(cls, bases):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def construct(cls, bases, attrs):
|
def construct(cls, bases, attrs):
|
||||||
cls.get_node = attrs.pop('get_node')
|
if not cls.is_object_type():
|
||||||
cls.id_resolver = attrs.pop('id_resolver', None)
|
cls.get_node = attrs.pop('get_node')
|
||||||
node_interface, node_field = node_definitions(
|
cls.id_resolver = attrs.pop('id_resolver', None)
|
||||||
cls.get_node,
|
node_interface, node_field = node_definitions(
|
||||||
id_resolver=cls.id_resolver,
|
cls.get_node,
|
||||||
interface_class=partial(GrapheneInterfaceType, graphene_type=cls),
|
id_resolver=cls.id_resolver,
|
||||||
field_class=Field,
|
interface_class=partial(GrapheneInterfaceType, graphene_type=cls),
|
||||||
)
|
field_class=Field,
|
||||||
cls._meta.graphql_type = node_interface
|
)
|
||||||
cls._Field = node_field
|
cls._meta.graphql_type = node_interface
|
||||||
|
cls._Field = node_field
|
||||||
return super(NodeMeta, cls).construct(bases, attrs)
|
return super(NodeMeta, cls).construct(bases, attrs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -7,9 +7,7 @@ from ...types import ObjectType, Schema, implements
|
||||||
from ...types.scalars import String
|
from ...types.scalars import String
|
||||||
|
|
||||||
|
|
||||||
class MyNode(ObjectType):
|
class MyNode(ObjectType, Node):
|
||||||
class Meta:
|
|
||||||
interfaces = [Node]
|
|
||||||
|
|
||||||
name = String()
|
name = String()
|
||||||
|
|
||||||
|
|
|
@ -15,17 +15,11 @@ class CustomNode(Node):
|
||||||
return photo_data.get(id)
|
return photo_data.get(id)
|
||||||
|
|
||||||
|
|
||||||
# @implements(CustomNode)
|
class User(ObjectType, CustomNode):
|
||||||
class User(ObjectType):
|
|
||||||
class Meta:
|
|
||||||
interfaces = [CustomNode]
|
|
||||||
name = String()
|
name = String()
|
||||||
|
|
||||||
|
|
||||||
# @implements(CustomNode)
|
class Photo(ObjectType, CustomNode):
|
||||||
class Photo(ObjectType):
|
|
||||||
class Meta:
|
|
||||||
interfaces = [CustomNode]
|
|
||||||
width = Int()
|
width = Int()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,34 +69,36 @@ class Field(AbstractField, GraphQLField, OrderedType):
|
||||||
self.attname = attname
|
self.attname = attname
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
|
def default_resolver(self, root, args, context, info):
|
||||||
|
return getattr(root, self.source or self.attname, None)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def resolver(self):
|
def resolver(self):
|
||||||
from .objecttype import ObjectType
|
from .objecttype import ObjectType
|
||||||
from .interface import GrapheneInterfaceType
|
from .interface import GrapheneInterfaceType
|
||||||
def default_resolver(root, args, context, info):
|
|
||||||
return getattr(root, self.source or self.attname, None)
|
|
||||||
|
|
||||||
resolver = getattr(self.parent, 'resolve_{}'.format(self.attname), None)
|
resolver = getattr(self.parent, 'resolve_{}'.format(self.attname), None)
|
||||||
|
|
||||||
# We try to get the resolver from the interfaces
|
# We try to get the resolver from the interfaces
|
||||||
if not resolver and issubclass(self.parent, ObjectType):
|
# This is not needed anymore as Interfaces could be extended now with Python syntax
|
||||||
graphql_type = self.parent._meta.graphql_type
|
# if not resolver and issubclass(self.parent, ObjectType):
|
||||||
interfaces = graphql_type._provided_interfaces or []
|
# graphql_type = self.parent._meta.graphql_type
|
||||||
for interface in interfaces:
|
# interfaces = graphql_type._provided_interfaces or []
|
||||||
if not isinstance(interface, GrapheneInterfaceType):
|
# for interface in interfaces:
|
||||||
continue
|
# if not isinstance(interface, GrapheneInterfaceType):
|
||||||
fields = interface.get_fields()
|
# continue
|
||||||
if self.attname in fields:
|
# fields = interface.get_fields()
|
||||||
resolver = getattr(interface.graphene_type, 'resolve_{}'.format(self.attname), None)
|
# if self.attname in fields:
|
||||||
if resolver:
|
# resolver = getattr(interface.graphene_type, 'resolve_{}'.format(self.attname), None)
|
||||||
# We remove the bounding to the method
|
# if resolver:
|
||||||
resolver = resolver #.__func__
|
# # We remove the bounding to the method
|
||||||
break
|
# resolver = resolver #.__func__
|
||||||
|
# break
|
||||||
|
|
||||||
if resolver:
|
if resolver:
|
||||||
resolver = resolver.__func__
|
resolver = resolver.__func__
|
||||||
else:
|
else:
|
||||||
resolver = default_resolver
|
resolver = self.default_resolver
|
||||||
|
|
||||||
# def resolver_wrapper(root, *args, **kwargs):
|
# def resolver_wrapper(root, *args, **kwargs):
|
||||||
# if not isinstance(root, self.parent):
|
# if not isinstance(root, self.parent):
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
from itertools import chain
|
||||||
import copy
|
import copy
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from graphql import GraphQLObjectType
|
from graphql import GraphQLObjectType
|
||||||
|
|
||||||
from .definitions import FieldsMeta, ClassTypeMeta, GrapheneGraphQLType
|
from .definitions import FieldsMeta, ClassTypeMeta, GrapheneGraphQLType
|
||||||
from .interface import GrapheneInterfaceType
|
from .interface import GrapheneInterfaceType, InterfaceTypeMeta, Interface
|
||||||
|
|
||||||
|
|
||||||
class GrapheneObjectType(GrapheneGraphQLType, GraphQLObjectType):
|
class GrapheneObjectType(GrapheneGraphQLType, GraphQLObjectType):
|
||||||
|
@ -45,7 +46,7 @@ def get_interfaces(cls, interfaces):
|
||||||
yield graphql_type
|
yield graphql_type
|
||||||
|
|
||||||
|
|
||||||
class ObjectTypeMeta(FieldsMeta, ClassTypeMeta):
|
class ObjectTypeMeta(InterfaceTypeMeta):
|
||||||
|
|
||||||
def get_options(cls, meta):
|
def get_options(cls, meta):
|
||||||
return cls.options_class(
|
return cls.options_class(
|
||||||
|
@ -57,9 +58,19 @@ class ObjectTypeMeta(FieldsMeta, ClassTypeMeta):
|
||||||
abstract=False
|
abstract=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_interfaces(cls, bases):
|
||||||
|
return (b for b in bases if issubclass(b, Interface))
|
||||||
|
|
||||||
|
def is_object_type(cls):
|
||||||
|
return issubclass(cls, ObjectType)
|
||||||
|
|
||||||
def construct(cls, bases, attrs):
|
def construct(cls, bases, attrs):
|
||||||
if not cls._meta.abstract:
|
if not cls._meta.abstract and cls.is_object_type():
|
||||||
interfaces = tuple(get_interfaces(cls, cls._meta.interfaces))
|
cls.get_interfaces(bases)
|
||||||
|
interfaces = tuple(get_interfaces(cls, chain(
|
||||||
|
cls._meta.interfaces,
|
||||||
|
cls.get_interfaces(bases),
|
||||||
|
)))
|
||||||
local_fields = cls._extract_local_fields(attrs)
|
local_fields = cls._extract_local_fields(attrs)
|
||||||
if not cls._meta.graphql_type:
|
if not cls._meta.graphql_type:
|
||||||
cls = super(ObjectTypeMeta, cls).construct(bases, attrs)
|
cls = super(ObjectTypeMeta, cls).construct(bases, attrs)
|
||||||
|
|
|
@ -201,6 +201,25 @@ def test_objecttype_graphene_interface():
|
||||||
assert fields['field'] > fields['extended'] > fields['name']
|
assert fields['field'] > fields['extended'] > fields['name']
|
||||||
|
|
||||||
|
|
||||||
|
def test_objecttype_graphene_inherit_interface():
|
||||||
|
class GrapheneInterface(Interface):
|
||||||
|
name = Field(GraphQLString)
|
||||||
|
extended = Field(GraphQLString)
|
||||||
|
|
||||||
|
class GrapheneObjectType(ObjectType, GrapheneInterface):
|
||||||
|
field = Field(GraphQLString)
|
||||||
|
|
||||||
|
graphql_type = GrapheneObjectType._meta.graphql_type
|
||||||
|
assert graphql_type.get_interfaces() == (GrapheneInterface._meta.graphql_type, )
|
||||||
|
assert graphql_type.is_type_of(GrapheneObjectType(), None, None)
|
||||||
|
fields = graphql_type.get_fields()
|
||||||
|
assert 'field' in fields
|
||||||
|
assert 'extended' in fields
|
||||||
|
assert 'name' in fields
|
||||||
|
assert issubclass(GrapheneObjectType, GrapheneInterface)
|
||||||
|
assert fields['field'] > fields['extended'] > fields['name']
|
||||||
|
|
||||||
|
|
||||||
# def test_objecttype_graphene_interface_extended():
|
# def test_objecttype_graphene_interface_extended():
|
||||||
# class GrapheneInterface(Interface):
|
# class GrapheneInterface(Interface):
|
||||||
# field = Field(GraphQLString)
|
# field = Field(GraphQLString)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user