mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 04:34:13 +03:00
Added support for UnionTypes
This commit is contained in:
parent
d2ca8a96a9
commit
24cd190f95
|
@ -8,7 +8,7 @@ Graphene is a Python library for building GraphQL schemas/types fast and easily.
|
|||
- **Django:** Automatic *Django model* mapping to Graphene Types. Check a fully working [Django](http://github.com/graphql-python/swapi-graphene) implementation
|
||||
|
||||
|
||||
*But, what is supported in this Python version?* **Everything**: Interfaces, ObjectTypes, Mutations and Relay (Nodes, Connections and Mutations).
|
||||
*What is supported in this Python version?* **Everything**: Interfaces, ObjectTypes, Mutations, Scalars, Unions and Relay (Nodes, Connections and Mutations).
|
||||
|
||||
|
||||
## Installation
|
||||
|
|
|
@ -12,9 +12,9 @@ easily.
|
|||
`Django <http://github.com/graphql-python/swapi-graphene>`__
|
||||
implementation
|
||||
|
||||
*But, what is supported in this Python version?* **Everything**:
|
||||
Interfaces, ObjectTypes, Mutations and Relay (Nodes, Connections and
|
||||
Mutations).
|
||||
*What is supported in this Python version?* **Everything**: Interfaces,
|
||||
ObjectTypes, Mutations, Scalars, Unions and Relay (Nodes, Connections
|
||||
and Mutations).
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
|
|
@ -13,8 +13,10 @@ class Options(object):
|
|||
self.local_fields = []
|
||||
self.is_interface = False
|
||||
self.is_mutation = False
|
||||
self.is_union = False
|
||||
self.interfaces = []
|
||||
self.parents = []
|
||||
self.types = []
|
||||
self.valid_attrs = DEFAULT_NAMES
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
|
|
|
@ -7,7 +7,7 @@ import six
|
|||
|
||||
from graphene import signals
|
||||
from graphql.core.type import (GraphQLInputObjectType, GraphQLInterfaceType,
|
||||
GraphQLObjectType)
|
||||
GraphQLObjectType, GraphQLUnionType)
|
||||
|
||||
from ..exceptions import SkipField
|
||||
from ..options import Options
|
||||
|
@ -51,10 +51,17 @@ class ObjectTypeMeta(type):
|
|||
|
||||
new_class._meta.is_interface = new_class.is_interface(parents)
|
||||
new_class._meta.is_mutation = new_class.is_mutation(parents)
|
||||
union_types = [p for p in parents if issubclass(p, BaseObjectType)]
|
||||
|
||||
new_class._meta.is_union = len(union_types) > 1
|
||||
new_class._meta.types = union_types
|
||||
|
||||
assert not (
|
||||
new_class._meta.is_interface and new_class._meta.is_mutation)
|
||||
|
||||
assert not (
|
||||
new_class._meta.is_interface and new_class._meta.is_union)
|
||||
|
||||
# Add all attributes to the class.
|
||||
for obj_name, obj in attrs.items():
|
||||
new_class.add_to_class(obj_name, obj)
|
||||
|
@ -66,6 +73,8 @@ class ObjectTypeMeta(type):
|
|||
new_class.add_extra_fields()
|
||||
|
||||
new_fields = new_class._meta.local_fields
|
||||
assert not(new_class._meta.is_union and new_fields), 'An union cannot have extra fields'
|
||||
|
||||
field_names = {f.name: f for f in new_fields}
|
||||
|
||||
for base in parents:
|
||||
|
@ -129,6 +138,8 @@ class BaseObjectType(BaseType):
|
|||
def __new__(cls, *args, **kwargs):
|
||||
if cls._meta.is_interface:
|
||||
raise Exception("An interface cannot be initialized")
|
||||
if cls._meta.is_union:
|
||||
raise Exception("An union cannot be initialized")
|
||||
return super(BaseObjectType, cls).__new__(cls)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -182,6 +193,12 @@ class BaseObjectType(BaseType):
|
|||
resolve_type=partial(cls.resolve_type, schema),
|
||||
fields=partial(cls.get_fields, schema)
|
||||
)
|
||||
elif cls._meta.is_union:
|
||||
return GraphQLUnionType(
|
||||
cls._meta.type_name,
|
||||
types=cls._meta.types,
|
||||
description=cls._meta.description,
|
||||
)
|
||||
return GraphQLObjectType(
|
||||
cls._meta.type_name,
|
||||
description=cls._meta.description,
|
||||
|
|
|
@ -4,7 +4,8 @@ from graphene.core.schema import Schema
|
|||
from graphene.core.types import Int, Interface, String
|
||||
from graphql.core.execution.middlewares.utils import (resolver_has_tag,
|
||||
tag_resolver)
|
||||
from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType
|
||||
from graphql.core.type import (GraphQLInterfaceType, GraphQLObjectType,
|
||||
GraphQLUnionType)
|
||||
|
||||
|
||||
class Character(Interface):
|
||||
|
@ -34,6 +35,16 @@ class Human(Character):
|
|||
def write_prop(self, value):
|
||||
self._write_prop = value
|
||||
|
||||
|
||||
class Droid(Character):
|
||||
'''Droid description'''
|
||||
pass
|
||||
|
||||
|
||||
class CharacterType(Droid, Human):
|
||||
'''Union Type'''
|
||||
pass
|
||||
|
||||
schema = Schema()
|
||||
|
||||
|
||||
|
@ -52,6 +63,19 @@ def test_interface_cannot_initialize():
|
|||
assert 'An interface cannot be initialized' == str(excinfo.value)
|
||||
|
||||
|
||||
def test_union():
|
||||
object_type = schema.T(CharacterType)
|
||||
assert CharacterType._meta.is_union is True
|
||||
assert isinstance(object_type, GraphQLUnionType)
|
||||
assert object_type.description == 'Union Type'
|
||||
|
||||
|
||||
def test_union_cannot_initialize():
|
||||
with raises(Exception) as excinfo:
|
||||
CharacterType()
|
||||
assert 'An union cannot be initialized' == str(excinfo.value)
|
||||
|
||||
|
||||
def test_interface_resolve_type():
|
||||
resolve_type = Character.resolve_type(schema, Human(object()))
|
||||
assert isinstance(resolve_type, GraphQLObjectType)
|
||||
|
|
Loading…
Reference in New Issue
Block a user