3
3
import logging
4
4
import sys
5
5
6
- from promise import Promise , is_thenable , promise_for_dict , promisify
6
+ from promise import Promise , promise_for_dict , promisify
7
7
8
8
from ..error import GraphQLError , GraphQLLocatedError
9
9
from ..pyutils .default_ordered_dict import DefaultOrderedDict
10
+ from ..pyutils .ordereddict import OrderedDict
10
11
from ..type import (GraphQLEnumType , GraphQLInterfaceType , GraphQLList ,
11
12
GraphQLNonNull , GraphQLObjectType , GraphQLScalarType ,
12
13
GraphQLSchema , GraphQLUnionType )
13
14
from .base import (ExecutionContext , ExecutionResult , ResolveInfo , Undefined ,
14
15
collect_fields , default_resolve_fn , get_field_def ,
15
16
get_operation_root_type )
16
17
from .executors .sync import SyncExecutor
18
+ from .middleware import MiddlewareManager
17
19
18
20
logger = logging .getLogger (__name__ )
19
21
20
22
23
+ def is_promise (obj ):
24
+ return type (obj ) == Promise
25
+
26
+
21
27
def execute (schema , document_ast , root_value = None , context_value = None ,
22
28
variable_values = None , operation_name = None , executor = None ,
23
- return_promise = False ):
29
+ return_promise = False , middlewares = None ):
24
30
assert schema , 'Must provide schema'
25
31
assert isinstance (schema , GraphQLSchema ), (
26
32
'Schema must be an instance of GraphQLSchema. Also ensure that there are ' +
27
33
'not multiple versions of GraphQL installed in your node_modules directory.'
28
34
)
35
+ if middlewares :
36
+ assert isinstance (middlewares , MiddlewareManager ), (
37
+ 'middlewares have to be an instance'
38
+ ' of MiddlewareManager. Received "{}".' .format (middlewares )
39
+ )
29
40
30
41
if executor is None :
31
42
executor = SyncExecutor ()
@@ -37,7 +48,8 @@ def execute(schema, document_ast, root_value=None, context_value=None,
37
48
context_value ,
38
49
variable_values ,
39
50
operation_name ,
40
- executor
51
+ executor ,
52
+ middlewares
41
53
)
42
54
43
55
def executor (resolve , reject ):
@@ -85,7 +97,7 @@ def execute_field_callback(results, response_name):
85
97
if result is Undefined :
86
98
return results
87
99
88
- if is_thenable (result ):
100
+ if is_promise (result ):
89
101
def collect_result (resolved_result ):
90
102
results [response_name ] = resolved_result
91
103
return results
@@ -104,15 +116,15 @@ def execute_field(prev_promise, response_name):
104
116
def execute_fields (exe_context , parent_type , source_value , fields ):
105
117
contains_promise = False
106
118
107
- final_results = collections . OrderedDict ()
119
+ final_results = OrderedDict ()
108
120
109
121
for response_name , field_asts in fields .items ():
110
122
result = resolve_field (exe_context , parent_type , source_value , field_asts )
111
123
if result is Undefined :
112
124
continue
113
125
114
126
final_results [response_name ] = result
115
- if is_thenable (result ):
127
+ if is_promise (result ):
116
128
contains_promise = True
117
129
118
130
if not contains_promise :
@@ -132,6 +144,9 @@ def resolve_field(exe_context, parent_type, source, field_asts):
132
144
return_type = field_def .type
133
145
resolve_fn = field_def .resolver or default_resolve_fn
134
146
147
+ # We wrap the resolve_fn from the middleware
148
+ resolve_fn_middleware = exe_context .get_field_resolver (resolve_fn )
149
+
135
150
# Build a dict of arguments from the field.arguments AST, using the variables scope to
136
151
# fulfill any variable references.
137
152
args = exe_context .get_argument_values (field_def , field_ast )
@@ -156,7 +171,7 @@ def resolve_field(exe_context, parent_type, source, field_asts):
156
171
)
157
172
158
173
executor = exe_context .executor
159
- result = resolve_or_error (resolve_fn , source , args , context , info , executor )
174
+ result = resolve_or_error (resolve_fn_middleware , source , args , context , info , executor )
160
175
161
176
return complete_value_catching_error (
162
177
exe_context ,
@@ -188,7 +203,7 @@ def complete_value_catching_error(exe_context, return_type, field_asts, info, re
188
203
# resolving a null value for this field if one is encountered.
189
204
try :
190
205
completed = complete_value (exe_context , return_type , field_asts , info , result )
191
- if is_thenable (completed ):
206
+ if is_promise (completed ):
192
207
def handle_error (error ):
193
208
exe_context .errors .append (error )
194
209
return Promise .fulfilled (None )
@@ -222,7 +237,7 @@ def complete_value(exe_context, return_type, field_asts, info, result):
222
237
"""
223
238
# If field type is NonNull, complete for inner type, and throw field error if result is null.
224
239
225
- if is_thenable (result ):
240
+ if is_promise (result ):
226
241
return promisify (result ).then (
227
242
lambda resolved : complete_value (
228
243
exe_context ,
@@ -238,16 +253,7 @@ def complete_value(exe_context, return_type, field_asts, info, result):
238
253
raise GraphQLLocatedError (field_asts , original_error = result )
239
254
240
255
if isinstance (return_type , GraphQLNonNull ):
241
- completed = complete_value (
242
- exe_context , return_type .of_type , field_asts , info , result
243
- )
244
- if completed is None :
245
- raise GraphQLError (
246
- 'Cannot return null for non-nullable field {}.{}.' .format (info .parent_type , info .field_name ),
247
- field_asts
248
- )
249
-
250
- return completed
256
+ return complete_nonnull_value (exe_context , return_type , field_asts , info , result )
251
257
252
258
# If result is null-like, return null.
253
259
if result is None :
@@ -283,7 +289,7 @@ def complete_list_value(exe_context, return_type, field_asts, info, result):
283
289
contains_promise = False
284
290
for item in result :
285
291
completed_item = complete_value_catching_error (exe_context , item_type , field_asts , info , item )
286
- if not contains_promise and is_thenable (completed_item ):
292
+ if not contains_promise and is_promise (completed_item ):
287
293
contains_promise = True
288
294
289
295
completed_results .append (completed_item )
@@ -295,15 +301,10 @@ def complete_leaf_value(return_type, result):
295
301
"""
296
302
Complete a Scalar or Enum by serializing to a valid value, returning null if serialization is not possible.
297
303
"""
298
- serialize = getattr (return_type , 'serialize' , None )
299
- assert serialize , 'Missing serialize method on type'
300
-
301
- serialized_result = serialize (result )
302
-
303
- if serialized_result is None :
304
- return None
304
+ # serialize = getattr(return_type, 'serialize', None)
305
+ # assert serialize, 'Missing serialize method on type'
305
306
306
- return serialized_result
307
+ return return_type . serialize ( result )
307
308
308
309
309
310
def complete_abstract_value (exe_context , return_type , field_asts , info , result ):
@@ -360,14 +361,21 @@ def complete_object_value(exe_context, return_type, field_asts, info, result):
360
361
)
361
362
362
363
# Collect sub-fields to execute to complete this value.
363
- subfield_asts = DefaultOrderedDict (list )
364
- visited_fragment_names = set ()
365
- for field_ast in field_asts :
366
- selection_set = field_ast .selection_set
367
- if selection_set :
368
- subfield_asts = collect_fields (
369
- exe_context , return_type , selection_set ,
370
- subfield_asts , visited_fragment_names
371
- )
372
-
364
+ subfield_asts = exe_context .get_sub_fields (return_type , field_asts )
373
365
return execute_fields (exe_context , return_type , result , subfield_asts )
366
+
367
+
368
+ def complete_nonnull_value (exe_context , return_type , field_asts , info , result ):
369
+ """
370
+ Complete a NonNull value by completing the inner type
371
+ """
372
+ completed = complete_value (
373
+ exe_context , return_type .of_type , field_asts , info , result
374
+ )
375
+ if completed is None :
376
+ raise GraphQLError (
377
+ 'Cannot return null for non-nullable field {}.{}.' .format (info .parent_type , info .field_name ),
378
+ field_asts
379
+ )
380
+
381
+ return completed
0 commit comments