diff --git a/graphene/new_types/mutation.py b/graphene/new_types/mutation.py new file mode 100644 index 00000000..d54740ec --- /dev/null +++ b/graphene/new_types/mutation.py @@ -0,0 +1,30 @@ +from functools import partial + +import six + +from ..utils.is_base_type import is_base_type +from ..utils.props import props +from .field import Field +from .objecttype import ObjectType, ObjectTypeMeta + + +class MutationMeta(ObjectTypeMeta): + + def __new__(cls, name, bases, attrs): + # Also ensure initialization is only performed for subclasses of + # Mutation + if not is_base_type(bases, MutationMeta): + return type.__new__(cls, name, bases, attrs) + + input_class = attrs.pop('Input', None) + + cls = ObjectTypeMeta.__new__(cls, name, bases, attrs) + field_args = props(input_class) if input_class else {} + resolver = getattr(cls, 'mutate', None) + assert resolver, 'All mutations must define a mutate method in it' + cls.Field = partial(Field, cls, args=field_args, resolver=resolver) + return cls + + +class Mutation(six.with_metaclass(MutationMeta, ObjectType)): + pass diff --git a/graphene/new_types/tests/test_mutation.py b/graphene/new_types/tests/test_mutation.py new file mode 100644 index 00000000..2b4a8859 --- /dev/null +++ b/graphene/new_types/tests/test_mutation.py @@ -0,0 +1,63 @@ +import pytest + +from ..field import Field +from ..mutation import Mutation +from ..objecttype import ObjectType +from ..scalars import String + + +def test_generate_mutation_no_args(): + class MyMutation(Mutation): + '''Documentation''' + @classmethod + def mutate(cls, *args, **kwargs): + pass + + assert issubclass(MyMutation, ObjectType) + assert MyMutation._meta.name == "MyMutation" + assert MyMutation._meta.description == "Documentation" + assert MyMutation.Field().resolver == MyMutation.mutate + + +# 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 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 == String + + +def test_generate_mutation_with_meta(): + class MyMutation(Mutation): + + class Meta: + name = 'MyOtherMutation' + description = 'Documentation' + + @classmethod + def mutate(cls, *args, **kwargs): + pass + + assert MyMutation._meta.name == "MyOtherMutation" + assert MyMutation._meta.description == "Documentation" + assert MyMutation.Field().resolver == MyMutation.mutate + + +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)