mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-11-01 00:17:26 +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