1818from ..utilities .type_from_ast import type_from_ast
1919from .values import get_directive_values
2020
21- __all__ = ["collect_fields" ]
21+ __all__ = ["collect_fields" , "collect_sub_fields" ]
2222
2323
2424def collect_fields (
@@ -27,20 +27,68 @@ def collect_fields(
2727 variable_values : Dict [str , Any ],
2828 runtime_type : GraphQLObjectType ,
2929 selection_set : SelectionSetNode ,
30- fields : Dict [str , List [FieldNode ]],
31- visited_fragment_names : Set [str ],
3230) -> Dict [str , List [FieldNode ]]:
3331 """Collect fields.
3432
35- Given a selection_set, adds all of the fields in that selection to the passed in
36- map of fields, and returns it at the end.
33+ Given a selection_set, collects all of the fields returns them at the end.
3734
38- collect_fields requires the "runtime type" of an object. For a field which
35+ collect_fields requires the "runtime type" of an object. For a field that
3936 returns an Interface or Union type, the "runtime type" will be the actual
40- Object type returned by that field.
37+ object type returned by that field.
4138
4239 For internal use only.
4340 """
41+ fields : Dict [str , List [FieldNode ]] = {}
42+ collect_fields_impl (
43+ schema , fragments , variable_values , runtime_type , selection_set , fields , set ()
44+ )
45+ return fields
46+
47+
48+ def collect_sub_fields (
49+ schema : GraphQLSchema ,
50+ fragments : Dict [str , FragmentDefinitionNode ],
51+ variable_values : Dict [str , Any ],
52+ return_type : GraphQLObjectType ,
53+ field_nodes : List [FieldNode ],
54+ ) -> Dict [str , List [FieldNode ]]:
55+ """Collect sub fields.
56+
57+ Given a list of field nodes, collects all of the subfields of the passed
58+ in fields, and returns them at the end.
59+
60+ collect_sub_fields requires the "return type" of an object. For a field that
61+ returns an Interface or Union type, the "return type" will be the actual
62+ object type returned by that field.
63+
64+ For internal use only.
65+ """
66+ sub_field_nodes : Dict [str , List [FieldNode ]] = {}
67+ visited_fragment_names : Set [str ] = set ()
68+ for node in field_nodes :
69+ if node .selection_set :
70+ collect_fields_impl (
71+ schema ,
72+ fragments ,
73+ variable_values ,
74+ return_type ,
75+ node .selection_set ,
76+ sub_field_nodes ,
77+ visited_fragment_names ,
78+ )
79+ return sub_field_nodes
80+
81+
82+ def collect_fields_impl (
83+ schema : GraphQLSchema ,
84+ fragments : Dict [str , FragmentDefinitionNode ],
85+ variable_values : Dict [str , Any ],
86+ runtime_type : GraphQLObjectType ,
87+ selection_set : SelectionSetNode ,
88+ fields : Dict [str , List [FieldNode ]],
89+ visited_fragment_names : Set [str ],
90+ ) -> None :
91+ """Collect fields (internal implementation)."""
4492 for selection in selection_set .selections :
4593 if isinstance (selection , FieldNode ):
4694 if not should_include_node (variable_values , selection ):
@@ -52,7 +100,7 @@ def collect_fields(
52100 variable_values , selection
53101 ) or not does_fragment_condition_match (schema , selection , runtime_type ):
54102 continue
55- collect_fields (
103+ collect_fields_impl (
56104 schema ,
57105 fragments ,
58106 variable_values ,
@@ -73,7 +121,7 @@ def collect_fields(
73121 schema , fragment , runtime_type
74122 ):
75123 continue
76- collect_fields (
124+ collect_fields_impl (
77125 schema ,
78126 fragments ,
79127 variable_values ,
@@ -82,7 +130,6 @@ def collect_fields(
82130 fields ,
83131 visited_fragment_names ,
84132 )
85- return fields
86133
87134
88135def should_include_node (
0 commit comments