def from_dict(cls, the_dict): """ Parses a *COIndex* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *COIndex* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') try: # -- reference time (strip away Z and T on ISO8601 format) t = the_dict['time'].replace('Z', '+00:00').replace('T', ' ') reference_time = formatting.ISO8601_to_UNIXtime(t) # -- reception time (now) reception_time = timestamps.now('unix') # -- location lon = float(the_dict['location']['longitude']) lat = float(the_dict['location']['latitude']) place = location.Location(None, lon, lat, None) # -- CO samples co_samples = the_dict['data'] except KeyError: raise exceptions.ParseAPIResponseError( ''.join([__name__, ': impossible to parse COIndex'])) return COIndex(reference_time, place, None, co_samples, reception_time)
def from_dict(cls, the_dict): """ Parses a *Alert* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *Alert* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') try: alert_id = the_dict['_id'] t = the_dict['last_update'].split('.')[0].replace('T', ' ') + '+00' alert_last_update = formatting.ISO8601_to_UNIXtime(t) alert_trigger_id = the_dict['triggerId'] alert_met_conds = [ dict(current_value=c['current_value']['min'], condition=Condition.from_dict(c['condition'])) for c in the_dict['conditions'] ] alert_coords = the_dict['coordinates'] return Alert(alert_id, alert_trigger_id, alert_met_conds, alert_coords, last_update=alert_last_update) except ValueError as e: raise exceptions.ParseAPIResponseError( 'Impossible to parse JSON: %s' % e) except KeyError as e: raise exceptions.ParseAPIResponseError( 'Impossible to parse JSON: %s' % e)
def from_dict(cls, the_dict): """ Parses a *NationalWeatherAlert* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *NationalWeatherAlert* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') try: sender = the_dict['sender_name'] title = the_dict['event'] description = the_dict['description'] start_time = the_dict['start'] end_time = the_dict['end'] except KeyError: raise exceptions.ParseAPIResponseError('Invalid data payload') tags = the_dict.get('tags', []) return NationalWeatherAlert(sender, title, description, start_time, end_time, tags)
def from_dict(cls, the_dict): """ Parses an *UVIndex* instance out of raw JSON data. Only certain properties of the data are used: if these properties are not found or cannot be parsed, an error is issued. :param the_dict: the input dict :type the_dict: dict :returns: an *UVIndex* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the input dict embeds an HTTP status error """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') try: # -- reference time reference_time = the_dict['date'] # -- reception time (now) reception_time = timestamps.now('unix') # -- location lon = float(the_dict['lon']) lat = float(the_dict['lat']) place = location.Location(None, lon, lat, None) # -- UV intensity uv_intensity = float(the_dict['value']) except KeyError: raise exceptions.ParseAPIResponseError(''.join( [__name__, ': impossible to parse UV Index'])) return UVIndex(reference_time, place, uv_intensity, reception_time)
def from_dict(cls, the_dict: dict): """ Parses a *OneCall* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *OneCall* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the input dict embeds an HTTP status error """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') # Check if server returned errors: this check overcomes the lack of use # of HTTP error status codes by the OWM API 2.5. This mechanism is # supposed to be deprecated as soon as the API fully adopts HTTP for # conveying errors to the clients if 'message' in the_dict and 'cod' in the_dict: if the_dict['cod'] == "404": return None elif the_dict['cod'] == "429": raise exceptions.APIResponseError( "OWM API: error - Exceeded call limit", the_dict['cod']) else: raise exceptions.APIResponseError( "OWM API: error - response payload", the_dict['cod']) try: current = Weather.from_dict(the_dict["current"]) minutely = None if "minutely" in the_dict: minutely = [ Weather.from_dict(item) for item in the_dict["minutely"] ] hourly = None if "hourly" in the_dict: hourly = [ Weather.from_dict(item) for item in the_dict["hourly"] ] daily = None if "daily" in the_dict: daily = [Weather.from_dict(item) for item in the_dict["daily"]] except KeyError: raise exceptions.ParseAPIResponseError( f"{__name__}: impossible to read weather info from input data") return OneCall(lat=the_dict.get("lat", None), lon=the_dict.get("lon", None), timezone=the_dict.get("timezone", None), current=current, forecast_minutely=minutely, forecast_hourly=hourly, forecast_daily=daily)
def from_dict(cls, the_dict): """ Parses a *Forecast* instance out of a raw data dictionary. Only certain properties of the data are used: if these properties are not found or cannot be parsed, an error is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *Forecast* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the input dictionary embeds an HTTP status error """ if the_dict is None: raise exceptions.ParseAPIResponseError('JSON data is None') # Check if server returned errors: this check overcomes the lack of use # of HTTP error status codes by the OWM API 2.5. This mechanism is # supposed to be deprecated as soon as the API fully adopts HTTP for # conveying errors to the clients if 'message' in the_dict and 'cod' in the_dict: if the_dict['cod'] == "404": print("OWM API: data not found - response payload", the_dict['cod']) return None elif the_dict['cod'] != "200": raise exceptions.APIResponseError( "OWM API: error - response payload", the_dict['cod']) try: place = location.Location.from_dict(the_dict) except KeyError: raise exceptions.ParseAPIResponseError(''.join([ __name__, ': impossible to read location info from JSON data' ])) # Handle the case when no results are found if 'count' in the_dict and the_dict['count'] == "0": weathers = [] elif 'cnt' in the_dict and the_dict['cnt'] == 0: weathers = [] else: if 'list' in the_dict: try: weathers = [weather.Weather.from_dict(item) \ for item in the_dict['list']] except KeyError: raise exceptions.ParseAPIResponseError(''.join([ __name__, ': impossible to read weather info from JSON data' ])) else: raise exceptions.ParseAPIResponseError(''.join([ __name__, ': impossible to read weather list from JSON data' ])) current_time = int(time.time()) return Forecast(None, current_time, place, weathers)
def from_dict(cls, the_dict): if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') try: weather_param = the_dict['name'] operator = the_dict['expression'] amount = the_dict['amount'] the_id = the_dict.get('_id', None) return Condition(weather_param, operator, amount, id=the_id) except KeyError as e: raise exceptions.ParseAPIResponseError( 'Impossible to parse data: %s' % e)
def get_geotiff(self, path, params=None, headers=None): builder = HttpRequestBuilder(self.root_uri, self.api_key, self.config, has_subdomains=self.admits_subdomains)\ .with_path(path)\ .with_api_key()\ .with_language()\ .with_query_params(params if params is not None else dict())\ .with_headers(headers if headers is not None else dict())\ .with_header('Accept', ImageTypeEnum.GEOTIFF.mime_type) url, params, headers, proxies = builder.build() try: resp = requests.get(url, stream=True, params=params, headers=headers, proxies=proxies, timeout=self.config['connection']['timeout_secs'], verify=self.config['connection']['verify_ssl_certs']) except requests.exceptions.SSLError as e: raise exceptions.InvalidSSLCertificateError(str(e)) except requests.exceptions.ConnectionError as e: raise exceptions.InvalidSSLCertificateError(str(e)) except requests.exceptions.Timeout: raise exceptions.TimeoutError('API call timeouted') HttpClient.check_status_code(resp.status_code, resp.text) try: return resp.status_code, resp.content except: raise exceptions.ParseAPIResponseError('Impossible to parse' 'API response data')
def from_dict_of_lists(cls, the_dict): """ Parses a list of *Weather* instances out of an input dict. Only certain properties of the data are used: if these properties are not found or cannot be parsed, an error is issued. :param the_dict: the input dict :type the_dict: dict :returns: a list of *Weather* instances or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the input dict an HTTP status error """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') # Check if server returned errors: this check overcomes the lack of use # of HTTP error status codes by the OWM API 2.5. This mechanism is # supposed to be deprecated as soon as the API fully adopts HTTP for # conveying errors to the clients if 'message' in the_dict and 'cod' in the_dict: if the_dict['cod'] == "404": print("OWM API: data not found - response payload: " + \ json.dumps(the_dict)) return None elif the_dict['cod'] != "200": raise exceptions.APIResponseError( "OWM API: error - response payload: " + json.dumps(the_dict), the_dict['cod']) # Handle the case when no results are found if 'cnt' in the_dict and the_dict['cnt'] == "0": return [] else: if 'list' in the_dict: try: return [ Weather.from_dict(item) for item in the_dict['list'] ] except KeyError: raise exceptions.ParseAPIResponseError(''.join([ __name__, ': impossible to read weather info from input data' ])) else: raise exceptions.ParseAPIResponseError(''.join([ __name__, ': impossible to read weather list from input data' ]))
def from_dict_of_lists(self, the_dict): """ Parses a list of *Observation* instances out of raw input dict containing a list. Only certain properties of the data are used: if these properties are not found or cannot be parsed, an error is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a `list` of *Observation* instances or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the OWM API returns an HTTP status error """ if the_dict is None: raise exceptions.ParseAPIResponseError('JSON data is None') if 'cod' in the_dict: # Check if server returned errors: this check overcomes the lack of use # of HTTP error status codes by the OWM API 2.5. This mechanism is # supposed to be deprecated as soon as the API fully adopts HTTP for # conveying errors to the clients if the_dict['cod'] == "200" or the_dict['cod'] == 200: pass else: if the_dict['cod'] == "404" or the_dict['cod'] == 404: print("OWM API: data not found") return None else: raise exceptions.APIResponseError( "OWM API: error - response payload", the_dict['cod']) # Handle the case when no results are found if 'count' in the_dict and the_dict['count'] == "0": return [] if 'cnt' in the_dict and the_dict['cnt'] == 0: return [] if 'list' in the_dict: return [Observation.from_dict(item) for item in the_dict['list']] # no way out.. raise exceptions.ParseAPIResponseError(''.join( [__name__, ': impossible to read JSON data']))
def from_dict(cls, the_dict): """ Parses an *Observation* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: an *Observation* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the input dict embeds an HTTP status error """ if the_dict is None: raise exceptions.ParseAPIResponseError('JSON data is None') # Check if server returned errors: this check overcomes the lack of use # of HTTP error status codes by the OWM API 2.5. This mechanism is # supposed to be deprecated as soon as the API fully adopts HTTP for # conveying errors to the clients if 'message' in the_dict and 'cod' in the_dict: if the_dict['cod'] != "404": raise exceptions.APIResponseError( "OWM API: error - response payload", the_dict['cod']) print("OWM API: observation data not available") return None try: place = location.Location.from_dict(the_dict) except KeyError: raise exceptions.ParseAPIResponseError(''.join([ __name__, ': impossible to read location info from JSON data' ])) try: w = weather.Weather.from_dict(the_dict) except KeyError: raise exceptions.ParseAPIResponseError(''.join( [__name__, ': impossible to read weather info from JSON data'])) current_time = int(time.time()) return Observation(current_time, place, w)
def from_dict(cls, the_dict): """ Parses a *Location* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *Location* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') country = None if 'sys' in the_dict and 'country' in the_dict['sys']: country = the_dict['sys']['country'] if 'city' in the_dict: data = the_dict['city'] else: data = the_dict if 'name' in data: name = data['name'] else: name = None if 'id' in data: ID = int(data['id']) else: ID = None if 'coord' in data: lon = data['coord'].get('lon', 0.0) lat = data['coord'].get('lat', 0.0) elif 'station' in data and 'coord' in data['station']: if 'lon' in data['station']['coord']: lon = data['station']['coord'].get('lon', 0.0) elif 'lng' in data['station']['coord']: lon = data['station']['coord'].get('lng', 0.0) else: lon = 0.0 lat = data['station']['coord'].get('lat', 0.0) else: raise KeyError("Impossible to read geographical coordinates from JSON") if 'country' in data: country = data['country'] return Location(name, lon, lat, ID, country)
def from_dict(cls, the_dict): """ Parses a *Station* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *Station* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') id = the_dict.get('ID', None) or the_dict.get('id', None) external_id = the_dict.get('external_id', None) lon = the_dict.get('longitude', None) lat = the_dict.get('latitude', None) alt = the_dict.get('altitude', None) name = the_dict.get('name', None) rank = the_dict.get('rank', None) created_at = the_dict.get('created_at', None) updated_at = the_dict.get('updated_at', None) return Station(id, created_at, updated_at, external_id, name, lon, lat, alt, rank)
def get_geotiff(self, path, params=None, headers=None): # check URL fromt the metaimage: if it looks like a complete URL, use that one (I know, it's a hack...) try: partial_path = path.split(self.root_uri)[1].lstrip('/') except: partial_path = '' # fallback so that a 404 is issued builder = HttpRequestBuilder(self.root_uri, self.api_key, self.config, has_subdomains=self.admits_subdomains)\ .with_path(partial_path)\ .with_api_key()\ .with_language()\ .with_query_params(params if params is not None else dict())\ .with_headers(headers if headers is not None else dict())\ .with_header('Accept', ImageTypeEnum.GEOTIFF.mime_type) url, params, headers, proxies = builder.build() try: resp = self.http.get( url, stream=True, params=params, headers=headers, proxies=proxies, timeout=self.config['connection']['timeout_secs'], verify=self.config['connection']['verify_ssl_certs']) except requests.exceptions.SSLError as e: raise exceptions.InvalidSSLCertificateError(str(e)) except requests.exceptions.ConnectionError as e: raise exceptions.InvalidSSLCertificateError(str(e)) except requests.exceptions.Timeout: raise exceptions.TimeoutError('API call timeouted') HttpClient.check_status_code(resp.status_code, resp.text) try: return resp.status_code, resp.content except: raise exceptions.ParseAPIResponseError('Impossible to parse' 'API response data')
def from_dict(cls, the_dict): """ Parses a *Weather* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *Weather* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the input dict embeds an HTTP status error """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') # -- times reference_time = 0 if 'dt' in the_dict: reference_time = the_dict['dt'] elif 'dt' in the_dict['last']: reference_time = the_dict['last']['dt'] if 'sunset' in the_dict: sunset_time = the_dict['sunset'] elif 'sys' in the_dict and 'sunset' in the_dict['sys']: sunset_time = the_dict['sys']['sunset'] else: sunset_time = None if 'sunrise' in the_dict: sunrise_time = the_dict['sunrise'] elif 'sys' in the_dict and 'sunrise' in the_dict['sys']: sunrise_time = the_dict['sys']['sunrise'] else: sunrise_time = None # -- calc dewpoint = None humidex = None heat_index = None if 'calc' in the_dict: if 'dewpoint' in the_dict['calc']: dewpoint = the_dict['calc']['dewpoint'] if 'humidex' in the_dict['calc']: humidex = the_dict['calc']['humidex'] if 'heatindex' in the_dict['calc']: heat_index = the_dict['calc']['heatindex'] elif 'last' in the_dict: if 'calc' in the_dict['last']: if 'dewpoint' in the_dict['last']['calc']: dewpoint = the_dict['last']['calc']['dewpoint'] if 'humidex' in the_dict['last']['calc']: humidex = the_dict['last']['calc']['humidex'] if 'heatindex' in the_dict['last']['calc']: heat_index = the_dict['last']['calc']['heatindex'] if 'dew_point' in the_dict and dewpoint is None: dewpoint = the_dict.get('dew_point', None) # -- visibility visibility_distance = None if 'visibility' in the_dict: if isinstance(the_dict['visibility'], int): visibility_distance = the_dict['visibility'] elif 'distance' in the_dict['visibility']: visibility_distance = the_dict['visibility']['distance'] elif 'last' in the_dict and 'visibility' in the_dict['last']: if isinstance(the_dict['last']['visibility'], int) or isinstance( the_dict['last']['visibility'], float): visibility_distance = the_dict['last']['visibility'] elif 'distance' in the_dict['last']['visibility']: visibility_distance = the_dict['last']['visibility'][ 'distance'] # -- clouds clouds = 0 if 'clouds' in the_dict: if isinstance(the_dict['clouds'], int) or isinstance( the_dict['clouds'], float): clouds = the_dict['clouds'] elif 'all' in the_dict['clouds']: clouds = the_dict['clouds']['all'] # -- precipitation workaround if 'precipitation' in the_dict and 'rain' not in the_dict: the_dict['rain'] = the_dict['precipitation'] # -- rain rain = dict() if 'rain' in the_dict: if isinstance(the_dict['rain'], int) or isinstance( the_dict['rain'], float): rain = {'all': the_dict['rain']} else: if the_dict['rain'] is not None: rain = the_dict['rain'].copy() # -- wind wind = dict() if 'wind' in the_dict and the_dict['wind'] is not None: wind = the_dict['wind'].copy() elif 'last' in the_dict: if 'wind' in the_dict['last'] and the_dict['last'][ 'wind'] is not None: wind = the_dict['last']['wind'].copy() else: if 'speed' in the_dict: wind['speed'] = the_dict['speed'] elif 'wind_speed' in the_dict: wind['speed'] = the_dict.get('wind_speed', 0) if 'deg' in the_dict: wind['deg'] = the_dict['deg'] elif 'wind_deg' in the_dict: wind['deg'] = the_dict.get('wind_deg', 0) if 'wind_gust' in the_dict: wind['gust'] = the_dict.get('wind_gust', 0) # -- humidity if 'humidity' in the_dict: humidity = the_dict['humidity'] elif 'main' in the_dict and 'humidity' in the_dict['main']: humidity = the_dict['main']['humidity'] elif 'last' in the_dict and 'main' in the_dict[ 'last'] and 'humidity' in the_dict['last']['main']: humidity = the_dict['last']['main']['humidity'] else: humidity = 0 # -- snow snow = dict() if 'snow' in the_dict: if isinstance(the_dict['snow'], int) or isinstance( the_dict['snow'], float): snow = {'all': the_dict['snow']} else: if the_dict['snow'] is not None: snow = the_dict['snow'].copy() # -- pressure atm_press = None if 'pressure' in the_dict: atm_press = the_dict['pressure'] elif 'main' in the_dict and 'pressure' in the_dict['main']: atm_press = the_dict['main']['pressure'] elif 'last' in the_dict: if 'main' in the_dict['last']: atm_press = the_dict['last']['main']['pressure'] sea_level_press = None if 'main' in the_dict and 'sea_level' in the_dict['main']: sea_level_press = the_dict['main']['sea_level'] pressure = {'press': atm_press, 'sea_level': sea_level_press} # -- temperature temperature = dict() if 'temp' in the_dict: if isinstance(the_dict['temp'], int) or isinstance( the_dict['temp'], float): temperature = {'temp': the_dict.get('temp', None)} elif the_dict['temp'] is not None: temperature = the_dict['temp'].copy() elif 'main' in the_dict and 'temp' in the_dict['main']: temp_dic = the_dict['main'] temperature = { 'temp': temp_dic['temp'], 'temp_kf': temp_dic.get('temp_kf', None), 'temp_max': temp_dic.get('temp_max', None), 'temp_min': temp_dic.get('temp_min', None), 'feels_like': temp_dic.get('feels_like', None) } elif 'last' in the_dict: if 'main' in the_dict['last']: temperature = dict(temp=the_dict['last']['main']['temp']) # add feels_like to temperature if present if 'feels_like' in the_dict: feels_like = the_dict['feels_like'] if isinstance(feels_like, int) or isinstance(feels_like, float): temperature['feels_like'] = the_dict.get('feels_like', None) elif isinstance(feels_like, dict): for label, temp in feels_like.items(): temperature[f'feels_like_{label}'] = temp # -- weather status info if 'weather' in the_dict: status = the_dict['weather'][0]['main'] detailed_status = the_dict['weather'][0]['description'] weather_code = the_dict['weather'][0]['id'] weather_icon_name = the_dict['weather'][0]['icon'] else: status = '' detailed_status = '' weather_code = 0 weather_icon_name = '' # -- timezone if 'timezone' in the_dict: utc_offset = the_dict['timezone'] else: utc_offset = None # -- UV index uvi = the_dict.get('uvi', None) return Weather(reference_time, sunset_time, sunrise_time, clouds, rain, snow, wind, humidity, pressure, temperature, status, detailed_status, weather_code, weather_icon_name, visibility_distance, dewpoint, humidex, heat_index, utc_offset=utc_offset, uvi=uvi)
def from_dict(cls, d): """ Parses a *StationHistory* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *StationHistory* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the input dict embeds an HTTP status error """ if d is None: raise exceptions.ParseAPIResponseError('Data is None') # Check if server returned errors: this check overcomes the lack of use # of HTTP error status codes by the OWM API but it's supposed to be # deprecated as soon as the API implements a correct HTTP mechanism for # communicating errors to the clients. In addition, in this specific # case the OWM API responses are the very same either when no results # are found for a station and when the station does not exist! measurements = {} try: if 'cod' in d: if d['cod'] != "200": raise exceptions.APIResponseError( "OWM API: error - response payload: " + str(d), d['cod']) if str(d['cnt']) == "0": return None else: for item in d['list']: if 'temp' not in item: temp = None elif isinstance(item['temp'], dict): temp = item['temp']['v'] else: temp = item['temp'] if 'humidity' not in item: hum = None elif isinstance(item['humidity'], dict): hum = item['humidity']['v'] else: hum = item['humidity'] if 'pressure' not in item: pres = None elif isinstance(item['pressure'], dict): pres = item['pressure']['v'] else: pres = item['pressure'] if 'rain' in item and isinstance(item['rain']['today'], dict): rain = item['rain']['today']['v'] else: rain = None if 'wind' in item and isinstance(item['wind']['speed'], dict): wind = item['wind']['speed']['v'] else: wind = None measurements[item['dt']] = { "temperature": temp, "humidity": hum, "pressure": pres, "rain": rain, "wind": wind } except KeyError: raise exceptions.ParseAPIResponseError( __name__ + ': impossible to read input data') current_time = int(time.time()) return StationHistory(None, None, current_time, measurements)