Fixed relay ClientIDMutation

This commit is contained in:
Syrus Akbary 2017-07-12 01:36:44 -07:00
parent 4820a7fede
commit 7a6d741531
6 changed files with 67 additions and 56 deletions

View File

@ -10,9 +10,7 @@ from promise import Promise, is_thenable
from ..types import (AbstractType, Boolean, Enum, Int, Interface, List, NonNull, Scalar, String, from ..types import (AbstractType, Boolean, Enum, Int, Interface, List, NonNull, Scalar, String,
Union) Union)
from ..types.field import Field from ..types.field import Field
from ..types.objecttype import ObjectType, ObjectTypeMeta from ..types.objecttype import ObjectType
from ..types.options import Options
from ..utils.is_base_type import is_base_type
from ..utils.props import props from ..utils.props import props
from .node import is_node from .node import is_node
@ -41,7 +39,7 @@ class PageInfo(ObjectType):
) )
class ConnectionMeta(ObjectTypeMeta): class ConnectionMeta(type):
def __new__(cls, name, bases, attrs): def __new__(cls, name, bases, attrs):
# Also ensure initialization is only performed for subclasses of Model # Also ensure initialization is only performed for subclasses of Model
@ -89,7 +87,7 @@ class ConnectionMeta(ObjectTypeMeta):
return ObjectTypeMeta.__new__(cls, name, bases, attrs) return ObjectTypeMeta.__new__(cls, name, bases, attrs)
class Connection(six.with_metaclass(ConnectionMeta, ObjectType)): class Connection(ObjectType):
pass pass

View File

@ -1,56 +1,53 @@
import re import re
from functools import partial from collections import OrderedDict
import six
from promise import Promise from promise import Promise
from ..types import Field, AbstractType, Argument, InputObjectType, String from ..types import Field, AbstractType, Argument, InputObjectType, String, Field
from ..types.mutation import Mutation, MutationMeta from ..types.mutation import Mutation, MutationOptions
from ..types.objecttype import ObjectTypeMeta
from ..utils.is_base_type import is_base_type
from ..utils.props import props from ..utils.props import props
class ClientIDMutationMeta(MutationMeta): class ClientIDMutation(Mutation):
def __new__(cls, name, bases, attrs): class Meta:
# Also ensure initialization is only performed for subclasses of abstract = True
# Mutation
if not is_base_type(bases, ClientIDMutationMeta):
return type.__new__(cls, name, bases, attrs)
input_class = attrs.pop('Input', None) @classmethod
def __init_subclass_with_meta__(cls, output=None, arguments=None, name=None, **options):
input_class = getattr(cls, 'Input', None)
name = name or cls.__name__
base_name = re.sub('Payload$', '', name) base_name = re.sub('Payload$', '', name)
if 'client_mutation_id' not in attrs:
attrs['client_mutation_id'] = String(name='clientMutationId') assert not output, "Can't specify any output"
cls = ObjectTypeMeta.__new__(cls, '{}Payload'.format(base_name), bases, assert not arguments, "Can't specify any arguments"
attrs)
bases = (InputObjectType, )
if input_class:
bases += (input_class, )
cls.Input = type('{}Input'.format(base_name),
bases, {
'client_mutation_id': String(name='clientMutationId')
})
arguments = OrderedDict(
input=cls.Input(required=True)
# 'client_mutation_id': String(name='clientMutationId')
)
mutate_and_get_payload = getattr(cls, 'mutate_and_get_payload', None) mutate_and_get_payload = getattr(cls, 'mutate_and_get_payload', None)
if cls.mutate and cls.mutate.__func__ == ClientIDMutation.mutate.__func__: if cls.mutate and cls.mutate.__func__ == ClientIDMutation.mutate.__func__:
assert mutate_and_get_payload, ( assert mutate_and_get_payload, (
"{}.mutate_and_get_payload method is required" "{name}.mutate_and_get_payload method is required"
" in a ClientIDMutation.").format(name) " in a ClientIDMutation.").format(name=name)
input_attrs = {}
bases = () if not name:
if not input_class: name = '{}Payload'.format(base_name)
input_attrs = {}
elif not issubclass(input_class, AbstractType):
input_attrs = props(input_class)
else:
bases += (input_class, )
input_attrs['client_mutation_id'] = String(name='clientMutationId')
cls.Input = type('{}Input'.format(base_name),
bases + (InputObjectType, ), input_attrs)
output_class = getattr(cls, 'Output', cls)
cls.Field = partial(
Field,
output_class,
resolver=cls.mutate,
input=Argument(cls.Input, required=True))
return cls
super(ClientIDMutation, cls).__init_subclass_with_meta__(output=None, arguments=arguments, name=name, **options)
cls._meta.fields['client_mutation_id'] = (
Field(String, name='clientMutationId')
)
class ClientIDMutation(six.with_metaclass(ClientIDMutationMeta, Mutation)):
@classmethod @classmethod
def mutate(cls, root, args, context, info): def mutate(cls, root, args, context, info):
input = args.get('input') input = args.get('input')

View File

@ -1,6 +1,6 @@
import pytest import pytest
from ...types import (AbstractType, Argument, Field, InputField, from ...types import ( Argument, Field, InputField, ID,
InputObjectType, NonNull, ObjectType, Schema) InputObjectType, NonNull, ObjectType, Schema)
from ...types.scalars import String from ...types.scalars import String
from ..mutation import ClientIDMutation from ..mutation import ClientIDMutation
@ -8,14 +8,14 @@ from ..node import Node
from promise import Promise from promise import Promise
class SharedFields(AbstractType): class SharedFields(object):
shared = String() shared = String()
class MyNode(ObjectType): class MyNode(ObjectType):
class Meta: # class Meta:
interfaces = (Node, ) # interfaces = (Node, )
id = ID()
name = String() name = String()
@ -43,18 +43,24 @@ class SaySomethingPromise(ClientIDMutation):
return Promise.resolve(SaySomething(phrase=str(what))) return Promise.resolve(SaySomething(phrase=str(what)))
# MyEdge = MyNode.Connection.Edge
class MyEdge(ObjectType):
node = Field(MyNode)
cursor = String()
class OtherMutation(ClientIDMutation): class OtherMutation(ClientIDMutation):
class Input(SharedFields): class Input(SharedFields):
additional_field = String() additional_field = String()
name = String() name = String()
my_node_edge = Field(MyNode.Connection.Edge) my_node_edge = Field(MyEdge)
@classmethod @classmethod
def mutate_and_get_payload(cls, args, context, info): def mutate_and_get_payload(cls, args, context, info):
shared = args.get('shared', '') shared = args.get('shared', '')
additionalField = args.get('additionalField', '') additionalField = args.get('additionalField', '')
edge_type = MyNode.Connection.Edge edge_type = MyEdge
return OtherMutation( return OtherMutation(
name=shared + additionalField, name=shared + additionalField,
my_node_edge=edge_type(cursor='1', node=MyNode(name='name'))) my_node_edge=edge_type(cursor='1', node=MyNode(name='name')))

View File

@ -6,4 +6,4 @@ class AbstractType(object):
def __init_subclass__(cls, *args, **kwargs): def __init_subclass__(cls, *args, **kwargs):
print("Abstract type is deprecated") print("Abstract type is deprecated")
super(AbstractType, cls).__init_subclass__(*args, **kwargs) # super(AbstractType, cls).__init_subclass__(*args, **kwargs)

View File

@ -20,8 +20,11 @@ class Mutation(ObjectType):
Mutation Type Definition Mutation Type Definition
''' '''
@classmethod @classmethod
def __init_subclass_with_meta__(cls, resolver=None, output=None, arguments=None, **options): def __init_subclass_with_meta__(cls, resolver=None, output=None, arguments=None, _meta=None, abstract=False, **options):
_meta = MutationOptions(cls) if abstract:
return
if not _meta:
_meta = MutationOptions(cls)
output = output or getattr(cls, 'Output', None) output = output or getattr(cls, 'Output', None)
fields = {} fields = {}
@ -51,7 +54,11 @@ class Mutation(ObjectType):
assert mutate, 'All mutations must define a mutate method in it' assert mutate, 'All mutations must define a mutate method in it'
resolver = get_unbound_function(mutate) resolver = get_unbound_function(mutate)
_meta.fields = fields if _meta.fields:
_meta.fields.update(fields)
else:
_meta.fields = fields
_meta.output = output _meta.output = output
_meta.resolver = resolver _meta.resolver = resolver
_meta.arguments = arguments _meta.arguments = arguments

View File

@ -42,7 +42,10 @@ class ObjectType(BaseType):
'Please use one or other.' 'Please use one or other.'
).format(name=cls.__name__) ).format(name=cls.__name__)
_meta.fields = fields if _meta.fields:
_meta.fields.update(fields)
else:
_meta.fields = fields
_meta.interfaces = interfaces _meta.interfaces = interfaces
_meta.possible_types = possible_types _meta.possible_types = possible_types
_meta.default_resolver = default_resolver _meta.default_resolver = default_resolver