Skip to content

Commit e54543d

Browse files
committed
Merge pull request #58 from mixcloud/from-js4
Porting various commits for 0.5.0
2 parents 5158a16 + 968d605 commit e54543d

File tree

1 file changed

+63
-33
lines changed

1 file changed

+63
-33
lines changed

graphql/execution/executor.py

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ def complete_value(self, ctx, return_type, field_asts, info, result):
214214
If the field type is a Scalar or Enum, ensures the completed value is a legal value of the type by calling the
215215
`serialize` method of GraphQL type definition.
216216
217+
If the field is an abstract type, determine the runtime type of the value and then complete based on that type.
218+
217219
Otherwise, the field type expects a sub-selection set, and will complete the value by evaluating all
218220
sub-selections.
219221
"""
@@ -251,49 +253,56 @@ def complete_value(self, ctx, return_type, field_asts, info, result):
251253

252254
# If field type is List, complete each item in the list with the inner type
253255
if isinstance(return_type, GraphQLList):
254-
assert isinstance(result, collections.Iterable), \
255-
('User Error: expected iterable, but did not find one' +
256-
'for field {}.{}').format(info.parent_type, info.field_name)
256+
return self.complete_list_value(ctx, return_type, field_asts, info, result)
257257

258-
item_type = return_type.of_type
259-
completed_results = []
260-
contains_deferred = False
261-
for item in result:
262-
completed_item = self.complete_value_catching_error(ctx, item_type, field_asts, info, item)
263-
if not contains_deferred and isinstance(completed_item, Deferred):
264-
contains_deferred = True
258+
# If field type is Scalar or Enum, serialize to a valid value, returning null if coercion is not possible.
259+
if isinstance(return_type, (GraphQLScalarType, GraphQLEnumType)):
260+
return self.complete_leaf_value(ctx, return_type, field_asts, info, result)
265261

266-
completed_results.append(completed_item)
262+
if isinstance(return_type, GraphQLObjectType):
263+
return self.complete_object_value(ctx, return_type, field_asts, info, result)
267264

268-
return DeferredList(completed_results) if contains_deferred else completed_results
265+
if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)):
266+
return self.complete_abstract_value(ctx, return_type, field_asts, info, result)
269267

270-
# If field type is Scalar or Enum, serialize to a valid value, returning null if coercion is not possible.
271-
if isinstance(return_type, (GraphQLScalarType, GraphQLEnumType)):
272-
serialized_result = return_type.serialize(result)
268+
assert False, u'Cannot complete value of unexpected type "{}"'.format(return_type)
273269

274-
if serialized_result is None:
275-
return None
270+
def complete_list_value(self, ctx, return_type, field_asts, info, result):
271+
"""
272+
Complete a list value by completing each item in the list with the inner type
273+
"""
274+
assert isinstance(result, collections.Iterable), \
275+
('User Error: expected iterable, but did not find one' +
276+
'for field {}.{}').format(info.parent_type, info.field_name)
276277

277-
return serialized_result
278+
item_type = return_type.of_type
279+
completed_results = []
280+
contains_deferred = False
281+
for item in result:
282+
completed_item = self.complete_value_catching_error(ctx, item_type, field_asts, info, item)
283+
if not contains_deferred and isinstance(completed_item, Deferred):
284+
contains_deferred = True
278285

279-
runtime_type = None
286+
completed_results.append(completed_item)
280287

281-
# Field type must be Object, Interface or Union and expect sub-selections.
282-
if isinstance(return_type, GraphQLObjectType):
283-
runtime_type = return_type
288+
return DeferredList(completed_results) if contains_deferred else completed_results
284289

285-
elif isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)):
286-
runtime_type = return_type.resolve_type(result, info)
287-
if runtime_type and not return_type.is_possible_type(runtime_type):
288-
raise GraphQLError(
289-
u'Runtime Object type "{}" is not a possible type for "{}".'.format(runtime_type, return_type),
290-
field_asts
291-
)
290+
def complete_leaf_value(self, ctx, return_type, field_asts, info, result):
291+
"""
292+
Complete a Scalar or Enum by serializing to a valid value, returning null if serialization is not possible.
293+
"""
294+
serialized_result = return_type.serialize(result)
292295

293-
if not runtime_type:
296+
if serialized_result is None:
294297
return None
295298

296-
if runtime_type.is_type_of and not runtime_type.is_type_of(result, info):
299+
return serialized_result
300+
301+
def complete_object_value(self, ctx, return_type, field_asts, info, result):
302+
"""
303+
Complete an Object value by evaluating all sub-selections.
304+
"""
305+
if return_type.is_type_of and not return_type.is_type_of(result, info):
297306
raise GraphQLError(
298307
u'Expected value of type "{}" but got {}.'.format(return_type, type(result).__name__),
299308
field_asts
@@ -306,11 +315,32 @@ def complete_value(self, ctx, return_type, field_asts, info, result):
306315
selection_set = field_ast.selection_set
307316
if selection_set:
308317
subfield_asts = collect_fields(
309-
ctx, runtime_type, selection_set,
318+
ctx, return_type, selection_set,
310319
subfield_asts, visited_fragment_names
311320
)
312321

313-
return self._execute_fields(ctx, runtime_type, result, subfield_asts)
322+
return self._execute_fields(ctx, return_type, result, subfield_asts)
323+
324+
def complete_abstract_value(self, ctx, return_type, field_asts, info, result):
325+
"""
326+
Complete an value of an abstract type by determining the runtime type of that value, then completing based
327+
on that type.
328+
"""
329+
# Field type must be Object, Interface or Union and expect sub-selections.
330+
runtime_type = None
331+
332+
if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)):
333+
runtime_type = return_type.resolve_type(result, info)
334+
if runtime_type and not return_type.is_possible_type(runtime_type):
335+
raise GraphQLError(
336+
u'Runtime Object type "{}" is not a possible type for "{}".'.format(runtime_type, return_type),
337+
field_asts
338+
)
339+
340+
if not runtime_type:
341+
return None
342+
343+
return self.complete_object_value(ctx, runtime_type, field_asts, info, result)
314344

315345
def resolve_or_error(self, resolve_fn, source, args, info):
316346
curried_resolve_fn = functools.partial(resolve_fn, source, args, info)

0 commit comments

Comments
 (0)