def parse_JSON(self, JSON_string): """ Parses a `pyowm.alertapi30.alert.Alert` instance out of raw JSON data. :param JSON_string: a raw JSON string :type JSON_string: str :return: a `pyowm.alertapi30.alert.Alert` instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) try: alert_id = d['_id'] t = d['last_update'].split('.')[0].replace('T', ' ') + '+00' alert_last_update = timeformatutils._ISO8601_to_UNIXtime(t) alert_trigger_id = d['triggerId'] alert_met_conds = [ dict(current_value=c['current_value']['min'], condition=Condition.from_dict(c['condition'])) for c in d['conditions'] ] alert_coords = d['coordinates'] return Alert(alert_id, alert_trigger_id, alert_met_conds, alert_coords, last_update=alert_last_update) except ValueError as e: raise parse_response_error.ParseResponseError('Impossible to parse JSON: %s' % e) except KeyError as e: raise parse_response_error.ParseResponseError('Impossible to parse JSON: %s' % e)
def parse_JSON(self, JSON_string): """ Parses a *pyowm.stationsapi30.station.Station* instance out of raw JSON data. :param JSON_string: a raw JSON string :type JSON_string: str :return: a *pyowm.stationsapi30.station.Station** instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) try: id = d.get('ID', None) or d.get('id', None) external_id = d.get('external_id', None) lon = d.get('longitude', None) lat = d.get('latitude', None) alt = d.get('altitude', None) except KeyError as e: raise parse_response_error.ParseResponseError('Impossible to parse JSON: %s' % e) name = d.get('name', None) rank = d.get('rank', None) created_at = d.get('created_at', None) updated_at = d.get('updated_at', None) return Station(id, created_at, updated_at, external_id, name, lon, lat, alt, rank)
def parse_JSON(self, JSON_string): """ Parses a *Forecast* 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 JSON_string: a raw JSON string :type JSON_string: str :returns: a *Forecast* instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the JSON string embeds an HTTP status error (this is an OWM web API 2.5 bug) """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) # 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 d and 'cod' in d: if d['cod'] == "404": print( "OWM API: data not found - response payload: " + json.dumps(d), d['cod']) return None elif d['cod'] != "200": raise api_response_error.APIResponseError( "OWM API: error - response payload: " + json.dumps(d), d['cod']) try: place = location.location_from_dictionary(d) except KeyError: raise parse_response_error.ParseResponseError(''.join([ __name__, ': impossible to read location info from JSON data' ])) # Handle the case when no results are found if 'count' in d and d['count'] == "0": weathers = [] elif 'cnt' in d and d['cnt'] == 0: weathers = [] else: if 'list' in d: try: weathers = [weather.weather_from_dictionary(item) \ for item in d['list']] except KeyError: raise parse_response_error.ParseResponseError( ''.join([__name__, ': impossible to read weather ' \ 'info from JSON data']) ) else: raise parse_response_error.ParseResponseError( ''.join([__name__, ': impossible to read weather ' \ 'list from JSON data']) ) current_time = int(round(time.time())) return forecast.Forecast(None, current_time, place, weathers)
def parse_JSON(self, JSON_string): """ Parses a *Station* 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 JSON_string: a raw JSON string :type JSON_string: str :returns: a *Station* instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the JSON string embeds an HTTP status error """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) try: name = d['station']['name'] station_ID = d['station']['id'] station_type = d['station']['type'] status = d['station']['status'] lat = d['station']['coord']['lat'] if 'lon' in d['station']['coord']: lon = d['station']['coord']['lon'] elif 'lng' in d['station']['coord']: lon = d['station']['coord']['lng'] else: lon = None if 'distance' in d: distance = d['distance'] else: distance = None except KeyError as e: error_msg = ''.join(( __name__, ': unable to read JSON data', )) raise parse_response_error.ParseResponseError(error_msg) else: if 'last' in d: last_weather = weather.weather_from_dictionary(d['last']) else: last_weather = None return station.Station(name, station_ID, station_type, status, lat, lon, distance, last_weather)
def parse_JSON(self, JSON_string): """ Parses a *pyowm.stationsapi30.measurement.AggregatedMeasurement* instance out of raw JSON data. :param JSON_string: a raw JSON string :type JSON_string: str :return: a *pyowm.stationsapi30.measurement.AggregatedMeasurement* instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) station_id = d.get('station_id', None) ts = d.get('date', None) if ts is not None: ts = int(ts) aggregated_on = d.get('type', None) temp = d.get('temp', dict()) humidity = d.get('humidity', dict()) wind = d.get('wind', dict()) pressure = d.get('pressure', dict()) precipitation = d.get('precipitation', dict()) return AggregatedMeasurement(station_id, ts, aggregated_on, temp=temp, humidity=humidity, wind=wind, pressure=pressure, precipitation=precipitation)
def get_json(self, uri, params=None, headers=None): resp = requests.get(uri, params=params, headers=headers) HttpClient.check_status_code(resp.status_code, resp.text) try: return resp.status_code, resp.json() except: raise parse_response_error.ParseResponseError('Impossible to parse' 'API response data')
def parse_JSON(self, JSON_string): """ Parses an *Observation* 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 JSON_string: a raw JSON string :type JSON_string: str :returns: an *Observation* instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the JSON string embeds an HTTP status error (this is an OWM web API 2.5 bug) """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = loads(JSON_string) # 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 d and 'cod' in d: if d['cod'] == "404": print("OWM API: observation data not available - response " \ "payload: " + dumps(d)) return None else: raise api_response_error.APIResponseError( "OWM API: error - response payload: " + \ dumps(d)) try: place = location.location_from_dictionary(d) except KeyError: raise parse_response_error.ParseResponseError( ''.join([__name__, ': impossible to ' \ 'read location info from JSON data'])) try: w = weather.weather_from_dictionary(d) except KeyError: raise parse_response_error.ParseResponseError( ''.join([__name__, ': impossible to ' \ 'read weather info from JSON data'])) current_time = int(round(time())) return observation.Observation(current_time, place, w)
def parse_JSON(self, JSON_string): """ Parses an *NO2Index* 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 JSON_string: a raw JSON string :type JSON_string: str :returns: an *NO2Index* instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the JSON string embeds an HTTP status error (this is an OWM web API 2.5 bug) """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) try: # -- reference time (strip away Z and T on ISO8601 format) t = d['time'].replace('Z', '+00').replace('T', ' ') reference_time = timeformatutils._ISO8601_to_UNIXtime(t) # -- reception time (now) reception_time = timeutils.now('unix') # -- location lon = float(d['location']['longitude']) lat = float(d['location']['latitude']) place = location.Location(None, lon, lat, None) # -- CO samples no2_samples = [ dict(label=key, precision=d['data'][key]['precision'], value=d['data'][key]['value']) for key in d['data'] ] except KeyError: raise parse_response_error.ParseResponseError(''.join( [__name__, ': impossible to parse NO2Index'])) return no2index.NO2Index(reference_time, place, None, no2_samples, reception_time)
def parse_JSON(self, JSON_string): """ Parses an *Ozone* 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 JSON_string: a raw JSON string :type JSON_string: str :returns: an *Ozone* instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the JSON string embeds an HTTP status error (this is an OWM web API 2.5 bug) """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) try: # -- reference time (strip away Z and T on ISO8601 format) ref_t = d['time'].replace('Z', '+00').replace('T', ' ') reference_time = timeformatutils._ISO8601_to_UNIXtime(ref_t) # -- reception time (now) reception_time = timeutils.now('unix') # -- location lon = float(d['location']['longitude']) lat = float(d['location']['latitude']) place = location.Location(None, lon, lat, None) # -- ozone Dobson Units value du = d['data'] if du is not None: du_value = float(du) else: raise ValueError('No information about Ozon Dobson Units') except KeyError: raise parse_response_error.ParseResponseError(''.join( [__name__, ': impossible to parse UV Index'])) return ozone.Ozone(reference_time, place, None, du_value, reception_time)
def parse_JSON(self, JSON_string): """ 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 JSON_string: a raw JSON string :type JSON_string: str :returns: an *UVIndex* instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the JSON string embeds an HTTP status error (this is an OWM web API 2.5 bug) """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) try: # -- reference time reference_time = d['date'] # -- reception time (now) reception_time = timeutils.now('unix') # -- location lon = float(d['lon']) lat = float(d['lat']) place = location.Location(None, lon, lat, None) # -- UV intensity uv_intensity = float(d['value']) except KeyError: raise parse_response_error.ParseResponseError(''.join( [__name__, ': impossible to parse UV Index'])) return uvindex.UVIndex(reference_time, place, uv_intensity, reception_time)
def get_json(self, uri, params=None, headers=None): try: resp = requests.get(uri, params=params, headers=headers, timeout=self.timeout, verify=self.verify_ssl_certs) except requests.exceptions.SSLError as e: raise api_call_error.APIInvalidSSLCertificateError(str(e)) except requests.exceptions.ConnectionError as e: raise api_call_error.APIInvalidSSLCertificateError(str(e)) except requests.exceptions.Timeout: raise api_call_error.APICallTimeoutError('API call timeouted') HttpClient.check_status_code(resp.status_code, resp.text) try: return resp.status_code, resp.json() except: raise parse_response_error.ParseResponseError('Impossible to parse' 'API response data')
def parse_JSON(self, JSON_string): """ Parses a list of *UVIndex* instances 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 JSON_string: a raw JSON string :type JSON_string: str :returns: a list of *UVIndex* instances or an empty list if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the JSON string embeds an HTTP status error """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) uvindex_parser = UVIndexParser() return [uvindex_parser.parse_JSON(json.dumps(item)) for item in d]
def get_geotiff(self, uri, params=None, headers=None): if headers is None: headers = {'Accept': ImageTypeEnum.GEOTIFF.mime_type} else: headers.update({'Accept': ImageTypeEnum.GEOTIFF.mime_type}) try: resp = requests.get(uri, stream=True, params=params, headers=headers, timeout=self.timeout, verify=self.verify_ssl_certs) except requests.exceptions.SSLError as e: raise api_call_error.APIInvalidSSLCertificateError(str(e)) except requests.exceptions.ConnectionError as e: raise api_call_error.APIInvalidSSLCertificateError(str(e)) except requests.exceptions.Timeout: raise api_call_error.APICallTimeoutError('API call timeouted') HttpClient.check_status_code(resp.status_code, resp.text) try: return resp.status_code, resp.content except: raise parse_response_error.ParseResponseError('Impossible to parse' 'API response data')
def parse_JSON(self, JSON_string): """ Parses a *StatioHistory* 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 JSON_string: a raw JSON string :type JSON_string: str :returns: a *StatioHistory* instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the JSON string embeds an HTTP status error (this is an OWM web API 2.5 bug) """ d = json.loads(JSON_string) # 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 api_response_error.APIResponseError( "OWM API: error - response " + \ "payload: " + str(d)) 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 parse_response_error.ParseResponseError(__name__ + \ ': impossible to read JSON data') current_time = round(time.time()) return stationhistory.StationHistory(None, None, current_time, measurements)
def parse_JSON(self, JSON_string): """ Parses a `pyowm.alertapi30.trigger.Trigger` instance out of raw JSON data. As per OWM documentation, start and end times are expressed with respect to the moment when you create/update the Trigger. By design, PyOWM will only allow users to specify *absolute* datetimes - which is, with the `exact` expression - for start/end timestamps (will otherwise result in a `ParseResponseError` be raised) :param JSON_string: a raw JSON string :type JSON_string: str :return: a `pyowm.alertapi30.trigger.Trigger` instance or ``None`` if no data is available :raises: *ParseResponseError* if it is impossible to find or parse the data needed to build the result """ if JSON_string is None: raise parse_response_error.ParseResponseError('JSON data is None') d = json.loads(JSON_string) try: # trigger id trigger_id = d.get('_id', None) # start timestamp start_dict = d['time_period']['start'] expr = start_dict['expression'] if expr != 'after': raise ValueError('Invalid time expression: "%s" on start timestamp. Only: "after" is supported' % expr) start = start_dict['amount'] # end timestamp end_dict = d['time_period']['end'] expr = end_dict['expression'] if expr != 'after': raise ValueError('Invalid time expression: "%s" on end timestamp. Only: "after" is supported' % expr) end = end_dict['amount'] # conditions conditions = [Condition.from_dict(c) for c in d['conditions']] # alerts alerts_dict = d['alerts'] alerts = list() for key in alerts_dict: alert_id = key alert_data = alerts_dict[alert_id] alert_last_update = alert_data['last_update'] alert_met_conds = [ dict(current_value=c['current_value']['min'], condition=Condition.from_dict(c['condition'])) for c in alert_data['conditions'] ] alert_coords = alert_data['coordinates'] alert = Alert(alert_id, trigger_id, alert_met_conds, alert_coords, last_update=alert_last_update) alerts.append(alert) # area area_list = d['area'] area = [GeometryBuilder.build(a_dict) for a_dict in area_list] # alert channels alert_channels = None # defaulting except ValueError as e: raise parse_response_error.ParseResponseError('Impossible to parse JSON: %s' % e) except KeyError as e: raise parse_response_error.ParseResponseError('Impossible to parse JSON: %s' % e) return Trigger(start, end, conditions, area=area, alerts=alerts, alert_channels=alert_channels, id=trigger_id)