10
10
import uuid
11
11
import json
12
12
import time
13
+ import re
13
14
14
15
import numpy as np
15
16
@@ -210,7 +211,39 @@ def _request(self, method, url, params=None, data=None, headers=None,
210
211
211
212
return all_responses
212
213
213
- def _get_col_config (self , service , fetch_name = None ):
214
+ def _request_w_cache (self , method , url , data = None , headers = None , retrieve_all = True ,
215
+ cache = False , cache_opts = None ):
216
+ # Note: the method only exposes 4 parameters of the underlying _request() function
217
+ # to play nice with existing mocks
218
+ # Caching: follow BaseQuery._request()'s pattern, which uses an AstroQuery object
219
+ if not cache :
220
+ response = self ._request (method , url , data = data , headers = headers , retrieve_all = retrieve_all )
221
+ else :
222
+ cacher = self ._get_cacher (method , url , data , headers , retrieve_all )
223
+ response = cacher .from_cache (self .cache_location )
224
+ if not response :
225
+ response = self ._request (method , url , data = data , headers = headers , retrieve_all = retrieve_all )
226
+ to_cache (response , cacher .request_file (self .cache_location ))
227
+ return response
228
+
229
+ def _get_cacher (self , method , url , data , headers , retrieve_all ):
230
+ """
231
+ Return an object that can cache the HTTP request based on the supplied arguments
232
+ """
233
+
234
+ # cacheBreaker parameter (to underlying MAST service) is not relevant (and breaks) local caching
235
+ # remove it from part of the cache key
236
+ data_no_cache_breaker = re .sub (r'^(.+)cacheBreaker%22%3A%20%22.+%22' , r'\1' , data )
237
+ # include retrieve_all as part of the cache key by appending it to data
238
+ # it cannot be added as part of req_kwargs dict, as it will be rejected by AstroQuery
239
+ data_w_retrieve_all = data_no_cache_breaker + " retrieve_all={}" .format (retrieve_all )
240
+ req_kwargs = dict (
241
+ data = data_no_cache_breaker ,
242
+ headers = headers
243
+ )
244
+ return AstroQuery (method , url , ** req_kwargs )
245
+
246
+ def _get_col_config (self , service , fetch_name = None , cache = False ):
214
247
"""
215
248
Gets the columnsConfig entry for given service and stores it in `self._column_configs`.
216
249
@@ -246,7 +279,7 @@ def _get_col_config(self, service, fetch_name=None):
246
279
if more :
247
280
mashup_request = {'service' : all_name , 'params' : {}, 'format' : 'extjs' }
248
281
req_string = _prepare_service_request_string (mashup_request )
249
- response = self ._request ("POST" , self .MAST_REQUEST_URL , data = req_string , headers = headers )
282
+ response = self ._request_w_cache ("POST" , self .MAST_REQUEST_URL , data = req_string , headers = headers , cache = cache )
250
283
json_response = response [0 ].json ()
251
284
252
285
self ._column_configs [service ].update (json_response ['data' ]['Tables' ][0 ]
@@ -300,7 +333,7 @@ def _parse_result(self, responses, verbose=False):
300
333
return all_results
301
334
302
335
@class_or_instance
303
- def service_request_async (self , service , params , pagesize = None , page = None , ** kwargs ):
336
+ def service_request_async (self , service , params , pagesize = None , page = None , cache = False , cache_opts = None , ** kwargs ):
304
337
"""
305
338
Given a Mashup service and parameters, builds and excecutes a Mashup query.
306
339
See documentation `here <https://mast.stsci.edu/api/v0/class_mashup_1_1_mashup_request.html>`__
@@ -320,6 +353,10 @@ def service_request_async(self, service, params, pagesize=None, page=None, **kwa
320
353
Default None.
321
354
Can be used to override the default behavior of all results being returned to obtain
322
355
a specific page of results.
356
+ cache : Boolean, optional
357
+ try to use cached the query result if set to True
358
+ cache_opts : dict, optional
359
+ cache options, details TBD, e.g., cache expiration policy, etc.
323
360
**kwargs :
324
361
See MashupRequest properties
325
362
`here <https://mast.stsci.edu/api/v0/class_mashup_1_1_mashup_request.html>`__
@@ -333,7 +370,7 @@ def service_request_async(self, service, params, pagesize=None, page=None, **kwa
333
370
# setting self._current_service
334
371
if service not in self ._column_configs .keys ():
335
372
fetch_name = kwargs .pop ('fetch_name' , None )
336
- self ._get_col_config (service , fetch_name )
373
+ self ._get_col_config (service , fetch_name , cache )
337
374
self ._current_service = service
338
375
339
376
# setting up pagination
@@ -359,12 +396,12 @@ def service_request_async(self, service, params, pagesize=None, page=None, **kwa
359
396
mashup_request [prop ] = value
360
397
361
398
req_string = _prepare_service_request_string (mashup_request )
362
- response = self ._request ("POST" , self .MAST_REQUEST_URL , data = req_string , headers = headers ,
363
- retrieve_all = retrieve_all )
399
+ response = self ._request_w_cache ("POST" , self .MAST_REQUEST_URL , data = req_string , headers = headers ,
400
+ retrieve_all = retrieve_all , cache = cache , cache_opts = cache_opts )
364
401
365
402
return response
366
403
367
- def build_filter_set (self , column_config_name , service_name = None , ** filters ):
404
+ def build_filter_set (self , column_config_name , service_name = None , cache = False , ** filters ):
368
405
"""
369
406
Takes user input dictionary of filters and returns a filterlist that the Mashup can understand.
370
407
@@ -392,7 +429,7 @@ def build_filter_set(self, column_config_name, service_name=None, **filters):
392
429
service_name = column_config_name
393
430
394
431
if not self ._column_configs .get (service_name ):
395
- self ._get_col_config (service_name , fetch_name = column_config_name )
432
+ self ._get_col_config (service_name , fetch_name = column_config_name , cache = cache )
396
433
397
434
caom_col_config = self ._column_configs [service_name ]
398
435
0 commit comments