diff --git a/graphene/types/tests/test_mutation.py b/graphene/types/tests/test_mutation.py index 2af6f4fd..d60f4950 100644 --- a/graphene/types/tests/test_mutation.py +++ b/graphene/types/tests/test_mutation.py @@ -44,15 +44,30 @@ def test_mutation_raises_exception_if_no_mutate(): def test_mutation_execution(): + def with_metadata(gql_type, data): + setattr(gql_type, 'metadata', data) + return gql_type + class CreateUser(Mutation): class Input: name = String() + metadata = with_metadata(String(), 'service_key') + + _Input = Input name = String() + external = String() - def mutate(self, args, context, info): + @classmethod + def mutate(cls, root, args, context, info): name = args.get('name') - return CreateUser(name=name) + external_data = { + 'service_key': 'new_data' + } + + metadata_type = dict(vars(cls._Input))['metadata'] + data = external_data[getattr(metadata_type, 'metadata')] + return CreateUser(name=name, external=data) class Query(ObjectType): a = String() @@ -64,12 +79,14 @@ def test_mutation_execution(): result = schema.execute(''' mutation mymutation { createUser(name:"Peter") { name + external } } ''') assert not result.errors assert result.data == { 'createUser': { - 'name': "Peter" + 'name': 'Peter', + 'external': 'new_data', } } diff --git a/graphene/types/tests/test_query.py b/graphene/types/tests/test_query.py index 4f9d8810..742f3c19 100644 --- a/graphene/types/tests/test_query.py +++ b/graphene/types/tests/test_query.py @@ -56,6 +56,36 @@ def test_query_wrong_default_value(): assert executed.data == {'hello': None} +def test_query_unmounted_type_with_custom_attributes(): + def set_custom_metadata(gql_type): + setattr(gql_type, 'metadata', 'some_key') + return gql_type + + class MyType(ObjectType): + field = set_custom_metadata(String()) + + @classmethod + def from_metadata(cls): + my_type = cls() + external_data = { + 'some_key': 'my_data' + } + for field_name, field_value in cls._meta.fields.items(): + data = external_data[getattr(field_value, 'metadata')] + setattr(my_type, field_name, data) + + return my_type + + class Query(ObjectType): + hello = Field(MyType, resolver=lambda *_: MyType.from_metadata()) + + hello_schema = Schema(Query) + + executed = hello_schema.execute('{ hello { field } }') + assert not executed.errors + assert executed.data == {'hello': {'field': 'my_data'}} + + def test_query_default_value_ignored_by_resolver(): class MyType(ObjectType): field = String() diff --git a/graphene/types/unmountedtype.py b/graphene/types/unmountedtype.py index c9b36631..d3e5c98a 100644 --- a/graphene/types/unmountedtype.py +++ b/graphene/types/unmountedtype.py @@ -19,34 +19,52 @@ class UnmountedType(OrderedType): super(UnmountedType, self).__init__() self.args = args self.kwargs = kwargs + self.custom_attributes = {} def get_type(self): raise NotImplementedError("get_type not implemented in {}".format(self)) + def __setattr__(self, name, value): + if hasattr(self, 'custom_attributes'): + self.custom_attributes[name] = value + OrderedType.__setattr__(self, name, value) + def Field(self): # noqa: N802 ''' Mount the UnmountedType as Field ''' from .field import Field - return Field( + f = Field( self.get_type(), *self.args, _creation_counter=self.creation_counter, **self.kwargs ) + if hasattr(self, 'custom_attributes'): + for name, value in self.custom_attributes.items(): + setattr(f, name, value) + + return f + def InputField(self): # noqa: N802 ''' Mount the UnmountedType as InputField ''' from .inputfield import InputField - return InputField( + f = InputField( self.get_type(), *self.args, _creation_counter=self.creation_counter, **self.kwargs ) + if hasattr(self, 'custom_attributes'): + for name, value in self.custom_attributes.items(): + setattr(f, name, value) + + return f + def Argument(self): # noqa: N802 ''' Mount the UnmountedType as Argument