@@ -124,7 +124,7 @@ def execute_operation(exe_context, operation, root_value):
124
124
)
125
125
126
126
if operation .operation == 'mutation' :
127
- return execute_fields_serially (exe_context , type , root_value , fields )
127
+ return execute_fields_serially (exe_context , type , root_value , [], fields )
128
128
129
129
if operation .operation == 'subscription' :
130
130
if not exe_context .allow_subscriptions :
@@ -133,12 +133,12 @@ def execute_operation(exe_context, operation, root_value):
133
133
"You will need to either use the subscribe function "
134
134
"or pass allow_subscriptions=True"
135
135
)
136
- return subscribe_fields (exe_context , type , root_value , fields )
136
+ return subscribe_fields (exe_context , type , root_value , fields , )
137
137
138
- return execute_fields (exe_context , type , root_value , fields , None )
138
+ return execute_fields (exe_context , type , root_value , fields , [], None )
139
139
140
140
141
- def execute_fields_serially (exe_context , parent_type , source_value , fields ):
141
+ def execute_fields_serially (exe_context , parent_type , source_value , path , fields ):
142
142
def execute_field_callback (results , response_name ):
143
143
field_asts = fields [response_name ]
144
144
result = resolve_field (
@@ -147,7 +147,7 @@ def execute_field_callback(results, response_name):
147
147
source_value ,
148
148
field_asts ,
149
149
None ,
150
- [response_name ]
150
+ path + [response_name ]
151
151
)
152
152
if result is Undefined :
153
153
return results
@@ -168,13 +168,13 @@ def execute_field(prev_promise, response_name):
168
168
return functools .reduce (execute_field , fields .keys (), Promise .resolve (collections .OrderedDict ()))
169
169
170
170
171
- def execute_fields (exe_context , parent_type , source_value , fields , info ):
171
+ def execute_fields (exe_context , parent_type , source_value , fields , path , info ):
172
172
contains_promise = False
173
173
174
174
final_results = OrderedDict ()
175
175
176
176
for response_name , field_asts in fields .items ():
177
- result = resolve_field (exe_context , parent_type , source_value , field_asts , info , ( info . path if info else []) + [response_name ])
177
+ result = resolve_field (exe_context , parent_type , source_value , field_asts , info , path + [response_name ])
178
178
if result is Undefined :
179
179
continue
180
180
@@ -207,8 +207,7 @@ def map_result(data):
207
207
# assert len(fields) == 1, "Can only subscribe one element at a time."
208
208
209
209
for response_name , field_asts in fields .items ():
210
-
211
- result = subscribe_field (exe_context , parent_type , source_value , field_asts )
210
+ result = subscribe_field (exe_context , parent_type , source_value , field_asts , [response_name ])
212
211
if result is Undefined :
213
212
continue
214
213
@@ -272,11 +271,12 @@ def resolve_field(exe_context, parent_type, source, field_asts, parent_info, fie
272
271
return_type ,
273
272
field_asts ,
274
273
info ,
274
+ field_path ,
275
275
result
276
276
)
277
277
278
278
279
- def subscribe_field (exe_context , parent_type , source , field_asts ):
279
+ def subscribe_field (exe_context , parent_type , source , field_asts , path ):
280
280
field_ast = field_asts [0 ]
281
281
field_name = field_ast .name .value
282
282
@@ -312,7 +312,7 @@ def subscribe_field(exe_context, parent_type, source, field_asts):
312
312
operation = exe_context .operation ,
313
313
variable_values = exe_context .variable_values ,
314
314
context = context ,
315
- path = [ field_name ]
315
+ path = path
316
316
)
317
317
318
318
executor = exe_context .executor
@@ -332,6 +332,7 @@ def subscribe_field(exe_context, parent_type, source, field_asts):
332
332
return_type ,
333
333
field_asts ,
334
334
info ,
335
+ path ,
335
336
))
336
337
337
338
@@ -346,16 +347,16 @@ def resolve_or_error(resolve_fn, source, info, args, executor):
346
347
return e
347
348
348
349
349
- def complete_value_catching_error (exe_context , return_type , field_asts , info , result ):
350
+ def complete_value_catching_error (exe_context , return_type , field_asts , info , path , result ):
350
351
# If the field type is non-nullable, then it is resolved without any
351
352
# protection from errors.
352
353
if isinstance (return_type , GraphQLNonNull ):
353
- return complete_value (exe_context , return_type , field_asts , info , result )
354
+ return complete_value (exe_context , return_type , field_asts , info , path , result )
354
355
355
356
# Otherwise, error protection is applied, logging the error and
356
357
# resolving a null value for this field if one is encountered.
357
358
try :
358
- completed = complete_value (exe_context , return_type , field_asts , info , result )
359
+ completed = complete_value (exe_context , return_type , field_asts , info , path , result )
359
360
if is_thenable (completed ):
360
361
def handle_error (error ):
361
362
traceback = completed ._traceback
@@ -371,7 +372,7 @@ def handle_error(error):
371
372
return None
372
373
373
374
374
- def complete_value (exe_context , return_type , field_asts , info , result ):
375
+ def complete_value (exe_context , return_type , field_asts , info , path , result ):
375
376
"""
376
377
Implements the instructions for completeValue as defined in the
377
378
"Field entries" section of the spec.
@@ -399,43 +400,44 @@ def complete_value(exe_context, return_type, field_asts, info, result):
399
400
return_type ,
400
401
field_asts ,
401
402
info ,
403
+ path ,
402
404
resolved
403
405
),
404
406
lambda error : Promise .rejected (
405
- GraphQLLocatedError (field_asts , original_error = error ))
407
+ GraphQLLocatedError (field_asts , original_error = error , path = path ))
406
408
)
407
409
408
410
# print return_type, type(result)
409
411
if isinstance (result , Exception ):
410
- raise GraphQLLocatedError (field_asts , original_error = result )
412
+ raise GraphQLLocatedError (field_asts , original_error = result , path = path )
411
413
412
414
if isinstance (return_type , GraphQLNonNull ):
413
- return complete_nonnull_value (exe_context , return_type , field_asts , info , result )
415
+ return complete_nonnull_value (exe_context , return_type , field_asts , info , path , result )
414
416
415
417
# If result is null-like, return null.
416
418
if result is None :
417
419
return None
418
420
419
421
# If field type is List, complete each item in the list with the inner type
420
422
if isinstance (return_type , GraphQLList ):
421
- return complete_list_value (exe_context , return_type , field_asts , info , result )
423
+ return complete_list_value (exe_context , return_type , field_asts , info , path , result )
422
424
423
425
# If field type is Scalar or Enum, serialize to a valid value, returning
424
426
# null if coercion is not possible.
425
427
if isinstance (return_type , (GraphQLScalarType , GraphQLEnumType )):
426
- return complete_leaf_value (return_type , result )
428
+ return complete_leaf_value (return_type , path , result )
427
429
428
430
if isinstance (return_type , (GraphQLInterfaceType , GraphQLUnionType )):
429
- return complete_abstract_value (exe_context , return_type , field_asts , info , result )
431
+ return complete_abstract_value (exe_context , return_type , field_asts , info , path , result )
430
432
431
433
if isinstance (return_type , GraphQLObjectType ):
432
- return complete_object_value (exe_context , return_type , field_asts , info , result )
434
+ return complete_object_value (exe_context , return_type , field_asts , info , path , result )
433
435
434
436
assert False , u'Cannot complete value of unexpected type "{}".' .format (
435
437
return_type )
436
438
437
439
438
- def complete_list_value (exe_context , return_type , field_asts , info , result ):
440
+ def complete_list_value (exe_context , return_type , field_asts , info , path , result ):
439
441
"""
440
442
Complete a list value by completing each item in the list with the inner type
441
443
"""
@@ -448,10 +450,8 @@ def complete_list_value(exe_context, return_type, field_asts, info, result):
448
450
contains_promise = False
449
451
450
452
index = 0
451
- path = info .path [:]
452
453
for item in result :
453
- info .path = path + [index ]
454
- completed_item = complete_value_catching_error (exe_context , item_type , field_asts , info , item )
454
+ completed_item = complete_value_catching_error (exe_context , item_type , field_asts , info , path + [index ], item , )
455
455
if not contains_promise and is_thenable (completed_item ):
456
456
contains_promise = True
457
457
@@ -461,7 +461,7 @@ def complete_list_value(exe_context, return_type, field_asts, info, result):
461
461
return Promise .all (completed_results ) if contains_promise else completed_results
462
462
463
463
464
- def complete_leaf_value (return_type , result ):
464
+ def complete_leaf_value (return_type , path , result ):
465
465
"""
466
466
Complete a Scalar or Enum by serializing to a valid value, returning null if serialization is not possible.
467
467
"""
@@ -471,12 +471,13 @@ def complete_leaf_value(return_type, result):
471
471
if serialized_result is None :
472
472
raise GraphQLError (
473
473
('Expected a value of type "{}" but ' +
474
- 'received: {}' ).format (return_type , result )
474
+ 'received: {}' ).format (return_type , result ),
475
+ path = path
475
476
)
476
477
return serialized_result
477
478
478
479
479
- def complete_abstract_value (exe_context , return_type , field_asts , info , result ):
480
+ def complete_abstract_value (exe_context , return_type , field_asts , info , path , result ):
480
481
"""
481
482
Complete an value of an abstract type by determining the runtime type of that value, then completing based
482
483
on that type.
@@ -514,7 +515,7 @@ def complete_abstract_value(exe_context, return_type, field_asts, info, result):
514
515
field_asts
515
516
)
516
517
517
- return complete_object_value (exe_context , runtime_type , field_asts , info , result )
518
+ return complete_object_value (exe_context , runtime_type , field_asts , info , path , result )
518
519
519
520
520
521
def get_default_resolve_type_fn (value , info , abstract_type ):
@@ -524,7 +525,7 @@ def get_default_resolve_type_fn(value, info, abstract_type):
524
525
return type
525
526
526
527
527
- def complete_object_value (exe_context , return_type , field_asts , info , result ):
528
+ def complete_object_value (exe_context , return_type , field_asts , info , path , result ):
528
529
"""
529
530
Complete an Object value by evaluating all sub-selections.
530
531
"""
@@ -537,21 +538,22 @@ def complete_object_value(exe_context, return_type, field_asts, info, result):
537
538
538
539
# Collect sub-fields to execute to complete this value.
539
540
subfield_asts = exe_context .get_sub_fields (return_type , field_asts )
540
- return execute_fields (exe_context , return_type , result , subfield_asts , info )
541
+ return execute_fields (exe_context , return_type , result , subfield_asts , path , info )
541
542
542
543
543
- def complete_nonnull_value (exe_context , return_type , field_asts , info , result ):
544
+ def complete_nonnull_value (exe_context , return_type , field_asts , info , path , result ):
544
545
"""
545
546
Complete a NonNull value by completing the inner type
546
547
"""
547
548
completed = complete_value (
548
- exe_context , return_type .of_type , field_asts , info , result
549
+ exe_context , return_type .of_type , field_asts , info , path , result
549
550
)
550
551
if completed is None :
551
552
raise GraphQLError (
552
553
'Cannot return null for non-nullable field {}.{}.' .format (
553
554
info .parent_type , info .field_name ),
554
- field_asts
555
+ field_asts ,
556
+ path = path
555
557
)
556
558
557
559
return completed
0 commit comments