Skip to content

Commit 61ffcc3

Browse files
committed
Improved use cases and tests
1 parent dd50783 commit 61ffcc3

File tree

8 files changed

+1097
-15
lines changed

8 files changed

+1097
-15
lines changed

graphql/execution/querybuilder/executor.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ def is_promise(obj):
2929

3030
def execute(schema, document_ast, root_value=None, context_value=None,
3131
variable_values=None, operation_name=None, executor=None,
32-
return_promise=False, middlewares=None):
32+
return_promise=False, middleware=None):
3333
assert schema, 'Must provide schema'
3434
assert isinstance(schema, GraphQLSchema), (
3535
'Schema must be an instance of GraphQLSchema. Also ensure that there are ' +
3636
'not multiple versions of GraphQL installed in your node_modules directory.'
3737
)
38-
if middlewares:
39-
assert isinstance(middlewares, MiddlewareManager), (
38+
if middleware:
39+
assert isinstance(middleware, MiddlewareManager), (
4040
'middlewares have to be an instance'
41-
' of MiddlewareManager. Received "{}".'.format(middlewares)
41+
' of MiddlewareManager. Received "{}".'.format(middleware)
4242
)
4343

4444
if executor is None:
@@ -52,7 +52,7 @@ def execute(schema, document_ast, root_value=None, context_value=None,
5252
variable_values,
5353
operation_name,
5454
executor,
55-
middlewares
55+
middleware
5656
)
5757

5858
def executor(resolve, reject):

graphql/execution/querybuilder/fragment.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from functools import partial
44
from ...pyutils.cached_property import cached_property
55
from ..values import get_argument_values, get_variable_values
6-
from ..base import collect_fields, ResolveInfo, Undefined
6+
from ..base import collect_fields, ResolveInfo, Undefined, get_field_def
77
from ..executor import is_promise
88

99
from ...pyutils.ordereddict import OrderedDict
@@ -33,7 +33,9 @@ def get_resolvers(context, type, selection_set):
3333
for response_name, field_asts in subfield_asts.items():
3434
field_ast = field_asts[0]
3535
field_name = field_ast.name.value
36-
field_def = type.fields[field_name]
36+
field_def = get_field_def(context and context.schema, type, field_name)
37+
if not field_def:
38+
continue
3739
field_base_type = get_base_type(field_def.type)
3840
field_fragment = None
3941
info = ResolveInfo(
@@ -89,7 +91,10 @@ def resolve(self, root):
8991
contains_promise = False
9092

9193
final_results = OrderedDict()
92-
94+
# return OrderedDict(
95+
# ((field_name, field_resolver(root, field_args, context, info))
96+
# for field_name, field_resolver, field_args, context, info in self.partial_resolvers)
97+
# )
9398
for response_name, field_resolver, field_args, context, info in self.partial_resolvers:
9499
result = field_resolver(root, field_args, context, info)
95100
if result is Undefined:
@@ -141,7 +146,7 @@ def resolve_type(self, result):
141146
context = self.context.context_value
142147

143148
if return_type.resolve_type:
144-
runtime_type = return_type.resolve_type(result, context, self.info)
149+
return return_type.resolve_type(result, context, self.info)
145150
else:
146151
for type in self.possible_types:
147152
if callable(type.is_type_of) and type.is_type_of(result, context, self.info):

graphql/execution/querybuilder/resolver.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,10 @@ def type_resolver(return_type, resolver, fragment=None, exe_context=None, info=N
8787
if isinstance(return_type, (GraphQLObjectType)):
8888
assert fragment and fragment.type == return_type, 'Fragment and return_type dont match'
8989
return type_resolver_type(return_type, resolver, fragment, exe_context, info, catch_error)
90-
# complete_object_value_resolve = partial(complete_object_value, fragment.resolve)
91-
# return partial(on_complete_resolver, complete_object_value_resolve, exe_context, info, resolver)
92-
# return partial(fragment.resolver, resolver)
9390

9491
if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)):
9592
assert fragment, 'You need to pass a fragment to resolve a Interface or Union'
9693
return type_resolver_type(return_type, resolver, fragment, exe_context, info, catch_error)
97-
# return partial(on_complete_resolver, fragment.resolve, exe_context, info, resolver)
98-
# return partial(fragment.resolver, resolver)
99-
# return partial(fragment.abstract_resolver, resolver, return_type)
10094

10195
raise Exception("The resolver have to be created for a fragment")
10296

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
from graphql import graphql
2+
from graphql.type import GraphQLBoolean, GraphQLSchema, GraphQLString
3+
from graphql.type.definition import (GraphQLField, GraphQLInterfaceType,
4+
GraphQLList, GraphQLObjectType,
5+
GraphQLUnionType)
6+
7+
8+
class Dog(object):
9+
10+
def __init__(self, name, woofs):
11+
self.name = name
12+
self.woofs = woofs
13+
14+
15+
class Cat(object):
16+
17+
def __init__(self, name, meows):
18+
self.name = name
19+
self.meows = meows
20+
21+
22+
class Human(object):
23+
24+
def __init__(self, name):
25+
self.name = name
26+
27+
28+
is_type_of = lambda type: lambda obj, context, info: isinstance(obj, type)
29+
30+
31+
def make_type_resolver(types):
32+
def resolve_type(obj, context, info):
33+
if callable(types):
34+
t = types()
35+
else:
36+
t = types
37+
38+
for klass, type in t:
39+
if isinstance(obj, klass):
40+
return type
41+
42+
return None
43+
44+
return resolve_type
45+
46+
47+
def test_is_type_of_used_to_resolve_runtime_type_for_interface():
48+
PetType = GraphQLInterfaceType(
49+
name='Pet',
50+
fields={
51+
'name': GraphQLField(GraphQLString)
52+
}
53+
)
54+
55+
DogType = GraphQLObjectType(
56+
name='Dog',
57+
interfaces=[PetType],
58+
is_type_of=is_type_of(Dog),
59+
fields={
60+
'name': GraphQLField(GraphQLString),
61+
'woofs': GraphQLField(GraphQLBoolean)
62+
}
63+
)
64+
65+
CatType = GraphQLObjectType(
66+
name='Cat',
67+
interfaces=[PetType],
68+
is_type_of=is_type_of(Cat),
69+
fields={
70+
'name': GraphQLField(GraphQLString),
71+
'meows': GraphQLField(GraphQLBoolean)
72+
}
73+
)
74+
75+
schema = GraphQLSchema(
76+
query=GraphQLObjectType(
77+
name='Query',
78+
fields={
79+
'pets': GraphQLField(
80+
GraphQLList(PetType),
81+
resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False)]
82+
)
83+
}
84+
),
85+
types=[CatType, DogType]
86+
)
87+
88+
query = '''
89+
{
90+
pets {
91+
name
92+
... on Dog {
93+
woofs
94+
}
95+
... on Cat {
96+
meows
97+
}
98+
}
99+
}
100+
'''
101+
102+
result = graphql(schema, query)
103+
assert not result.errors
104+
assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}]}
105+
106+
107+
def test_is_type_of_used_to_resolve_runtime_type_for_union():
108+
DogType = GraphQLObjectType(
109+
name='Dog',
110+
is_type_of=is_type_of(Dog),
111+
fields={
112+
'name': GraphQLField(GraphQLString),
113+
'woofs': GraphQLField(GraphQLBoolean)
114+
}
115+
)
116+
117+
CatType = GraphQLObjectType(
118+
name='Cat',
119+
is_type_of=is_type_of(Cat),
120+
fields={
121+
'name': GraphQLField(GraphQLString),
122+
'meows': GraphQLField(GraphQLBoolean)
123+
}
124+
)
125+
126+
PetType = GraphQLUnionType(
127+
name='Pet',
128+
types=[CatType, DogType]
129+
)
130+
131+
schema = GraphQLSchema(
132+
query=GraphQLObjectType(
133+
name='Query',
134+
fields={
135+
'pets': GraphQLField(
136+
GraphQLList(PetType),
137+
resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False)]
138+
)
139+
}
140+
),
141+
types=[CatType, DogType]
142+
)
143+
144+
query = '''
145+
{
146+
pets {
147+
... on Dog {
148+
name
149+
woofs
150+
}
151+
... on Cat {
152+
name
153+
meows
154+
}
155+
}
156+
}
157+
'''
158+
159+
result = graphql(schema, query)
160+
assert not result.errors
161+
assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}]}
162+
163+
164+
def test_resolve_type_on_interface_yields_useful_error():
165+
PetType = GraphQLInterfaceType(
166+
name='Pet',
167+
fields={
168+
'name': GraphQLField(GraphQLString)
169+
},
170+
resolve_type=make_type_resolver(lambda: [
171+
(Dog, DogType),
172+
(Cat, CatType),
173+
(Human, HumanType)
174+
])
175+
)
176+
177+
DogType = GraphQLObjectType(
178+
name='Dog',
179+
interfaces=[PetType],
180+
fields={
181+
'name': GraphQLField(GraphQLString),
182+
'woofs': GraphQLField(GraphQLBoolean)
183+
}
184+
)
185+
186+
HumanType = GraphQLObjectType(
187+
name='Human',
188+
fields={
189+
'name': GraphQLField(GraphQLString),
190+
}
191+
)
192+
193+
CatType = GraphQLObjectType(
194+
name='Cat',
195+
interfaces=[PetType],
196+
fields={
197+
'name': GraphQLField(GraphQLString),
198+
'meows': GraphQLField(GraphQLBoolean)
199+
}
200+
)
201+
202+
schema = GraphQLSchema(
203+
query=GraphQLObjectType(
204+
name='Query',
205+
fields={
206+
'pets': GraphQLField(
207+
GraphQLList(PetType),
208+
resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False), Human('Jon')]
209+
)
210+
}
211+
),
212+
types=[DogType, CatType]
213+
)
214+
215+
query = '''
216+
{
217+
pets {
218+
name
219+
... on Dog {
220+
woofs
221+
}
222+
... on Cat {
223+
meows
224+
}
225+
}
226+
}
227+
'''
228+
229+
result = graphql(schema, query)
230+
assert result.errors[0].message == 'Runtime Object type "Human" is not a possible type for "Pet".'
231+
assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}, None]}
232+
233+
234+
def test_resolve_type_on_union_yields_useful_error():
235+
DogType = GraphQLObjectType(
236+
name='Dog',
237+
fields={
238+
'name': GraphQLField(GraphQLString),
239+
'woofs': GraphQLField(GraphQLBoolean)
240+
}
241+
)
242+
243+
HumanType = GraphQLObjectType(
244+
name='Human',
245+
fields={
246+
'name': GraphQLField(GraphQLString),
247+
}
248+
)
249+
250+
CatType = GraphQLObjectType(
251+
name='Cat',
252+
fields={
253+
'name': GraphQLField(GraphQLString),
254+
'meows': GraphQLField(GraphQLBoolean)
255+
}
256+
)
257+
258+
PetType = GraphQLUnionType(
259+
name='Pet',
260+
types=[DogType, CatType],
261+
resolve_type=make_type_resolver(lambda: [
262+
(Dog, DogType),
263+
(Cat, CatType),
264+
(Human, HumanType)
265+
])
266+
)
267+
268+
schema = GraphQLSchema(
269+
query=GraphQLObjectType(
270+
name='Query',
271+
fields={
272+
'pets': GraphQLField(
273+
GraphQLList(PetType),
274+
resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False), Human('Jon')]
275+
)
276+
}
277+
)
278+
)
279+
280+
query = '''
281+
{
282+
pets {
283+
... on Dog {
284+
name
285+
woofs
286+
}
287+
... on Cat {
288+
name
289+
meows
290+
}
291+
}
292+
}
293+
'''
294+
295+
result = graphql(schema, query)
296+
assert result.errors[0].message == 'Runtime Object type "Human" is not a possible type for "Pet".'
297+
assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}, None]}

0 commit comments

Comments
 (0)