From dd276656c568be4365e0e2d044a3dafb398422c7 Mon Sep 17 00:00:00 2001 From: Phil Kates Date: Fri, 29 Sep 2017 14:59:33 -0700 Subject: [PATCH] splunk: Handle datetime objects in event payload If an event contained a datetime.datetime object it would cause an exception in the Splunk component. Most of the media_player components do this in their `media_position_updated_at` attribute. Use the JSONEncoder from homeassistant.remote instead of just using the standard json.dumps encoder. Fixes #9590 --- homeassistant/components/splunk.py | 4 +++- tests/components/test_splunk.py | 34 +++++++++++++++++++----------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/splunk.py b/homeassistant/components/splunk.py index 2b4ea862d2db2e..38f8a91a9171d4 100644 --- a/homeassistant/components/splunk.py +++ b/homeassistant/components/splunk.py @@ -14,6 +14,7 @@ CONF_NAME, CONF_HOST, CONF_PORT, CONF_SSL, CONF_TOKEN, EVENT_STATE_CHANGED) from homeassistant.helpers import state as state_helper import homeassistant.helpers.config_validation as cv +from homeassistant.remote import JSONEncoder _LOGGER = logging.getLogger(__name__) @@ -81,7 +82,8 @@ def splunk_event_listener(event): "host": event_collector, "event": json_body, } - requests.post(event_collector, data=json.dumps(payload), + requests.post(event_collector, + data=json.dumps(payload, cls=JSONEncoder), headers=headers, timeout=10) except requests.exceptions.RequestException as error: _LOGGER.exception("Error saving event to Splunk: %s", error) diff --git a/tests/components/test_splunk.py b/tests/components/test_splunk.py index d0c46c5f8ea887..38143119112e23 100644 --- a/tests/components/test_splunk.py +++ b/tests/components/test_splunk.py @@ -1,10 +1,13 @@ """The tests for the Splunk component.""" +import json import unittest from unittest import mock from homeassistant.setup import setup_component import homeassistant.components.splunk as splunk from homeassistant.const import STATE_ON, STATE_OFF, EVENT_STATE_CHANGED +from homeassistant.helpers import state as state_helper +import homeassistant.util.dt as dt_util from tests.common import get_test_home_assistant @@ -71,30 +74,37 @@ def _setup(self, mock_requests): self.handler_method = self.hass.bus.listen.call_args_list[0][0][1] @mock.patch.object(splunk, 'requests') - @mock.patch('json.dumps') - def test_event_listener(self, mock_dump, mock_requests): + def test_event_listener(self, mock_requests): """Test event listener.""" - mock_dump.side_effect = lambda x: x self._setup(mock_requests) - valid = {'1': 1, - '1.0': 1.0, - STATE_ON: 1, - STATE_OFF: 0, - 'foo': 'foo', - } + now = dt_util.now() + valid = { + '1': 1, + '1.0': 1.0, + STATE_ON: 1, + STATE_OFF: 0, + 'foo': 'foo', + } for in_, out in valid.items(): state = mock.MagicMock(state=in_, domain='fake', object_id='entity', - attributes={}) + attributes={'datetime_attr': now}) event = mock.MagicMock(data={'new_state': state}, time_fired=12345) + try: + out = state_helper.state_as_number(state) + except ValueError: + out = state.state + body = [{ 'domain': 'fake', 'entity_id': 'entity', - 'attributes': {}, + 'attributes': { + 'datetime_attr': now.isoformat() + }, 'time': '12345', 'value': out, 'host': 'HASS', @@ -107,7 +117,7 @@ def test_event_listener(self, mock_dump, mock_requests): self.assertEqual( self.mock_post.call_args, mock.call( - payload['host'], data=payload, + payload['host'], data=json.dumps(payload), headers={'Authorization': 'Splunk secret'}, timeout=10 )