From 8030fea44318b9dfcda854c96dfa5091b266f95e Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 29 Sep 2016 01:38:56 -0700 Subject: [PATCH] Fixed flexible resolving in return type --- graphene/types/interface.py | 6 +++++- graphene/types/objecttype.py | 5 +---- graphene/types/tests/test_query.py | 28 ++++++++++++++++++++++++++++ graphene/types/typemap.py | 8 ++++++-- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/graphene/types/interface.py b/graphene/types/interface.py index f5a2d61a..cc8361e6 100644 --- a/graphene/types/interface.py +++ b/graphene/types/interface.py @@ -48,7 +48,11 @@ class Interface(six.with_metaclass(InterfaceMeta)): when the field is resolved. ''' - resolve_type = None + @classmethod + def resolve_type(cls, instance, context, info): + from .objecttype import ObjectType + if isinstance(instance, ObjectType): + return type(instance) def __init__(self, *args, **kwargs): raise Exception("An Interface cannot be intitialized") diff --git a/graphene/types/objecttype.py b/graphene/types/objecttype.py index ca3f6b0c..f06dbf5e 100644 --- a/graphene/types/objecttype.py +++ b/graphene/types/objecttype.py @@ -63,10 +63,7 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta)): have a name, but most importantly describe their fields. ''' - @classmethod - def is_type_of(cls, root, context, info): - if isinstance(root, cls): - return True + is_type_of = None def __init__(self, *args, **kwargs): # ObjectType acting as container diff --git a/graphene/types/tests/test_query.py b/graphene/types/tests/test_query.py index 1f09b925..4f9d8810 100644 --- a/graphene/types/tests/test_query.py +++ b/graphene/types/tests/test_query.py @@ -41,6 +41,10 @@ def test_query_wrong_default_value(): class MyType(ObjectType): field = String() + @classmethod + def is_type_of(cls, root, context, info): + return isinstance(root, MyType) + class Query(ObjectType): hello = Field(MyType, default_value='hello') @@ -153,6 +157,30 @@ def test_query_middlewares(): assert executed.data == {'hello': 'dlroW', 'other': 'rehto'} +def test_objecttype_on_instances(): + class Ship: + def __init__(self, name): + self.name = name + + class ShipType(ObjectType): + name = String(description="Ship name", required=True) + + def resolve_name(self, context, args, info): + # Here self will be the Ship instance returned in resolve_ship + return self.name + + class Query(ObjectType): + ship = Field(ShipType) + + def resolve_ship(self, context, args, info): + return Ship(name='xwing') + + schema = Schema(query=Query) + executed = schema.execute('{ ship { name } }') + assert not executed.errors + assert executed.data == {'ship': {'name': 'xwing'}} + + def test_big_list_query_benchmark(benchmark): big_list = range(10000) diff --git a/graphene/types/typemap.py b/graphene/types/typemap.py index ed036d6c..ecaedf75 100644 --- a/graphene/types/typemap.py +++ b/graphene/types/typemap.py @@ -6,6 +6,7 @@ from graphql import (GraphQLArgument, GraphQLBoolean, GraphQLField, GraphQLFloat, GraphQLID, GraphQLInputObjectField, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLString) from graphql.type import GraphQLEnumValue +from graphql.execution.executor import get_default_resolve_type_fn from graphql.type.typemap import GraphQLTypeMap from ..utils.str_converters import to_camel_case @@ -26,11 +27,14 @@ def is_graphene_type(_type): return True -def resolve_type(resolve_type_func, map, root, args, info): - _type = resolve_type_func(root, args, info) +def resolve_type(resolve_type_func, map, root, context, info): + _type = resolve_type_func(root, context, info) # assert inspect.isclass(_type) and issubclass(_type, ObjectType), ( # 'Received incompatible type "{}".'.format(_type) # ) + if not _type: + return get_default_resolve_type_fn(root, context, info, info.return_type) + if inspect.isclass(_type) and issubclass(_type, ObjectType): graphql_type = map.get(_type._meta.name) assert graphql_type and graphql_type.graphene_type == _type