mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-10-31 07:57:26 +03:00 
			
		
		
		
	Added mutation and props utility
This commit is contained in:
		
							parent
							
								
									4c8f5367ba
								
							
						
					
					
						commit
						01190fb6ff
					
				
							
								
								
									
										28
									
								
								graphene/types/mutation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								graphene/types/mutation.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| from functools import partial | ||||
| import six | ||||
| 
 | ||||
| from .objecttype import ObjectTypeMeta, ObjectType | ||||
| from .field import Field | ||||
| 
 | ||||
| from ..utils.props import props | ||||
| 
 | ||||
| 
 | ||||
| class MutationMeta(ObjectTypeMeta): | ||||
| 
 | ||||
|     def construct_field(cls, field_attrs): | ||||
|         resolver = getattr(cls, 'mutate', None) | ||||
|         assert resolver, 'All mutations must define a mutate method in it' | ||||
|         return partial(Field, cls, args=field_attrs, resolver=resolver) | ||||
| 
 | ||||
|     def construct(cls, bases, attrs): | ||||
|         super(MutationMeta, cls).construct(bases, attrs) | ||||
|         if not cls._meta.abstract: | ||||
|             Input = attrs.pop('Input', None) | ||||
|             field_attrs = props(Input) if Input else {} | ||||
|             cls.Field = cls.construct_field(field_attrs) | ||||
|         return cls | ||||
| 
 | ||||
| 
 | ||||
| class Mutation(six.with_metaclass(MutationMeta, ObjectType)): | ||||
|     class Meta: | ||||
|         abstract = True | ||||
							
								
								
									
										234
									
								
								graphene/types/tests/test_mutation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								graphene/types/tests/test_mutation.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,234 @@ | |||
| import pytest | ||||
| 
 | ||||
| from graphql import GraphQLObjectType, GraphQLField, GraphQLString, GraphQLInterfaceType | ||||
| 
 | ||||
| from ..schema import Schema | ||||
| from ..objecttype import ObjectType | ||||
| from ..mutation import Mutation | ||||
| from ..interface import Interface | ||||
| from ..scalars import String | ||||
| from ..field import Field | ||||
| from ..argument import Argument | ||||
| 
 | ||||
| 
 | ||||
| def test_generate_mutation_no_args(): | ||||
|     class MyMutation(Mutation): | ||||
|         '''Documentation''' | ||||
|         @classmethod | ||||
|         def mutate(cls, *args, **kwargs): | ||||
|             pass | ||||
| 
 | ||||
|     assert issubclass(MyMutation, ObjectType) | ||||
|     graphql_type = MyMutation._meta.graphql_type | ||||
|     assert isinstance(graphql_type, GraphQLObjectType) | ||||
|     assert graphql_type.name == "MyMutation" | ||||
|     assert graphql_type.description == "Documentation" | ||||
| 
 | ||||
| 
 | ||||
| def test_generate_mutation_with_args(): | ||||
|     class MyMutation(Mutation): | ||||
|         '''Documentation''' | ||||
|         class Input: | ||||
|             s = String() | ||||
| 
 | ||||
|         @classmethod | ||||
|         def mutate(cls, *args, **kwargs): | ||||
|             pass | ||||
| 
 | ||||
|     graphql_type = MyMutation._meta.graphql_type | ||||
|     field = MyMutation.Field() | ||||
|     assert isinstance(graphql_type, GraphQLObjectType) | ||||
|     assert graphql_type.name == "MyMutation" | ||||
|     assert graphql_type.description == "Documentation" | ||||
|     assert isinstance(field, Field) | ||||
|     assert field.type == MyMutation._meta.graphql_type | ||||
|     assert 's' in field.args | ||||
|     assert field.args['s'].type == GraphQLString | ||||
| 
 | ||||
| 
 | ||||
| def test_generate_mutation_with_meta(): | ||||
|     class MyMutation(Mutation): | ||||
|         class Meta: | ||||
|             name = 'MyOtherMutation' | ||||
|             description = 'Documentation' | ||||
| 
 | ||||
|         @classmethod | ||||
|         def mutate(cls, *args, **kwargs): | ||||
|             pass | ||||
| 
 | ||||
|     graphql_type = MyMutation._meta.graphql_type | ||||
|     assert isinstance(graphql_type, GraphQLObjectType) | ||||
|     assert graphql_type.name == "MyOtherMutation" | ||||
|     assert graphql_type.description == "Documentation" | ||||
| 
 | ||||
| 
 | ||||
| def test_empty_mutation_has_meta(): | ||||
|     class MyMutation(Mutation): | ||||
|         @classmethod | ||||
|         def mutate(cls, *args, **kwargs): | ||||
|             pass | ||||
| 
 | ||||
|     assert MyMutation._meta | ||||
| 
 | ||||
| 
 | ||||
| def test_mutation_raises_exception_if_no_mutate(): | ||||
|     with pytest.raises(AssertionError) as excinfo: | ||||
|         class MyMutation(Mutation): | ||||
|             pass | ||||
| 
 | ||||
|     assert "All mutations must define a mutate method in it" == str(excinfo.value) | ||||
| 
 | ||||
| # def test_objecttype_inheritance(): | ||||
| #     class MyInheritedObjectType(ObjectType): | ||||
| #         inherited = Field(GraphQLString) | ||||
| 
 | ||||
| #     class MyObjectType(MyInheritedObjectType): | ||||
| #         field = Field(GraphQLString) | ||||
| 
 | ||||
| #     graphql_type = MyObjectType._meta.graphql_type | ||||
| #     fields = graphql_type.get_fields() | ||||
| #     assert 'field' in fields | ||||
| #     assert 'inherited' in fields | ||||
| #     assert fields['field'] > fields['inherited'] | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_as_container_only_args(): | ||||
| #     container = Container("1", "2") | ||||
| #     assert container.field1 == "1" | ||||
| #     assert container.field2 == "2" | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_as_container_args_kwargs(): | ||||
| #     container = Container("1", field2="2") | ||||
| #     assert container.field1 == "1" | ||||
| #     assert container.field2 == "2" | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_as_container_few_kwargs(): | ||||
| #     container = Container(field2="2") | ||||
| #     assert container.field2 == "2" | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_as_container_all_kwargs(): | ||||
| #     container = Container(field1="1", field2="2") | ||||
| #     assert container.field1 == "1" | ||||
| #     assert container.field2 == "2" | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_as_container_extra_args(): | ||||
| #     with pytest.raises(IndexError) as excinfo: | ||||
| #         Container("1", "2", "3") | ||||
| 
 | ||||
| #     assert "Number of args exceeds number of fields" == str(excinfo.value) | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_as_container_invalid_kwargs(): | ||||
| #     with pytest.raises(TypeError) as excinfo: | ||||
| #         Container(unexisting_field="3") | ||||
| 
 | ||||
| #     assert "'unexisting_field' is an invalid keyword argument for this function" == str(excinfo.value) | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_reuse_graphql_type(): | ||||
| #     MyGraphQLType = GraphQLObjectType('MyGraphQLType', fields={ | ||||
| #         'field': GraphQLField(GraphQLString) | ||||
| #     }) | ||||
| 
 | ||||
| #     class GrapheneObjectType(ObjectType): | ||||
| #         class Meta: | ||||
| #             graphql_type = MyGraphQLType | ||||
| 
 | ||||
| #     graphql_type = GrapheneObjectType._meta.graphql_type | ||||
| #     assert graphql_type == MyGraphQLType | ||||
| #     instance = GrapheneObjectType(field="A") | ||||
| #     assert instance.field == "A" | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_add_fields_in_reused_graphql_type(): | ||||
| #     MyGraphQLType = GraphQLObjectType('MyGraphQLType', fields={ | ||||
| #         'field': GraphQLField(GraphQLString) | ||||
| #     }) | ||||
| 
 | ||||
| #     with pytest.raises(AssertionError) as excinfo: | ||||
| #         class GrapheneObjectType(ObjectType): | ||||
| #             field = Field(GraphQLString) | ||||
| 
 | ||||
| #             class Meta: | ||||
| #                 graphql_type = MyGraphQLType | ||||
| 
 | ||||
| #     assert """Field "MyGraphQLType.field" can only be mounted in ObjectType or Interface, received GrapheneObjectType.""" == str(excinfo.value) | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_graphql_interface(): | ||||
| #     MyInterface = GraphQLInterfaceType('MyInterface', fields={ | ||||
| #         'field': GraphQLField(GraphQLString) | ||||
| #     }) | ||||
| 
 | ||||
| #     class GrapheneObjectType(ObjectType): | ||||
| #         class Meta: | ||||
| #             interfaces = [MyInterface] | ||||
| 
 | ||||
| #     graphql_type = GrapheneObjectType._meta.graphql_type | ||||
| #     assert graphql_type.get_interfaces() == (MyInterface, ) | ||||
| #     # assert graphql_type.is_type_of(MyInterface, None, None) | ||||
| #     fields = graphql_type.get_fields() | ||||
| #     assert 'field' in fields | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_graphene_interface(): | ||||
| #     class GrapheneInterface(Interface): | ||||
| #         field = Field(GraphQLString) | ||||
| 
 | ||||
| #     class GrapheneObjectType(ObjectType): | ||||
| #         class Meta: | ||||
| #             interfaces = [GrapheneInterface] | ||||
| 
 | ||||
| #     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 | ||||
| 
 | ||||
| 
 | ||||
| # def test_objecttype_graphene_interface_extended(): | ||||
| #     class GrapheneInterface(Interface): | ||||
| #         field = Field(GraphQLString) | ||||
| 
 | ||||
| #     class GrapheneObjectType(ObjectType): | ||||
| #         class Meta: | ||||
| #             interfaces = [GrapheneInterface] | ||||
| 
 | ||||
| #     schema = Schema(query=GrapheneObjectType) | ||||
| #     assert str(schema) == """ | ||||
| # schema { | ||||
| #   query: GrapheneObjectType | ||||
| # } | ||||
| 
 | ||||
| # interface GrapheneInterface { | ||||
| #   field: String | ||||
| # } | ||||
| 
 | ||||
| # type GrapheneObjectType implements GrapheneInterface { | ||||
| #   field: String | ||||
| # } | ||||
| # """.lstrip() | ||||
| #     GrapheneInterface._meta.graphql_type.add_field(Field(String, name='dynamic')) | ||||
| #     # GrapheneObjectType._meta.graphql_type._field_map = None | ||||
| #     assert GrapheneInterface._meta.graphql_type.get_fields().keys() == ['field', 'dynamic'] | ||||
| #     assert GrapheneObjectType._meta.graphql_type.get_fields().keys() == ['field', 'dynamic'] | ||||
| #     schema.rebuild() | ||||
| #     assert str(schema) == """ | ||||
| # schema { | ||||
| #   query: GrapheneObjectType | ||||
| # } | ||||
| 
 | ||||
| # interface GrapheneInterface { | ||||
| #   field: String | ||||
| #   dynamic: String | ||||
| # } | ||||
| 
 | ||||
| # type GrapheneObjectType implements GrapheneInterface { | ||||
| #   field: String | ||||
| #   dynamic: String | ||||
| # } | ||||
| # """.lstrip() | ||||
							
								
								
									
										15
									
								
								graphene/utils/props.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								graphene/utils/props.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| class _OldClass: | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| class _NewClass(object): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| _all_vars = set(dir(_OldClass) + dir(_NewClass)) | ||||
| 
 | ||||
| 
 | ||||
| def props(x): | ||||
|     return { | ||||
|         key: value for key, value in vars(x).items() if key not in _all_vars | ||||
|     } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user