Example #1
0
 def test_get_alerts(self):
     cond = Condition('humidity', 'LESS_THAN', 10)
     alert1 = Alert('alert1', 'trigger1', [{
         "current_value": 263.576,
         "condition": cond
     }], {
         "lon": 37,
         "lat": 53
     }, 1481802090232)
     alert2 = Alert('alert2', 'trigger1', [{
         "current_value": 111.576,
         "condition": cond
     }], {
         "lon": 37,
         "lat": 53
     }, 1481802100000)
     alerts = [alert1, alert2]
     instance = Trigger(1526809375,
                        1527809375, [cond], [geo.Point(13.6, 46.9)],
                        alerts=alerts,
                        alert_channels=None)
     result = instance.get_alerts()
     self.assertTrue(isinstance(result, list))
     self.assertTrue(alert1 in result)
     self.assertTrue(alert2 in result)
Example #2
0
    def test_get_alerts_since(self):
        cond = Condition('humidity', 'LESS_THAN', 10)
        alert1 = Alert('alert1', 'trigger1', [{
            "current_value": 263.576,
            "condition": cond
        }], {
            "lon": 37,
            "lat": 53
        }, 1000)
        alert2 = Alert('alert2', 'trigger1', [{
            "current_value": 111.576,
            "condition": cond
        }], {
            "lon": 37,
            "lat": 53
        }, 3000)
        alert3 = Alert('alert3', 'trigger1', [{
            "current_value": 119.332,
            "condition": cond
        }], {
            "lon": 37,
            "lat": 53
        }, 9000)
        alert4 = Alert('alert4', 'trigger1', [{
            "current_value": 119.332,
            "condition": cond
        }], {
            "lon": 37,
            "lat": 53
        }, 12000)
        alerts = [alert1, alert2, alert3, alert4]
        instance = Trigger(1526809375,
                           1527809375, [cond], [geo.Point(13.6, 46.9)],
                           alerts=alerts,
                           alert_channels=None)

        result = instance.get_alerts_since(4000)
        self.assertEqual(2, len(result))
        self.assertTrue(alert3 in result)
        self.assertTrue(alert4 in result)

        result = instance.get_alerts_since(3000)
        self.assertEqual(3, len(result))
        self.assertTrue(alert2 in result)
        self.assertTrue(alert3 in result)
        self.assertTrue(alert4 in result)

        result = instance.get_alerts_since(15000)
        self.assertEqual(0, len(result))
Example #3
0
    def test_get_alerts_on(self):
        cond1 = Condition('humidity', 'LESS_THAN', 10)
        cond2 = Condition('temp', 'GREATER_THAN_EQUAL', 100.6)
        alert1 = Alert('alert1', 'trigger1', [{
            "current_value": 8.576,
            "condition": cond1
        }], {
            "lon": 37,
            "lat": 53
        }, 1000)
        alert2 = Alert('alert2', 'trigger1', [{
            "current_value": 111.576,
            "condition": cond2
        }], {
            "lon": 37,
            "lat": 53
        }, 3000)
        alert3 = Alert('alert3', 'trigger1', [{
            "current_value": 119.332,
            "condition": cond2
        }], {
            "lon": 37,
            "lat": 53
        }, 9000)
        alert4 = Alert('alert4', 'trigger1', [{
            "current_value": 7.332,
            "condition": cond1
        }], {
            "lon": 37,
            "lat": 53
        }, 12000)
        alerts = [alert1, alert2, alert3, alert4]
        instance = Trigger(1526809375,
                           1527809375, [cond1, cond2], [geo.Point(13.6, 46.9)],
                           alerts=alerts,
                           alert_channels=None)
        result = instance.get_alerts_on('temp')
        self.assertEqual(2, len(result))
        self.assertTrue(alert2 in result)
        self.assertTrue(alert3 in result)

        result = instance.get_alerts_on('humidity')
        self.assertEqual(2, len(result))
        self.assertTrue(alert1 in result)
        self.assertTrue(alert4 in result)

        result = instance.get_alerts_on('wind_direction')
        self.assertEqual(0, len(result))
 def test_to_dict(self):
     condition = Condition('humidity', 'LESS_THAN', 10)
     instance = Alert('alert1', 'trigger1', [{
         "current_value": 263.576,
         "condition": condition.to_dict()}],
         {"lon": 37, "lat": 53},
         1481802090232)
     result = instance.to_dict()
     self.assertIsInstance(result, dict)
     self.assertEqual('alert1', result['id'])
     self.assertEqual('trigger1', result['trigger_id'])
     self.assertEqual(1, len(result['met_conditions']))
     mc = result['met_conditions'][0]
     self.assertEqual(dict(current_value=263.576, condition=condition.to_dict()), mc)
     self.assertEqual({"lon": 37, "lat": 53}, result['coordinates'])
     self.assertEqual(1481802090232, result['last_update'])
    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 test_repr(self):
     the_dict = {
      '_id': '5853dbe27416a400011b1b77',
      'conditions': [{'_id': '5853dbe27416a400011b1b78',
                      'condition': {'amount': 273, 'expression': '$lt', 'name': 'temp'},
                      'current_value': {'max': 258.62, 'min': 258.62}}],
      'coordinates': {'lat': '53', 'lon': '37'},
      'date': '2016-12-17T00:00:00.000Z',
      'last_update': '2016-12-16T11:19:46.352Z',
      'triggerId': '5852816a9aaacb00153134a3'}
     instance = Alert.from_dict(the_dict)
     print(instance)
 def get_alerts_for(self, trigger):
     """
     Retrieves all of the alerts that were fired for the specified Trigger
     :param trigger: the trigger
     :type trigger: `pyowm.alertapi30.trigger.Trigger`
     :return: list of `pyowm.alertapi30.alert.Alert` objects
     """
     assert trigger is not None
     assert isinstance(trigger.id, str), "Value must be a string"
     status, data = self.http_client.get_json(
         ALERTS_URI % trigger.id,
         params={'appid': self.API_key},
         headers={'Content-Type': 'application/json'})
     return [Alert.from_dict(item) for item in data]
Example #8
0
 def test_get_alert(self):
     cond = Condition('humidity', 'LESS_THAN', 10)
     alert = Alert('alert1', 'trigger1', [{
         "current_value": 263.576,
         "condition": cond
     }], {
         "lon": 37,
         "lat": 53
     }, 1481802090232)
     alerts = [alert]
     instance = Trigger(1526809375,
                        1527809375, [cond], [geo.Point(13.6, 46.9)],
                        alerts=alerts,
                        alert_channels=None)
     self.assertEqual(alert, instance.get_alert('alert1'))
 def get_alert(self, alert_id, trigger):
     """
     Retrieves info about the alert record on the Alert API that has the specified ID and belongs to the specified
     parent Trigger object
     :param trigger: the parent trigger
     :type trigger: `pyowm.alertapi30.trigger.Trigger`
     :param alert_id: the ID of the alert
     :type alert_id `pyowm.alertapi30.alert.Alert`
     :return: an `pyowm.alertapi30.alert.Alert` instance
     """
     assert trigger is not None
     assert alert_id is not None
     assert isinstance(alert_id, str), "Value must be a string"
     assert isinstance(trigger.id, str), "Value must be a string"
     status, data = self.http_client.get_json(
         NAMED_ALERT_URI % (trigger.id, alert_id),
         params={'appid': self.API_key},
         headers={'Content-Type': 'application/json'})
     return Alert.from_dict(data)
    def test_get_alert(self):
        cond = Condition('humidity', 'LESS_THAN', 10)
        alert = Alert('alert1', 'trigger1', [{
            "current_value": 263.576,
            "condition": cond
        }], {
            "lon": 37,
            "lat": 53
        }, 1481802090232)
        alert_two = copy.deepcopy(alert)
        alert_two.id = 'alert_two'
        alerts = [alert_two, alert
                  ]  # Second alert has to be 1st element to have full coverage
        instance = Trigger(1526809375,
                           1527809375, [cond], [geo.Point(13.6, 46.9)],
                           alerts=alerts,
                           alert_channels=None)
        self.assertEqual(alert, instance.get_alert('alert1'))

        # Trigger without alerts
        instance.alerts = []
        self.assertIsNone(instance.get_alert(alert_id='alert1'))
    def test_from_dict(self):
        the_dict = {
         '_id': '5853dbe27416a400011b1b77',
         'conditions': [{'_id': '5853dbe27416a400011b1b78',
                         'condition': {'amount': 273, 'expression': '$lt', 'name': 'temp'},
                         'current_value': {'max': 258.62, 'min': 258.62}}],
         'coordinates': {'lat': '53', 'lon': '37'},
         'date': '2016-12-17T00:00:00.000Z',
         'last_update': '2016-12-16T11:19:46.352Z',
         'triggerId': '5852816a9aaacb00153134a3'}
        result = Alert.from_dict(the_dict)
        self.assertIsInstance(result, Alert)

        with self.assertRaises(pyowm.commons.exceptions.ParseAPIResponseError):
            Alert.from_dict(None)

        with self.assertRaises(pyowm.commons.exceptions.ParseAPIResponseError):
            Alert.from_dict(dict(nonexistent='key'))

        value_error_dict = copy.deepcopy(the_dict)
        value_error_dict['last_update'] = 'not_valid_timestamp'
        with self.assertRaises(pyowm.commons.exceptions.ParseAPIResponseError):
            Alert.from_dict(value_error_dict)
 def test_alert_last_updated_is_none(self):
     alert = Alert('alert1', 'trigger1', [{
         "current_value": 263.576,
         "condition": Condition('humidity', 'LESS_THAN', 10)}],
                   {"lon": 37, "lat": 53})
     self.assertIsNone(alert.last_update)
Example #13
0
    def from_dict(cls, the_dict):
        if the_dict is None:
            raise pyowm.commons.exceptions.ParseAPIResponseError(
                'Data is None')
        try:
            # trigger id
            trigger_id = the_dict.get('_id', None)

            # start timestamp
            start_dict = the_dict['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 = the_dict['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 the_dict['conditions']
            ]

            # alerts
            alerts_dict = the_dict['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 = []
                for c in alert_data['conditions']:
                    if isinstance(c['current_value'], int):
                        cv = c['current_value']
                    else:
                        cv = c['current_value']['min']
                    item = dict(current_value=cv,
                                condition=Condition.from_dict(c['condition']))
                    alert_met_conds.append(item)
                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 = the_dict['area']
            area = [GeometryBuilder.build(a_dict) for a_dict in area_list]

            # alert channels
            alert_channels = None  # defaulting

        except ValueError as e:
            raise pyowm.commons.exceptions.ParseAPIResponseError(
                'Impossible to parse JSON: %s' % e)

        except KeyError as e:
            raise pyowm.commons.exceptions.ParseAPIResponseError(
                'Impossible to parse JSON: %s' % e)

        return Trigger(start,
                       end,
                       conditions,
                       area=area,
                       alerts=alerts,
                       alert_channels=alert_channels,
                       id=trigger_id)
Example #14
0
    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)
Example #15
0
class TestAlertManager(unittest.TestCase):
    _cond1 = Condition('humidity', 'LESS_THAN', 10)
    _cond2 = Condition('temp', 'GREATER_THAN_EQUAL', 100.6)
    _trigger = Trigger(1526809375,
                       1527809375, [_cond1, _cond2], [geo.Point(13.6, 46.9)],
                       alerts=[],
                       alert_channels=None,
                       id='trigger-id')
    _alert = Alert('alert1', 'trigger1', [{
        "current_value": 263.576,
        "condition": _cond1
    }], {
        "lon": 37,
        "lat": 53
    }, 1481802090232)

    def factory(self, _kls):
        sm = AlertManager('APIKey')
        sm.http_client = _kls()
        return sm

    def test_instantiation_fails_without_api_key(self):
        self.assertRaises(AssertionError, AlertManager, None)

    def test_get_alert_api_version(self):
        instance = AlertManager('APIKey')
        result = instance.alert_api_version()
        self.assertIsInstance(result, tuple)
        self.assertEqual(result, ALERT_API_VERSION)

    def test_get_triggers(self):
        instance = self.factory(MockHttpClientTwoTriggers)
        results = instance.get_triggers()
        self.assertEqual(2, len(results))
        t = results[0]
        self.assertIsInstance(t, Trigger)

    def test_get_trigger_fails_with_wrong_input(self):
        instance = AlertManager('APIKey')
        with self.assertRaises(AssertionError):
            instance.get_trigger(None)
        with self.assertRaises(AssertionError):
            instance.get_trigger(123)

    def test_get_trigger(self):
        instance = self.factory(MockHttpClientOneTrigger)
        result = instance.get_trigger('any-id')
        self.assertIsInstance(result, Trigger)

    def test_create_trigger(self):
        instance = self.factory(MockHttpClient)
        result = instance.create_trigger(1526809375,
                                         1527809375,
                                         [self._cond1, self._cond2],
                                         [geo.Point(13.6, 46.9)],
                                         alert_channels=None)
        self.assertIsInstance(result, Trigger)

    def test_create_trigger_fails_with_wrong_inputs(self):
        instance = self.factory(MockHttpClient)
        with self.assertRaises(AssertionError):
            instance.create_trigger(None,
                                    1527809375, [self._cond1, self._cond2],
                                    [geo.Point(13.6, 46.9)],
                                    alert_channels=None)
        with self.assertRaises(AssertionError):
            instance.create_trigger(1526809375,
                                    None, [self._cond1, self._cond2],
                                    [geo.Point(13.6, 46.9)],
                                    alert_channels=None)
        with self.assertRaises(ValueError):
            instance.create_trigger(1526809375,
                                    1327809375, [self._cond1, self._cond2],
                                    [geo.Point(13.6, 46.9)],
                                    alert_channels=None)
        with self.assertRaises(AssertionError):
            instance.create_trigger(1526809375,
                                    1527809375,
                                    None, [geo.Point(13.6, 46.9)],
                                    alert_channels=None)
        with self.assertRaises(ValueError):
            instance.create_trigger(1526809375,
                                    1527809375, [], [geo.Point(13.6, 46.9)],
                                    alert_channels=None)
        with self.assertRaises(AssertionError):
            instance.create_trigger(1526809375,
                                    1527809375, [self._cond1, self._cond2],
                                    None,
                                    alert_channels=None)
        with self.assertRaises(ValueError):
            instance.create_trigger(1526809375,
                                    1527809375, [self._cond1, self._cond2], [],
                                    alert_channels=None)

    def test_delete_trigger_fails_with_wrong_input(self):
        instance = AlertManager('APIKey')
        with self.assertRaises(AssertionError):
            instance.delete_trigger(None)
        with self.assertRaises(AssertionError):
            self._trigger.id = 123
            instance.delete_trigger(self._trigger)

    def test_delete_trigger(self):
        instance = self.factory(MockHttpClient)
        parser = TriggerParser()
        trigger = parser.parse_JSON(MockHttpClient.test_trigger_json)
        result = instance.delete_trigger(trigger)
        self.assertIsNone(result)

    def test_update_trigger_fails_with_wrong_input(self):
        instance = AlertManager('APIKey')
        with self.assertRaises(AssertionError):
            instance.update_trigger(None)
        with self.assertRaises(AssertionError):
            self._trigger.id = 123
            instance.update_trigger(self._trigger)

    def test_update_trigger(self):
        instance = self.factory(MockHttpClient)
        parser = TriggerParser()
        modified_trigger = parser.parse_JSON(MockHttpClient.test_trigger_json)
        modified_trigger.id = '5852816a9aaacb00153134a3'
        modified_trigger.end = self._trigger.end_after_millis + 10000
        result = instance.update_trigger(modified_trigger)
        self.assertIsNone(result)

    def test_get_alerts_for_fails_with_wrong_input(self):
        instance = AlertManager('APIKey')
        with self.assertRaises(AssertionError):
            instance.get_alerts_for(None)
        with self.assertRaises(AssertionError):
            self._trigger.id = 123
            instance.get_alerts_for(self._trigger)

    def test_get_alerts_for(self):
        instance = self.factory(MockHttpClientTwoAlerts)
        self._trigger.id = 'trigger-id'
        results = instance.get_alerts_for(self._trigger)
        self.assertEqual(2, len(results))
        self.assertIsInstance(results[0], Alert)
        self.assertIsInstance(results[1], Alert)

    def test_get_alert_fails_with_wrong_input(self):
        instance = AlertManager('APIKey')
        with self.assertRaises(AssertionError):
            instance.get_alert(None, self._trigger)
        with self.assertRaises(AssertionError):
            instance.get_alert(123, self._trigger)
        with self.assertRaises(AssertionError):
            instance.get_alert('alert-id', None)
        with self.assertRaises(AssertionError):
            self._trigger.id = 123
            instance.get_alert('alert-id', self._trigger)

    def test_get_alert(self):
        self._trigger.id = 'trigger-id'
        instance = self.factory(MockHttpClientOneAlert)
        result = instance.get_alert('alert-id', self._trigger)
        self.assertIsInstance(result, Alert)

    def test_delete_all_alerts_for_fails_with_wrong_input(self):
        instance = AlertManager('APIKey')
        with self.assertRaises(AssertionError):
            instance.delete_all_alerts_for(None)
        with self.assertRaises(AssertionError):
            self._trigger.id = 123
            instance.delete_all_alerts_for(self._trigger)

    def test_delete_all_alerts_for(self):
        instance = self.factory(MockHttpClientTwoAlerts)
        result = instance.delete_all_alerts_for(self._trigger)
        self.assertIsNone(result)

    def test_delete_alert_fails_with_wrong_input(self):
        instance = AlertManager('APIKey')
        with self.assertRaises(AssertionError):
            instance.delete_alert(None)
        with self.assertRaises(AssertionError):
            self._alert.id = 123
            instance.delete_alert(self._alert)
        self._alert.id = 'alert-id'
        self._alert.trigger_id = None
        with self.assertRaises(AssertionError):
            instance.delete_alert(self._alert)
        self._alert.trigger_id = 789
        with self.assertRaises(AssertionError):
            instance.delete_alert(self._alert)

    def test_delete_alert(self):
        instance = self.factory(MockHttpClientOneAlert)
        result = instance.delete_alert(self._alert)
        self.assertIsNone(result)