15
15
16
16
17
17
class Executor (object ):
18
- def __init__ (self , execution_middlewares = None , default_resolver = default_resolve_fn ):
19
- self .execution_middlewares = execution_middlewares or []
20
- self .default_resolve_fn = default_resolver
18
+ def __init__ (self , execution_middlewares = None , default_resolver = default_resolve_fn , map_type = dict ):
19
+ assert issubclass (map_type , collections .MutableMapping )
20
+
21
+ self ._execution_middlewares = execution_middlewares or []
22
+ self ._default_resolve_fn = default_resolver
23
+ self ._map_type = map_type
24
+ self ._enforce_strict_ordering = issubclass (map_type , collections .OrderedDict )
25
+
26
+ @property
27
+ def enforce_strict_ordering (self ):
28
+ return self ._enforce_strict_ordering
29
+
30
+ @property
31
+ def map_type (self ):
32
+ return self ._map_type
21
33
22
34
def execute (self , schema , request = '' , root = None , args = None , operation_name = None , request_context = None ,
23
35
execute_serially = False , validate_ast = True ):
@@ -34,7 +46,7 @@ def execute(self, schema, request='', root=None, args=None, operation_name=None,
34
46
validate_ast
35
47
)
36
48
37
- for middleware in self .execution_middlewares :
49
+ for middleware in self ._execution_middlewares :
38
50
if hasattr (middleware , 'execution_result' ):
39
51
curried_execution_function = functools .partial (middleware .execution_result , curried_execution_function )
40
52
@@ -81,7 +93,10 @@ def _execute_operation(self, ctx, root, operation, execute_serially):
81
93
if operation .operation == 'mutation' or execute_serially :
82
94
execute_serially = True
83
95
84
- fields = DefaultOrderedDict (list ) if execute_serially else collections .defaultdict (list )
96
+ fields = DefaultOrderedDict (list ) \
97
+ if (execute_serially or self ._enforce_strict_ordering ) \
98
+ else collections .defaultdict (list )
99
+
85
100
fields = collect_fields (ctx , type , operation .selection_set , fields , set ())
86
101
87
102
if execute_serially :
@@ -101,20 +116,20 @@ def collect_result(resolved_result):
101
116
return results
102
117
103
118
if isinstance (result , Deferred ):
104
- return result .add_callback (collect_result )
119
+ return succeed ( result ) .add_callback (collect_result )
105
120
106
121
else :
107
122
return collect_result (result )
108
123
109
124
def execute_field (prev_deferred , response_name ):
110
125
return prev_deferred .add_callback (execute_field_callback , response_name )
111
126
112
- return functools .reduce (execute_field , fields .keys (), succeed ({} ))
127
+ return functools .reduce (execute_field , fields .keys (), succeed (self . _map_type () ))
113
128
114
129
def _execute_fields (self , execution_context , parent_type , source_value , fields ):
115
130
contains_deferred = False
116
131
117
- results = {}
132
+ results = self . _map_type ()
118
133
for response_name , field_asts in fields .items ():
119
134
result = self ._resolve_field (execution_context , parent_type , source_value , field_asts )
120
135
if result is Undefined :
@@ -138,7 +153,7 @@ def _resolve_field(self, execution_context, parent_type, source, field_asts):
138
153
return Undefined
139
154
140
155
return_type = field_def .type
141
- resolve_fn = field_def .resolver or self .default_resolve_fn
156
+ resolve_fn = field_def .resolver or self ._default_resolve_fn
142
157
143
158
# Build a dict of arguments from the field.arguments AST, using the variables scope to
144
159
# fulfill any variable references.
@@ -283,7 +298,7 @@ def complete_value(self, ctx, return_type, field_asts, info, result):
283
298
)
284
299
285
300
# Collect sub-fields to execute to complete this value.
286
- subfield_asts = collections .defaultdict (list )
301
+ subfield_asts = DefaultOrderedDict ( list ) if self . _enforce_strict_ordering else collections .defaultdict (list )
287
302
visited_fragment_names = set ()
288
303
for field_ast in field_asts :
289
304
selection_set = field_ast .selection_set
@@ -298,7 +313,7 @@ def run_resolve_fn(self, resolve_fn, source, args, info):
298
313
curried_resolve_fn = functools .partial (resolve_fn , source , args , info )
299
314
300
315
try :
301
- for middleware in self .execution_middlewares :
316
+ for middleware in self ._execution_middlewares :
302
317
if hasattr (middleware , 'run_resolve_fn' ):
303
318
curried_resolve_fn = functools .partial (middleware .run_resolve_fn , curried_resolve_fn , resolve_fn )
304
319
0 commit comments