@@ -331,8 +331,6 @@ def execute_operation(
331
331
# Errors from sub-fields of a NonNull type may propagate to the top level, at
332
332
# which point we still log the error and null the parent field, which in this
333
333
# case is the entire response.
334
- #
335
- # Similar to complete_value_catching_error.
336
334
try :
337
335
# noinspection PyArgumentList
338
336
result = (
@@ -595,6 +593,7 @@ def resolve_field(
595
593
if not field_def :
596
594
return Undefined
597
595
596
+ return_type = field_def .type
598
597
resolve_fn = field_def .resolve or self .field_resolver
599
598
600
599
if self .middleware_manager :
@@ -604,29 +603,6 @@ def resolve_field(
604
603
605
604
# Get the resolve function, regardless of if its result is normal or abrupt
606
605
# (error).
607
- result = self .resolve_field_value_or_error (
608
- field_def , field_nodes , resolve_fn , source , info
609
- )
610
-
611
- return self .complete_value_catching_error (
612
- field_def .type , field_nodes , info , path , result
613
- )
614
-
615
- def resolve_field_value_or_error (
616
- self ,
617
- field_def : GraphQLField ,
618
- field_nodes : List [FieldNode ],
619
- resolve_fn : GraphQLFieldResolver ,
620
- source : Any ,
621
- info : GraphQLResolveInfo ,
622
- ) -> Union [Exception , Any ]:
623
- """Resolve field to a value or an error.
624
-
625
- Isolates the "ReturnOrAbrupt" behavior to not de-opt the resolve_field()
626
- method. Returns the result of resolveFn or the abrupt-return Error object.
627
-
628
- For internal use only.
629
- """
630
606
try :
631
607
# Build a dictionary of arguments from the field.arguments AST, using the
632
608
# variables scope to fulfill any variable references.
@@ -635,58 +611,38 @@ def resolve_field_value_or_error(
635
611
# Note that contrary to the JavaScript implementation, we pass the context
636
612
# value as part of the resolve info.
637
613
result = resolve_fn (source , info , ** args )
614
+
615
+ completed : AwaitableOrValue [Any ]
638
616
if self .is_awaitable (result ):
639
617
# noinspection PyShadowingNames
640
618
async def await_result () -> Any :
641
619
try :
642
- return await result
620
+ completed = self .complete_value (
621
+ return_type , field_nodes , info , path , await result
622
+ )
623
+ if self .is_awaitable (completed ):
624
+ return await completed
625
+ return completed
643
626
except Exception as error :
644
- return error
627
+ self .handle_field_error (error , field_nodes , path , return_type )
628
+ return None
645
629
646
630
return await_result ()
647
- return result
648
- except Exception as error :
649
- return error
650
631
651
- def complete_value_catching_error (
652
- self ,
653
- return_type : GraphQLOutputType ,
654
- field_nodes : List [FieldNode ],
655
- info : GraphQLResolveInfo ,
656
- path : Path ,
657
- result : Any ,
658
- ) -> AwaitableOrValue [Any ]:
659
- """Complete a value while catching an error.
660
-
661
- This is a small wrapper around completeValue which detects and logs errors in
662
- the execution context.
663
- """
664
- completed : AwaitableOrValue [Any ]
665
- try :
666
- if self .is_awaitable (result ):
667
-
668
- async def await_result () -> Any :
669
- value = self .complete_value (
670
- return_type , field_nodes , info , path , await result
671
- )
672
- if self .is_awaitable (value ):
673
- return await value
674
- return value
675
-
676
- completed = await_result ()
677
- else :
678
- completed = self .complete_value (
679
- return_type , field_nodes , info , path , result
680
- )
632
+ completed = self .complete_value (
633
+ return_type , field_nodes , info , path , result
634
+ )
681
635
if self .is_awaitable (completed ):
682
636
# noinspection PyShadowingNames
683
637
async def await_completed () -> Any :
684
638
try :
685
639
return await completed
686
640
except Exception as error :
687
641
self .handle_field_error (error , field_nodes , path , return_type )
642
+ return None
688
643
689
644
return await_completed ()
645
+
690
646
return completed
691
647
except Exception as error :
692
648
self .handle_field_error (error , field_nodes , path , return_type )
@@ -825,10 +781,45 @@ def complete_list_value(
825
781
for index , item in enumerate (result ):
826
782
# No need to modify the info object containing the path, since from here on
827
783
# it is not ever accessed by resolver functions.
828
- field_path = path .add_key (index , None )
829
- completed_item = self .complete_value_catching_error (
830
- item_type , field_nodes , info , field_path , item
831
- )
784
+ item_path = path .add_key (index , None )
785
+ completed_item : AwaitableOrValue [Any ]
786
+ if is_awaitable (item ):
787
+ # noinspection PyShadowingNames
788
+ async def await_completed (item : Any , item_path : Path ) -> Any :
789
+ try :
790
+ completed = self .complete_value (
791
+ item_type , field_nodes , info , item_path , await item
792
+ )
793
+ if is_awaitable (completed ):
794
+ return await completed
795
+ return completed
796
+ except Exception as error :
797
+ self .handle_field_error (
798
+ error , field_nodes , item_path , item_type
799
+ )
800
+ return None
801
+
802
+ completed_item = await_completed (item , item_path )
803
+ else :
804
+ try :
805
+ completed_item = self .complete_value (
806
+ item_type , field_nodes , info , item_path , item
807
+ )
808
+ if is_awaitable (completed_item ):
809
+ # noinspection PyShadowingNames
810
+ async def await_completed (item : Any , item_path : Path ) -> Any :
811
+ try :
812
+ return await item
813
+ except Exception as error :
814
+ self .handle_field_error (
815
+ error , field_nodes , item_path , item_type
816
+ )
817
+ return None
818
+
819
+ completed_item = await_completed (completed_item , item_path )
820
+ except Exception as error :
821
+ self .handle_field_error (error , field_nodes , item_path , item_type )
822
+ completed_item = None
832
823
833
824
if is_awaitable (completed_item ):
834
825
append_awaitable (index )
0 commit comments