11# Licensed under a 3-clause BSD style license - see LICENSE.rst
2- import requests
2+ import pprint
33from bs4 import BeautifulSoup
44from astropy .extern .six .moves .urllib import parse as urlparse
55from astropy .extern import six
@@ -23,9 +23,9 @@ def __init__(self):
2323 self ._default_form_values = None
2424
2525 def _get_default_form_values (self , form ):
26- """Return the already selected values of a given form (a BeautifulSoup
26+ """
27+ Return the already selected values of a given form (a BeautifulSoup
2728 form node) as a dict.
28-
2929 """
3030 res = []
3131 for elem in form .find_all (['input' , 'select' ]):
@@ -48,20 +48,21 @@ def _get_default_form_values(self, form):
4848 if option .get ('selected' ) == '' :
4949 value = option .get ('value' , option .text .strip ())
5050 res .append ((elem .get ('name' ), value ))
51- return dict (
52- (k , v ) for (k , v ) in res if v not in [None , u'None' , u'null' ] and v
53- )
51+ return {k :v
52+ for (k , v ) in res
53+ if v not in [None , u'None' , u'null' ] and v
54+ }
5455
55- def _submit_form (self , input = None ):
56- """Fill out the form of the SkyView site and submit it with the
56+ def _generate_payload (self , input = None ):
57+ """
58+ Fill out the form of the SkyView site and submit it with the
5759 values given in `input` (a dictionary where the keys are the form
5860 element's names and the values are their respective values).
59-
6061 """
6162 if input is None :
6263 input = {}
63- response = requests . get ( self .URL )
64- bs = BeautifulSoup (response .content )
64+ form_response = self . _request ( 'GET' , self .URL )
65+ bs = BeautifulSoup (form_response .content , "html.parser" )
6566 form = bs .find ('form' )
6667 # cache the default values to save HTTP traffic
6768 if self ._default_form_values is None :
@@ -73,14 +74,19 @@ def _submit_form(self, input=None):
7374 if v is not None :
7475 payload [k ] = v
7576 url = urlparse .urljoin (self .URL , form .get ('action' ))
76- response = requests .get (url , params = payload )
77+ return url , payload
78+
79+ def _submit_form (self , input = None , cache = True ):
80+ url , payload = self ._generate_payload (input = input )
81+ response = self ._request ('GET' , url , params = payload , cache = cache )
7782 return response
7883
79- def get_images (
80- self , position , survey , coordinates = None , projection = None ,
81- pixels = None , scaling = None , sampler = None , resolver = None ,
82- deedger = None , lut = None , grid = None , gridlabels = None ):
83- """Query the SkyView service, download the FITS file that will be
84+ def get_images (self , position , survey , coordinates = None , projection = None ,
85+ pixels = None , scaling = None , sampler = None , resolver = None ,
86+ deedger = None , lut = None , grid = None , gridlabels = None ,
87+ cache = True ):
88+ """
89+ Query the SkyView service, download the FITS file that will be
8490 found and return a generator over the local paths to the
8591 downloaded FITS files.
8692
@@ -177,33 +183,34 @@ def get_images(
177183 A list of `astropy.fits.HDUList` objects
178184
179185 """
180- readable_objects = self .get_images_async (
181- position , survey , coordinates , projection ,
182- pixels , scaling , sampler , resolver ,
183- deedger , lut , grid , gridlabels )
186+ readable_objects = self .get_images_async (position , survey , coordinates ,
187+ projection , pixels , scaling ,
188+ sampler , resolver , deedger ,
189+ lut , grid , gridlabels ,
190+ cache = cache )
184191 return [obj .get_fits () for obj in readable_objects ]
185192
186193 @prepend_docstr_noreturns (get_images .__doc__ )
187- def get_images_async (
188- self , position , survey , coordinates = None , projection = None ,
189- pixels = None , scaling = None , sampler = None , resolver = None ,
190- deedger = None , lut = None , grid = None , gridlabels = None ):
194+ def get_images_async (self , position , survey , coordinates = None ,
195+ projection = None , pixels = None , scaling = None ,
196+ sampler = None , resolver = None , deedger = None , lut = None ,
197+ grid = None , gridlabels = None , cache = True ):
191198 """
192199 Returns
193200 -------
194201 A list of context-managers that yield readable file-like objects
195202 """
196- image_urls = self .get_image_list (
197- position , survey , coordinates , projection ,
198- pixels , scaling , sampler , resolver ,
199- deedger , lut , grid , gridlabels )
203+ image_urls = self .get_image_list (position , survey , coordinates ,
204+ projection , pixels , scaling , sampler ,
205+ resolver , deedger , lut , grid ,
206+ gridlabels , cache = cache )
200207 return [commons .FileContainer (url ) for url in image_urls ]
201208
202209 @prepend_docstr_noreturns (get_images .__doc__ )
203- def get_image_list (
204- self , position , survey , coordinates = None , projection = None ,
205- pixels = None , scaling = None , sampler = None , resolver = None ,
206- deedger = None , lut = None , grid = None , gridlabels = None ):
210+ def get_image_list (self , position , survey , coordinates = None ,
211+ projection = None , pixels = None , scaling = None ,
212+ sampler = None , resolver = None , deedger = None , lut = None ,
213+ grid = None , gridlabels = None , cache = True ):
207214 """
208215 Returns
209216 -------
@@ -216,6 +223,9 @@ def get_image_list(
216223 u'http://skyview.gsfc.nasa.gov/tempspace/fits/skv6183161285798_2.fits',
217224 u'http://skyview.gsfc.nasa.gov/tempspace/fits/skv6183161285798_3.fits']
218225 """
226+
227+ self ._validate_surveys (survey )
228+
219229 input = {
220230 'Position' : position ,
221231 'survey' : survey ,
@@ -229,17 +239,50 @@ def get_image_list(
229239 'resolver' : resolver ,
230240 'Sampler' : sampler ,
231241 'pixels' : pixels }
232- response = self ._submit_form (input )
242+ response = self ._submit_form (input , cache = cache )
233243 urls = self ._parse_response (response )
234244 return urls
235245
236246 def _parse_response (self , response ):
237- bs = BeautifulSoup (response .content )
247+ bs = BeautifulSoup (response .content , "html.parser" )
238248 urls = []
239249 for a in bs .find_all ('a' ):
240250 if a .text == 'FITS' :
241251 href = a .get ('href' )
242252 urls .append (urlparse .urljoin (response .url , href ))
243253 return urls
244254
255+ @property
256+ def survey_dict (self ):
257+ if not hasattr (self , '_survey_dict' ):
258+
259+ response = self ._request ('GET' , self .URL )
260+ page = BeautifulSoup (response .content , "html.parser" )
261+ surveys = page .findAll ('select' , {'name' :'survey' })
262+
263+ self ._survey_dict = {sel ['id' ]:[x .text for x in sel .findAll ('option' )]
264+ for sel in surveys }
265+ return self ._survey_dict
266+
267+ @property
268+ def _valid_surveys (self ):
269+ # Return a flat list of all valid surveys
270+ return [x for v in self .survey_dict .values () for x in v ]
271+
272+ def _validate_surveys (self , surveys ):
273+ if not isinstance (surveys , list ):
274+ surveys = [surveys ]
275+
276+ for sv in surveys :
277+ if sv not in self ._valid_surveys :
278+ raise ValueError ("Survey is not among the surveys hosted "
279+ "at skyview. See list_surveys or "
280+ "survey_dict for valid surveys." )
281+
282+ def list_surveys (self ):
283+ """
284+ Print out a formatted version of the survey dict
285+ """
286+ pprint .pprint (self .survey_dict )
287+
245288SkyView = SkyViewClass ()
0 commit comments