def history(self, date, lat=None, lon=None, us_city=None): latlon_location_param = None us_city_location_param = None if lat and lon: latlon_location_param = '{0},{1}'.format(lat,lon) # Try for US city first, since this will be more reusable if us_city: # Split on comma to extract state if us_city.count(',') != 1: self.log.info("Unable to parse city/state for us city: {0}".format(us_city)) else: city_parts = [part.strip() for part in us_city.split(',')] if len(city_parts[-1]) > 2: # US states are 2-chars self.log.info("Doesn't look like a US city (state component > 2 chars): {0}".format(us_city)) else: us_city_location_param = city_parts[-1] + "/" + city_parts[0].replace(' ', '_') # Check both for cache, starting with more specific one for lp in (latlon_location_param, us_city_location_param): if lp is not None: data = self._check_cache(lp, date) if data: break if data is None: if not self.cache_only: # Attempt to fetch for real (and cache), giving preference to the less specific # for the sake of better reusability for lp in (us_city_location_param, latlon_location_param): if lp is not None: try: res = self.get(date.strftime('history_%Y%m%d'), 'q', lp) except Fault: self.log.info("Server fault trying to fetch weather for {0},{1}".format(lp, date)) continue else: break else: # We tried all param options but each had an error raise NoDataFound("Unable to retrieve weather for lat/lon={0}, us_city={1}, date={2}".format((lat,lon), us_city, date)) # res should be defined if we get this far. data = res.json() self._write_cache(lp, date, data) else: raise NoDataFound("cache_only=True and no cached data found for lat/lon={0}, us_city={1}, date={2}".format((lat,lon), us_city, date)) try: history_data = HistoryDay.from_json(data['history']) except: self.log.exception("Unable to parse data: {0!r}".format(data)) raise return history_data
def history(self, date, lat=None, lon=None, us_city=None): latlon_location_param = None us_city_location_param = None if lat and lon: latlon_location_param = '{0},{1}'.format(lat, lon) # Try for US city first, since this will be more reusable if us_city: # Split on comma to extract state if us_city.count(',') != 1: self.log.info("Unable to parse city/state for us city: {0}".format(us_city)) else: state_code = None city_parts = [part.strip() for part in us_city.split(',')] if len(city_parts[-1]) > 2: # US states are 2-chars if city_parts[-1] in state_name_to_abbrev_map: state_code = state_name_to_abbrev_map[city_parts[-1]] else: self.log.debug("State len > 2 and not in name -> abbrev map: {0!r}".format(city_parts[-1])) else: state_code = city_parts[-1] if state_code: us_city_location_param = state_code + "/" + city_parts[0].replace(' ', '_') else: self.log.info("Unable to parse US state from {0!r}.".format(us_city)) # Check both for cache, starting with more specific one data = None for lp in (latlon_location_param, us_city_location_param): if lp is not None: data = self._check_cache(lp, date) if data: break if data is None: if not self.cache_only: # Attempt to fetch for real (and cache), giving preference to the less specific # for the sake of better reusability for lp in (us_city_location_param, latlon_location_param): if lp is not None: try: res = self.get(date.strftime('history_%Y%m%d'), 'q', lp) except Fault: self.log.info("Server fault trying to fetch weather for {0},{1}".format(lp, date)) continue else: data = res.json() if 'history' in data and data['history'].get('observations'): # Do not break if we don't have a valid JSON response break else: # We tried all param options but each had an error raise NoDataFound( "Unable to retrieve weather for lat/lon={0}, us_city={1}, date={2}".format((lat, lon), us_city, date)) # data should be non-null if we get here. self._write_cache(lp, date, data) else: raise NoDataFound( "cache_only=True and no cached data found for lat/lon={0}, us_city={1}, date={2}".format((lat, lon), us_city, date)) try: history_data = HistoryDay.from_json(data['history']) except: self.log.exception("Unable to parse data: {0!r}".format(data)) raise return history_data