27
27
28
28
__all__ = [
29
29
"CollectFieldsContext" ,
30
+ "CollectedFields" ,
30
31
"DeferUsage" ,
31
32
"FieldDetails" ,
32
33
"collect_fields" ,
@@ -69,13 +70,20 @@ class CollectFieldsContext(NamedTuple):
69
70
visited_fragment_names : set [str ]
70
71
71
72
73
+ class CollectedFields (NamedTuple ):
74
+ """Collected fields with new defer usages."""
75
+
76
+ fields : dict [str , list [FieldDetails ]]
77
+ new_defer_usages : list [DeferUsage ]
78
+
79
+
72
80
def collect_fields (
73
81
schema : GraphQLSchema ,
74
82
fragments : dict [str , FragmentDefinitionNode ],
75
83
variable_values : dict [str , Any ],
76
84
runtime_type : GraphQLObjectType ,
77
85
operation : OperationDefinitionNode ,
78
- ) -> dict [ str , list [ FieldDetails ]] :
86
+ ) -> CollectedFields :
79
87
"""Collect fields.
80
88
81
89
Given a selection_set, collects all the fields and returns them.
@@ -87,6 +95,7 @@ def collect_fields(
87
95
For internal use only.
88
96
"""
89
97
grouped_field_set : dict [str , list [FieldDetails ]] = defaultdict (list )
98
+ new_defer_usages : list [DeferUsage ] = []
90
99
context = CollectFieldsContext (
91
100
schema ,
92
101
fragments ,
@@ -96,8 +105,10 @@ def collect_fields(
96
105
set (),
97
106
)
98
107
99
- collect_fields_impl (context , operation .selection_set , grouped_field_set )
100
- return grouped_field_set
108
+ collect_fields_impl (
109
+ context , operation .selection_set , grouped_field_set , new_defer_usages
110
+ )
111
+ return CollectedFields (grouped_field_set , new_defer_usages )
101
112
102
113
103
114
def collect_subfields (
@@ -107,7 +118,7 @@ def collect_subfields(
107
118
operation : OperationDefinitionNode ,
108
119
return_type : GraphQLObjectType ,
109
120
field_details : list [FieldDetails ],
110
- ) -> dict [ str , list [ FieldDetails ]] :
121
+ ) -> CollectedFields :
111
122
"""Collect subfields.
112
123
113
124
Given a list of field nodes, collects all the subfields of the passed in fields,
@@ -128,6 +139,7 @@ def collect_subfields(
128
139
set (),
129
140
)
130
141
sub_grouped_field_set : dict [str , list [FieldDetails ]] = defaultdict (list )
142
+ new_defer_usages : list [DeferUsage ] = []
131
143
132
144
for field_detail in field_details :
133
145
node = field_detail .node
@@ -136,17 +148,18 @@ def collect_subfields(
136
148
context ,
137
149
node .selection_set ,
138
150
sub_grouped_field_set ,
151
+ new_defer_usages ,
139
152
field_detail .defer_usage ,
140
153
)
141
154
142
- return sub_grouped_field_set
155
+ return CollectedFields ( sub_grouped_field_set , new_defer_usages )
143
156
144
157
145
158
def collect_fields_impl (
146
159
context : CollectFieldsContext ,
147
160
selection_set : SelectionSetNode ,
148
161
grouped_field_set : dict [str , list [FieldDetails ]],
149
- parent_defer_usage : DeferUsage | None = None ,
162
+ new_defer_usages : list [ DeferUsage ] ,
150
163
defer_usage : DeferUsage | None = None ,
151
164
) -> None :
152
165
"""Collect fields (internal implementation)."""
@@ -164,31 +177,39 @@ def collect_fields_impl(
164
177
if not should_include_node (variable_values , selection ):
165
178
continue
166
179
key = get_field_entry_key (selection )
167
- grouped_field_set [key ].append (
168
- FieldDetails (selection , defer_usage or parent_defer_usage )
169
- )
180
+ grouped_field_set [key ].append (FieldDetails (selection , defer_usage ))
170
181
elif isinstance (selection , InlineFragmentNode ):
171
182
if not should_include_node (
172
183
variable_values , selection
173
184
) or not does_fragment_condition_match (schema , selection , runtime_type ):
174
185
continue
175
186
176
187
new_defer_usage = get_defer_usage (
177
- operation , variable_values , selection , parent_defer_usage
188
+ operation , variable_values , selection , defer_usage
178
189
)
179
190
180
- collect_fields_impl (
181
- context ,
182
- selection .selection_set ,
183
- grouped_field_set ,
184
- parent_defer_usage ,
185
- new_defer_usage or defer_usage ,
186
- )
191
+ if new_defer_usage is None :
192
+ collect_fields_impl (
193
+ context ,
194
+ selection .selection_set ,
195
+ grouped_field_set ,
196
+ new_defer_usages ,
197
+ defer_usage ,
198
+ )
199
+ else :
200
+ new_defer_usages .append (new_defer_usage )
201
+ collect_fields_impl (
202
+ context ,
203
+ selection .selection_set ,
204
+ grouped_field_set ,
205
+ new_defer_usages ,
206
+ new_defer_usage ,
207
+ )
187
208
elif isinstance (selection , FragmentSpreadNode ): # pragma: no cover else
188
209
frag_name = selection .name .value
189
210
190
211
new_defer_usage = get_defer_usage (
191
- operation , variable_values , selection , parent_defer_usage
212
+ operation , variable_values , selection , defer_usage
192
213
)
193
214
194
215
if new_defer_usage is None and (
@@ -205,14 +226,22 @@ def collect_fields_impl(
205
226
206
227
if new_defer_usage is None :
207
228
visited_fragment_names .add (frag_name )
208
-
209
- collect_fields_impl (
210
- context ,
211
- fragment .selection_set ,
212
- grouped_field_set ,
213
- parent_defer_usage ,
214
- new_defer_usage or defer_usage ,
215
- )
229
+ collect_fields_impl (
230
+ context ,
231
+ fragment .selection_set ,
232
+ grouped_field_set ,
233
+ new_defer_usages ,
234
+ defer_usage ,
235
+ )
236
+ else :
237
+ new_defer_usages .append (new_defer_usage )
238
+ collect_fields_impl (
239
+ context ,
240
+ fragment .selection_set ,
241
+ grouped_field_set ,
242
+ new_defer_usages ,
243
+ new_defer_usage ,
244
+ )
216
245
217
246
218
247
def get_defer_usage (
0 commit comments