From ac416b6ab023b3570cb542b151b5683b384ab6d7 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Tue, 14 Jun 2016 22:04:57 -0700 Subject: [PATCH] Improved ClientIdMutation --- graphene/relay/mutation.py | 61 +++++++++++++++++------------- graphene/types/mutation.py | 14 ++----- graphene/utils/is_graphene_type.py | 3 +- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/graphene/relay/mutation.py b/graphene/relay/mutation.py index eccfce93..ee9128dd 100644 --- a/graphene/relay/mutation.py +++ b/graphene/relay/mutation.py @@ -10,39 +10,48 @@ from ..utils.copy_fields import copy_fields from ..utils.props import props +from ..types.objecttype import ObjectType + +from ..utils.is_base_type import is_base_type +from ..types.options import Options + + class ClientIDMutationMeta(MutationMeta): - _construct_field = False - def get_options(cls, meta): - options = cls.options_class( - meta, + def __new__(cls, name, bases, attrs): + super_new = type.__new__ + + # Also ensure initialization is only performed for subclasses of Model + # (excluding Model class itself). + if not is_base_type(bases, ClientIDMutationMeta): + return super_new(cls, name, bases, attrs) + + options = Options( + attrs.pop('Meta', None), name=None, - abstract=False + description=None, ) - options.graphql_type = None - options.interfaces = [] - return options - def construct(cls, bases, attrs): - if not cls._meta.abstract: - Input = attrs.pop('Input', None) - input_fields = props(Input) if Input else {} + Input = attrs.pop('Input', None) - cls.mutate_and_get_payload = attrs.pop('mutate_and_get_payload', None) + cls = super_new(cls, name, bases, dict(attrs, _meta=options)) - input_local_fields = copy_fields(InputField, get_fields(InputObjectType, input_fields, ())) - local_fields = cls._extract_local_fields(attrs) - assert cls.mutate_and_get_payload, "{}.mutate_and_get_payload method is required in a ClientIDMutation ObjectType.".format(cls.__name__) - field = mutation_with_client_mutation_id( - name=cls._meta.name or cls.__name__, - input_fields=input_local_fields, - output_fields=cls._fields(bases, attrs, local_fields), - mutate_and_get_payload=cls.mutate_and_get_payload, - ) - cls._meta.graphql_type = field.type - cls.Field = partial(Field.copy_and_extend, field, type=field.type, _creation_counter=None) - constructed = super(ClientIDMutationMeta, cls).construct(bases, attrs) - return constructed + input_fields = props(Input) if Input else {} + input_local_fields = copy_fields(InputField, get_fields(InputObjectType, input_fields, ())) + output_fields = copy_fields(Field, get_fields(ObjectType, attrs, bases)) + + mutate_and_get_payload = getattr(cls, 'mutate_and_get_payload', None) + assert mutate_and_get_payload, "{}.mutate_and_get_payload method is required in a ClientIDMutation ObjectType.".format(cls.__name__) + + field = mutation_with_client_mutation_id( + name=options.name or cls.__name__, + input_fields=input_local_fields, + output_fields=output_fields, + mutate_and_get_payload=cls.mutate_and_get_payload, + ) + options.graphql_type = field.type + cls.Field = partial(Field.copy_and_extend, field, type=field.type, _creation_counter=None) + return cls class ClientIDMutation(six.with_metaclass(ClientIDMutationMeta, Mutation)): diff --git a/graphene/types/mutation.py b/graphene/types/mutation.py index 5266ef1c..8a1fd0dc 100644 --- a/graphene/types/mutation.py +++ b/graphene/types/mutation.py @@ -10,13 +10,6 @@ from ..utils.is_base_type import is_base_type class MutationMeta(ObjectTypeMeta): - _construct_field = True - - def construct_field(cls, field_args): - resolver = getattr(cls, 'mutate', None) - assert resolver, 'All mutations must define a mutate method in it' - return partial(Field, cls, args=field_args, resolver=resolver) - def __new__(cls, name, bases, attrs): super_new = super(MutationMeta, cls).__new__ @@ -28,9 +21,10 @@ class MutationMeta(ObjectTypeMeta): Input = attrs.pop('Input', None) cls = super_new(cls, name, bases, attrs) - if cls._construct_field: - field_args = props(Input) if Input else {} - cls.Field = cls.construct_field(field_args) + field_args = props(Input) if Input 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 diff --git a/graphene/utils/is_graphene_type.py b/graphene/utils/is_graphene_type.py index d252fa44..c9b8e1cf 100644 --- a/graphene/utils/is_graphene_type.py +++ b/graphene/utils/is_graphene_type.py @@ -8,8 +8,9 @@ def is_graphene_type(_type): from ..types.interface import Interface from ..types.scalars import Scalar from ..types.enum import Enum + from ..relay.mutation import ClientIDMutation - if _type in [Interface, InputObjectType, ObjectType, Mutation]: + if _type in [Interface, InputObjectType, ObjectType, Mutation, ClientIDMutation]: return False return inspect.isclass(_type) and issubclass(_type, ( Interface,