1
1
import functools
2
2
3
- from promise import Promise , promise_for_dict
3
+ from promise import Promise , is_thenable , promise_for_dict
4
4
5
5
from ...pyutils .cached_property import cached_property
6
6
from ...pyutils .default_ordered_dict import DefaultOrderedDict
10
10
from ..base import ResolveInfo , Undefined , collect_fields , get_field_def
11
11
from ..values import get_argument_values
12
12
from ...error import GraphQLError
13
-
14
-
15
- def is_promise (obj ):
16
- return isinstance (obj , Promise )
13
+ from .utils import imap , normal_map
17
14
18
15
19
16
def get_base_type (type ):
@@ -78,7 +75,20 @@ def get_resolvers(context, type, field_asts):
78
75
field_ast .arguments ,
79
76
context and context .variable_values
80
77
)
81
- yield (response_name , resolver , args , context and context .context_value , info )
78
+ yield (response_name , Field (resolver , args , context and context .context_value , info ))
79
+
80
+
81
+ class Field (object ):
82
+ __slots__ = ('fn' , 'args' , 'context' , 'info' )
83
+
84
+ def __init__ (self , fn , args , context , info ):
85
+ self .fn = fn
86
+ self .args = args
87
+ self .context = context
88
+ self .info = info
89
+
90
+ def execute (self , root ):
91
+ return self .fn (root , self .args , self .context , self .info )
82
92
83
93
84
94
class Fragment (object ):
@@ -97,6 +107,22 @@ def partial_resolvers(self):
97
107
self .field_asts
98
108
))
99
109
110
+ @cached_property
111
+ def fragment_container (self ):
112
+ fields = zip (* self .partial_resolvers )[0 ]
113
+ class FragmentInstance (dict ):
114
+ # def __init__(self):
115
+ # self.fields = fields
116
+ # _fields = ('c','b','a')
117
+ set = dict .__setitem__
118
+ # def set(self, name, value):
119
+ # self[name] = value
120
+
121
+ def __iter__ (self ):
122
+ return iter (fields )
123
+
124
+ return FragmentInstance
125
+
100
126
def have_type (self , root ):
101
127
return not self .type .is_type_of or self .type .is_type_of (root , self .context .context_value , self .info )
102
128
@@ -109,18 +135,18 @@ def resolve(self, root):
109
135
110
136
contains_promise = False
111
137
112
- final_results = OrderedDict ()
138
+ final_results = self . fragment_container ()
113
139
# return OrderedDict(
114
140
# ((field_name, field_resolver(root, field_args, context, info))
115
141
# for field_name, field_resolver, field_args, context, info in self.partial_resolvers)
116
142
# )
117
- for response_name , field_resolver , field_args , context , info in self .partial_resolvers :
143
+ for response_name , field_resolver in self .partial_resolvers :
118
144
119
- result = field_resolver (root , field_args , context , info )
145
+ result = field_resolver . execute (root )
120
146
if result is Undefined :
121
147
continue
122
148
123
- if not contains_promise and is_promise (result ):
149
+ if not contains_promise and is_thenable (result ):
124
150
contains_promise = True
125
151
126
152
final_results [response_name ] = result
@@ -136,14 +162,14 @@ def resolve(self, root):
136
162
137
163
def resolve_serially (self , root ):
138
164
def execute_field_callback (results , resolver ):
139
- response_name , field_resolver , field_args , context , info = resolver
165
+ response_name , field_resolver = resolver
140
166
141
- result = field_resolver (root , field_args , context , info )
167
+ result = field_resolver . execute (root )
142
168
143
169
if result is Undefined :
144
170
return results
145
171
146
- if is_promise (result ):
172
+ if is_thenable (result ):
147
173
def collect_result (resolved_result ):
148
174
results [response_name ] = resolved_result
149
175
return results
@@ -156,7 +182,7 @@ def collect_result(resolved_result):
156
182
def execute_field (prev_promise , resolver ):
157
183
return prev_promise .then (lambda results : execute_field_callback (results , resolver ))
158
184
159
- return functools .reduce (execute_field , self .partial_resolvers , Promise .resolve (OrderedDict ()))
185
+ return functools .reduce (execute_field , self .partial_resolvers , Promise .resolve (self . fragment_container ()))
160
186
161
187
def __eq__ (self , other ):
162
188
return isinstance (other , Fragment ) and (
@@ -180,6 +206,12 @@ def __init__(self, abstract_type, field_asts, context=None, info=None):
180
206
def possible_types (self ):
181
207
return self .context .schema .get_possible_types (self .abstract_type )
182
208
209
+ @cached_property
210
+ def possible_types_with_is_type_of (self ):
211
+ return [
212
+ (type , type .is_type_of ) for type in self .possible_types if callable (type .is_type_of )
213
+ ]
214
+
183
215
def get_fragment (self , type ):
184
216
if isinstance (type , str ):
185
217
type = self .context .schema .get_type (type )
@@ -194,6 +226,7 @@ def get_fragment(self, type):
194
226
self .context ,
195
227
self .info
196
228
)
229
+
197
230
return self ._fragments [type ]
198
231
199
232
def resolve_type (self , result ):
@@ -202,10 +235,10 @@ def resolve_type(self, result):
202
235
203
236
if return_type .resolve_type :
204
237
return return_type .resolve_type (result , context , self .info )
205
- else :
206
- for type in self .possible_types :
207
- if callable ( type . is_type_of ) and type . is_type_of (result , context , self .info ):
208
- return type
238
+
239
+ for type , is_type_of in self .possible_types_with_is_type_of :
240
+ if is_type_of (result , context , self .info ):
241
+ return type
209
242
210
243
def resolve (self , root ):
211
244
_type = self .resolve_type (root )
0 commit comments