17
17
# under the License.
18
18
#
19
19
20
- import abc
21
20
import datetime
22
21
import six
23
22
from grakn .service .Session .util import enums
@@ -117,13 +116,19 @@ def from_grpc_value_object(grpc_value_object):
117
116
def iter_res_to_iterator (tx_service , iterator_id , next_iteration_handler ):
118
117
return ResponseIterator (tx_service , iterator_id , next_iteration_handler )
119
118
119
+ @staticmethod
120
+ def create_explanation (tx_service , grpc_explanation_res ):
121
+ """ Convert gRPC explanation response to explanation object """
122
+ grpc_list_of_concept_maps = grpc_explanation_res .explanation
123
+ native_list_of_concept_maps = []
124
+ for grpc_concept_map in grpc_list_of_concept_maps :
125
+ native_list_of_concept_maps .append (AnswerConverter ._create_concept_map (tx_service , grpc_concept_map ))
126
+ return Explanation (native_list_of_concept_maps )
127
+
120
128
class Explanation (object ):
121
- def __init__ ( self , query_pattern , list_of_concept_maps ):
122
- self . _query_pattern = query_pattern
129
+
130
+ def __init__ ( self , list_of_concept_maps ):
123
131
self ._concept_maps_list = list_of_concept_maps
124
-
125
- def query_pattern (self ):
126
- return self ._query_pattern
127
132
128
133
def get_answers (self ):
129
134
""" Return answers this explanation is dependent on"""
@@ -133,24 +138,9 @@ def get_answers(self):
133
138
134
139
# ----- Different types of answers -----
135
140
136
- class Answer (object ):
137
- """ Top level answer, provides interface """
138
-
139
- def __init__ (self , explanation ):
140
- self ._explanation = explanation
141
- __init__ .__annotations__ = {'explanation' : Explanation }
142
-
143
- @abc .abstractmethod
144
- def get (self ):
145
- pass
141
+ class AnswerGroup (object ):
146
142
147
- def explanation (self ):
148
- return self ._explanation
149
-
150
- class AnswerGroup (Answer ):
151
-
152
- def __init__ (self , owner_concept , answer_list , explanation ):
153
- super (AnswerGroup , self ).__init__ (explanation )
143
+ def __init__ (self , owner_concept , answer_list ):
154
144
self ._owner_concept = owner_concept
155
145
self ._answer_list = answer_list
156
146
@@ -164,12 +154,13 @@ def answers(self):
164
154
return self ._answer_list
165
155
166
156
157
+ class ConceptMap (object ):
167
158
168
- class ConceptMap ( Answer ):
169
-
170
- def __init__ ( self , concept_map , explanations ):
171
- super ( ConceptMap , self ). __init__ ( explanations )
172
- self ._concept_map = concept_map
159
+ def __init__ ( self , concept_map , query_pattern , has_explanation , tx_service ):
160
+ self . _concept_map = concept_map
161
+ self . _has_explanation = has_explanation
162
+ self . _query_pattern = query_pattern
163
+ self ._tx_service = tx_service
173
164
174
165
def get (self , var = None ):
175
166
""" Get the indicated variable's Concept from the map or this ConceptMap """
@@ -180,9 +171,19 @@ def get(self, var=None):
180
171
# TODO specialize exception
181
172
raise GraknError ("Variable {0} is not in the ConceptMap" .format (var ))
182
173
return self ._concept_map [var ]
183
- """ Return ConceptMap """
184
- return self
185
-
174
+
175
+ def query_pattern (self ):
176
+ return self ._query_pattern
177
+
178
+ def has_explanation (self ):
179
+ return self ._has_explanation
180
+
181
+ def explanation (self ):
182
+ if self ._has_explanation :
183
+ return self ._tx_service .explanation (self )
184
+ else :
185
+ raise GraknError ("Explanation not available on concept map: " + str (self ))
186
+
186
187
def map (self ):
187
188
""" Get the map from Variable (str) to Concept objects """
188
189
return self ._concept_map
@@ -199,67 +200,54 @@ def is_empty(self):
199
200
""" Check if the variable map is empty """
200
201
return len (self ._concept_map ) == 0
201
202
202
- class ConceptList (Answer ):
203
203
204
- def __init__ (self , concept_id_list , explanation ):
205
- super (ConceptList , self ).__init__ (explanation )
206
- self ._concept_id_list = concept_id_list
207
- __init__ .__annotations__ = {'explanation' : Explanation }
204
+ class ConceptList (object ):
208
205
209
- def get (self ):
210
- """ Get this ConceptList """
211
- return self ._concept_id_list
206
+ def __init__ (self , concept_id_list ):
207
+ self ._concept_id_list = concept_id_list
212
208
213
209
def list (self ):
214
210
""" Get the list of concept IDs """
215
211
return self ._concept_id_list
216
212
217
- class ConceptSet (Answer ):
218
213
219
- def __init__ (self , concept_id_set , explanation ):
220
- super (ConceptSet , self ).__init__ (explanation )
221
- self ._concept_id_set = concept_id_set
222
- __init__ .__annotations__ = {'explanation' : Explanation }
214
+ class ConceptSet (object ):
223
215
224
- def get (self ):
225
- """ Get this ConceptSet """
226
- return self
216
+ def __init__ (self , concept_id_set ):
217
+ self . _concept_id_set = concept_id_set
218
+ __init__ . __annotations__ = { '_concept_id_set' : 'List[str]' }
227
219
228
220
def set (self ):
229
221
""" Return the set of Concept IDs within this ConceptSet """
230
222
return self ._concept_id_set
231
223
224
+
232
225
class ConceptSetMeasure (ConceptSet ):
233
226
234
- def __init__ (self , concept_id_set , number , explanation ):
235
- super (ConceptSetMeasure , self ).__init__ (concept_id_set , explanation )
227
+ def __init__ (self , concept_id_set , number ):
228
+ super (ConceptSetMeasure , self ).__init__ (concept_id_set )
236
229
self ._measurement = number
237
- __init__ .__annotations__ = {'explanation ' : Explanation }
230
+ __init__ .__annotations__ = {'_measurement ' : float }
238
231
239
232
def measurement (self ):
240
233
return self ._measurement
241
234
242
235
243
- class Value (Answer ):
236
+ class Value (object ):
244
237
245
- def __init__ (self , number , explanation ):
246
- super (Value , self ).__init__ (explanation )
238
+ def __init__ (self , number ):
247
239
self ._number = number
248
- __init__ .__annotations__ = {'explanation' : Explanation }
249
-
250
- def get (self ):
251
- """ Get this Value object """
252
- return self
240
+ __init__ .__annotations__ = {'number' : float }
253
241
254
242
def number (self ):
255
243
""" Get as number (float or int) """
256
244
return self ._number
257
245
258
- class Void (Answer ):
246
+
247
+ class Void (object ):
259
248
def __init__ (self , message ):
260
- super (Void , self ).__init__ (None )
261
249
self ._message = message
262
- __init__ .__annotations__ = {'explanation' : Explanation , ' message' : str }
250
+ __init__ .__annotations__ = {'message' : str }
263
251
264
252
def message (self ):
265
253
""" Get the message on this Void answer type """
@@ -274,7 +262,7 @@ def convert(tx_service, grpc_answer):
274
262
which_one = grpc_answer .WhichOneof ('answer' )
275
263
276
264
if which_one == 'conceptMap' :
277
- return AnswerConverter ._create_concept_map (tx_service , grpc_answer .conceptMap )
265
+ return AnswerConverter ._create_concept_map (tx_service , grpc_answer .conceptMap )
278
266
elif which_one == 'answerGroup' :
279
267
return AnswerConverter ._create_answer_group (tx_service , grpc_answer .answerGroup )
280
268
elif which_one == 'conceptList' :
@@ -298,56 +286,39 @@ def _create_concept_map(tx_service, grpc_concept_map_msg):
298
286
for (variable , grpc_concept ) in var_concept_map .items ():
299
287
answer_map [variable ] = ConceptFactory .create_concept (tx_service , grpc_concept )
300
288
301
- # build explanation
302
- explanation = AnswerConverter ._create_explanation (tx_service , grpc_concept_map_msg .explanation )
303
- return ConceptMap (answer_map , explanation )
289
+ query_pattern = grpc_concept_map_msg .pattern
290
+ has_explanation = grpc_concept_map_msg .hasExplanation
291
+
292
+ return ConceptMap (answer_map , query_pattern , has_explanation , tx_service )
304
293
305
294
@staticmethod
306
295
def _create_answer_group (tx_service , grpc_answer_group ):
307
296
grpc_owner_concept = grpc_answer_group .owner
308
297
owner_concept = ConceptFactory .create_concept (tx_service , grpc_owner_concept )
309
298
grpc_answers = list (grpc_answer_group .answers )
310
299
answer_list = [AnswerConverter .convert (tx_service , grpc_answer ) for grpc_answer in grpc_answers ]
311
- explanation = AnswerConverter ._create_explanation (tx_service , grpc_answer_group .explanation )
312
- return AnswerGroup (owner_concept , answer_list , explanation )
300
+ return AnswerGroup (owner_concept , answer_list )
313
301
314
302
@staticmethod
315
303
def _create_concept_list (tx_service , grpc_concept_list_msg ):
316
304
ids_list = list (grpc_concept_list_msg .list .ids )
317
- # build explanation
318
- explanation = AnswerConverter ._create_explanation (tx_service , grpc_concept_list_msg .explanation )
319
- return ConceptList (ids_list , explanation )
305
+ return ConceptList (ids_list )
320
306
321
307
@staticmethod
322
308
def _create_concept_set (tx_service , grpc_concept_set_msg ):
323
309
ids_set = set (grpc_concept_set_msg .set .ids )
324
- # build explanation
325
- explanation = AnswerConverter ._create_explanation (tx_service , grpc_concept_set_msg .explanation )
326
- return ConceptSet (ids_set , explanation )
310
+ return ConceptSet (ids_set )
327
311
328
312
@staticmethod
329
313
def _create_concept_set_measure (tx_service , grpc_concept_set_measure ):
330
314
concept_ids = list (grpc_concept_set_measure .set .ids )
331
315
number = grpc_concept_set_measure .measurement .value
332
- explanation = AnswerConverter ._create_explanation (tx_service , grpc_concept_set_measure .explanation )
333
- return ConceptSetMeasure (concept_ids , AnswerConverter ._number_string_to_native (number ), explanation )
316
+ return ConceptSetMeasure (concept_ids , AnswerConverter ._number_string_to_native (number ))
334
317
335
318
@staticmethod
336
319
def _create_value (tx_service , grpc_value_msg ):
337
320
number = grpc_value_msg .number .value
338
- # build explanation
339
- explanation = AnswerConverter ._create_explanation (tx_service , grpc_value_msg .explanation )
340
- return Value (AnswerConverter ._number_string_to_native (number ), explanation )
341
-
342
- @staticmethod
343
- def _create_explanation (tx_service , grpc_explanation ):
344
- """ Convert grpc Explanation message into object """
345
- query_pattern = grpc_explanation .pattern
346
- grpc_list_of_concept_maps = grpc_explanation .answers
347
- native_list_of_concept_maps = []
348
- for grpc_concept_map in grpc_list_of_concept_maps :
349
- native_list_of_concept_maps .append (AnswerConverter ._create_concept_map (tx_service , grpc_concept_map ))
350
- return Explanation (query_pattern , native_list_of_concept_maps )
321
+ return Value (AnswerConverter ._number_string_to_native (number ))
351
322
352
323
@staticmethod
353
324
def _create_void (tx_service , grpc_void ):
@@ -362,7 +333,6 @@ def _number_string_to_native(number):
362
333
return float (number )
363
334
364
335
365
-
366
336
class ResponseIterator (six .Iterator ):
367
337
""" Retrieves next value in the Grakn response iterator """
368
338
@@ -389,7 +359,7 @@ def collect_concepts(self):
389
359
""" Helper method to retrieve concepts from a query() method """
390
360
concepts = []
391
361
for answer in self :
392
- if type (answer ) != ConceptMap :
362
+ if not isinstance (answer , ConceptMap ) :
393
363
raise GraknError ("Only use .collect_concepts on ConceptMaps returned by query()" )
394
364
concepts .extend (answer .map ().values ()) # get concept map => concepts
395
365
return concepts
0 commit comments