Skip to content

Commit 4a59135

Browse files
committed
Wrap or not wrap. Root is the question
1 parent 1795ed5 commit 4a59135

File tree

5 files changed

+50
-12
lines changed

5 files changed

+50
-12
lines changed

graphene/contrib/django/tests/test_types.py

+23-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from pytest import raises
12
from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType
23
from mock import patch
34

@@ -33,10 +34,11 @@ def test_django_interface():
3334
assert DjangoNode._meta.is_interface is True
3435

3536

36-
@patch('graphene.contrib.django.tests.models.Article.objects.filter')
37-
def test_django_get_node(objects):
38-
Human.get_node(1)
39-
objects.assert_called_with(id=1)
37+
@patch('graphene.contrib.django.tests.models.Article.objects.get', return_value=Article(id=1))
38+
def test_django_get_node(get):
39+
human = Human.get_node(1)
40+
get.assert_called_with(id=1)
41+
assert human.id == 1
4042

4143

4244
def test_pseudo_interface_registered():
@@ -67,10 +69,26 @@ def test_node_replacedfield():
6769

6870

6971
def test_interface_resolve_type():
70-
resolve_type = Character.resolve_type(schema, Human(object()))
72+
resolve_type = Character.resolve_type(schema, Human())
7173
assert isinstance(resolve_type, GraphQLObjectType)
7274

7375

76+
def test_interface_objecttype_init_none():
77+
h = Human()
78+
assert h._root is None
79+
80+
81+
def test_interface_objecttype_init_good():
82+
instance = Article()
83+
h = Human(instance)
84+
assert h._root == instance
85+
86+
87+
def test_interface_objecttype_init_unexpected():
88+
with raises(AssertionError) as excinfo:
89+
Human(object())
90+
assert str(excinfo.value) == "Human received a non-compatible instance (object) when expecting Article"
91+
7492
def test_object_type():
7593
object_type = schema.T(Human)
7694
Human._meta.fields_map

graphene/contrib/django/types.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,19 @@ def add_extra_fields(cls):
3838

3939
class InstanceObjectType(BaseObjectType):
4040

41-
def __init__(self, instance=None):
42-
self.instance = instance
43-
super(InstanceObjectType, self).__init__()
41+
def __init__(self, _root=None):
42+
if _root:
43+
assert isinstance(_root, self._meta.model), (
44+
'{} received a non-compatible instance ({}) '
45+
'when expecting {}'.format(
46+
self.__class__.__name__,
47+
_root.__class__.__name__,
48+
self._meta.model.__name__
49+
))
50+
super(InstanceObjectType, self).__init__(_root=_root)
4451

4552
def __getattr__(self, attr):
46-
return getattr(self.instance, attr)
53+
return getattr(self._root, attr)
4754

4855

4956
class DjangoObjectType(six.with_metaclass(
@@ -61,5 +68,8 @@ class DjangoNode(BaseNode, DjangoInterface):
6168

6269
@classmethod
6370
def get_node(cls, id):
64-
instance = cls._meta.model.objects.filter(id=id).first()
65-
return cls(instance)
71+
try:
72+
instance = cls._meta.model.objects.get(id=id)
73+
return cls(instance)
74+
except cls._meta.model.DoesNotExist:
75+
return None

graphene/core/schema.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def execute(self, request='', root=None, vars=None,
113113
return self.executor.execute(
114114
self.schema,
115115
request,
116-
root=self.query(root),
116+
root=root,
117117
args=vars,
118118
operation_name=operation_name,
119119
**kwargs

graphene/core/types/field.py

+9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from collections import OrderedDict
2+
from functools import wraps
23

34
import six
45
from graphql.core.type import GraphQLField, GraphQLInputObjectField
@@ -76,6 +77,14 @@ def internal_type(self, schema):
7677
assert len(arguments) == 0
7778
arguments = type_objecttype.get_arguments()
7879
resolver = getattr(type_objecttype, 'mutate')
80+
else:
81+
my_resolver = resolver
82+
@wraps(my_resolver)
83+
def wrapped_func(instance, args, info):
84+
if not isinstance(instance, self.object_type):
85+
instance = self.object_type(_root=instance)
86+
return my_resolver(instance, args, info)
87+
resolver = wrapped_func
7988

8089
resolver = snake_case_args(resolver)
8190
assert type, 'Internal type for field %s is None' % str(self)

graphene/core/types/objecttype.py

+1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ def __new__(cls, *args, **kwargs):
144144

145145
def __init__(self, *args, **kwargs):
146146
signals.pre_init.send(self.__class__, args=args, kwargs=kwargs)
147+
self._root = kwargs.pop('_root', None)
147148
args_len = len(args)
148149
fields = self._meta.fields
149150
if args_len > len(fields):

0 commit comments

Comments
 (0)