core/tests/components/rest/test_sensor.py

680 lines
25 KiB
Python
Raw Normal View History

"""The tests for the REST sensor platform."""
2016-10-31 04:51:03 +00:00
import unittest
from unittest.mock import Mock, patch
2016-10-31 04:51:03 +00:00
import pytest
from pytest import raises
2016-10-31 04:51:03 +00:00
import requests
from requests.exceptions import RequestException, Timeout
from requests.structures import CaseInsensitiveDict
2016-10-31 04:51:03 +00:00
import requests_mock
Consolidate all platforms that have tests (#22109) * Moved climate components with tests into platform dirs. * Updated tests from climate component. * Moved binary_sensor components with tests into platform dirs. * Updated tests from binary_sensor component. * Moved calendar components with tests into platform dirs. * Updated tests from calendar component. * Moved camera components with tests into platform dirs. * Updated tests from camera component. * Moved cover components with tests into platform dirs. * Updated tests from cover component. * Moved device_tracker components with tests into platform dirs. * Updated tests from device_tracker component. * Moved fan components with tests into platform dirs. * Updated tests from fan component. * Moved geo_location components with tests into platform dirs. * Updated tests from geo_location component. * Moved image_processing components with tests into platform dirs. * Updated tests from image_processing component. * Moved light components with tests into platform dirs. * Updated tests from light component. * Moved lock components with tests into platform dirs. * Moved media_player components with tests into platform dirs. * Updated tests from media_player component. * Moved scene components with tests into platform dirs. * Moved sensor components with tests into platform dirs. * Updated tests from sensor component. * Moved switch components with tests into platform dirs. * Updated tests from sensor component. * Moved vacuum components with tests into platform dirs. * Updated tests from vacuum component. * Moved weather components with tests into platform dirs. * Fixed __init__.py files * Fixes for stuff moved as part of this branch. * Fix stuff needed to merge with balloob's branch. * Formatting issues. * Missing __init__.py files. * Fix-ups * Fixup * Regenerated requirements. * Linting errors fixed. * Fixed more broken tests. * Missing init files. * Fix broken tests. * More broken tests * There seems to be a thread race condition. I suspect the logger stuff is running in another thread, which means waiting until the aio loop is done is missing the log messages. Used sleep instead because that allows the logger thread to run. I think the api_streams sensor might not be thread safe. * Disabled tests, will remove sensor in #22147 * Updated coverage and codeowners.
2019-03-19 06:07:39 +00:00
import homeassistant.components.rest.sensor as rest
import homeassistant.components.sensor as sensor
from homeassistant.const import DATA_MEGABYTES
from homeassistant.exceptions import PlatformNotReady
2016-10-31 04:51:03 +00:00
from homeassistant.helpers.config_validation import template
from homeassistant.setup import setup_component
from tests.common import assert_setup_component, get_test_home_assistant
2016-10-31 04:51:03 +00:00
class TestRestSensorSetup(unittest.TestCase):
"""Tests for setting up the REST sensor platform."""
2016-10-31 04:51:03 +00:00
def setUp(self):
2018-08-19 20:29:08 +00:00
"""Set up things to be run when tests are started."""
2016-10-31 04:51:03 +00:00
self.hass = get_test_home_assistant()
def tearDown(self):
"""Stop everything that was started."""
self.hass.stop()
def test_setup_missing_config(self):
"""Test setup with configuration missing required entries."""
with assert_setup_component(0):
2019-07-31 19:25:30 +00:00
assert setup_component(
self.hass, sensor.DOMAIN, {"sensor": {"platform": "rest"}}
)
2016-10-31 04:51:03 +00:00
def test_setup_missing_schema(self):
"""Test setup with resource missing schema."""
with pytest.raises(PlatformNotReady):
2019-07-31 19:25:30 +00:00
rest.setup_platform(
self.hass,
{"platform": "rest", "resource": "localhost", "method": "GET"},
None,
)
@patch("requests.Session.send", side_effect=requests.exceptions.ConnectionError())
2016-10-31 04:51:03 +00:00
def test_setup_failed_connect(self, mock_req):
"""Test setup when connection error occurs."""
with raises(PlatformNotReady):
2019-07-31 19:25:30 +00:00
rest.setup_platform(
self.hass,
{"platform": "rest", "resource": "http://localhost", "method": "GET"},
2019-07-31 19:25:30 +00:00
lambda devices, update=True: None,
)
2016-10-31 04:51:03 +00:00
2019-07-31 19:25:30 +00:00
@patch("requests.Session.send", side_effect=Timeout())
2016-10-31 04:51:03 +00:00
def test_setup_timeout(self, mock_req):
"""Test setup when connection timeout occurs."""
with raises(PlatformNotReady):
2019-07-31 19:25:30 +00:00
rest.setup_platform(
self.hass,
{"platform": "rest", "resource": "http://localhost", "method": "GET"},
2019-07-31 19:25:30 +00:00
lambda devices, update=True: None,
)
2016-10-31 04:51:03 +00:00
@requests_mock.Mocker()
def test_setup_minimum(self, mock_req):
"""Test setup with minimum configuration."""
2019-07-31 19:25:30 +00:00
mock_req.get("http://localhost", status_code=200)
with assert_setup_component(1, "sensor"):
assert setup_component(
self.hass,
"sensor",
{"sensor": {"platform": "rest", "resource": "http://localhost"}},
)
assert 2 == mock_req.call_count
2016-10-31 04:51:03 +00:00
@requests_mock.Mocker()
def test_setup_minimum_resource_template(self, mock_req):
"""Test setup with minimum configuration (resource_template)."""
mock_req.get("http://localhost", status_code=200)
with assert_setup_component(1, "sensor"):
assert setup_component(
self.hass,
"sensor",
{
"sensor": {
"platform": "rest",
"resource_template": "http://localhost",
}
},
)
assert mock_req.call_count == 2
@requests_mock.Mocker()
def test_setup_duplicate_resource(self, mock_req):
"""Test setup with duplicate resources."""
mock_req.get("http://localhost", status_code=200)
with assert_setup_component(0, "sensor"):
assert setup_component(
self.hass,
"sensor",
{
"sensor": {
"platform": "rest",
"resource": "http://localhost",
"resource_template": "http://localhost",
}
},
)
2016-10-31 04:51:03 +00:00
@requests_mock.Mocker()
def test_setup_get(self, mock_req):
"""Test setup with valid configuration."""
2019-07-31 19:25:30 +00:00
mock_req.get("http://localhost", status_code=200)
with assert_setup_component(1, "sensor"):
assert setup_component(
self.hass,
"sensor",
{
"sensor": {
"platform": "rest",
"resource": "http://localhost",
"method": "GET",
"value_template": "{{ value_json.key }}",
"name": "foo",
"unit_of_measurement": DATA_MEGABYTES,
2019-07-31 19:25:30 +00:00
"verify_ssl": "true",
"timeout": 30,
"authentication": "basic",
"username": "my username",
"password": "my password",
"headers": {"Accept": "application/json"},
}
},
)
assert 2 == mock_req.call_count
2016-10-31 04:51:03 +00:00
@requests_mock.Mocker()
def test_setup_post(self, mock_req):
"""Test setup with valid configuration."""
2019-07-31 19:25:30 +00:00
mock_req.post("http://localhost", status_code=200)
with assert_setup_component(1, "sensor"):
assert setup_component(
self.hass,
"sensor",
{
"sensor": {
"platform": "rest",
"resource": "http://localhost",
"method": "POST",
"value_template": "{{ value_json.key }}",
"payload": '{ "device": "toaster"}',
"name": "foo",
"unit_of_measurement": DATA_MEGABYTES,
2019-07-31 19:25:30 +00:00
"verify_ssl": "true",
"timeout": 30,
"authentication": "basic",
"username": "my username",
"password": "my password",
"headers": {"Accept": "application/json"},
}
},
)
assert 2 == mock_req.call_count
2016-10-31 04:51:03 +00:00
@requests_mock.Mocker()
def test_setup_get_xml(self, mock_req):
"""Test setup with valid configuration."""
mock_req.get("http://localhost", status_code=200)
with assert_setup_component(1, "sensor"):
assert setup_component(
self.hass,
"sensor",
{
"sensor": {
"platform": "rest",
"resource": "http://localhost",
"method": "GET",
"value_template": "{{ value_json.key }}",
"name": "foo",
"unit_of_measurement": DATA_MEGABYTES,
"verify_ssl": "true",
"timeout": 30,
"authentication": "basic",
"username": "my username",
"password": "my password",
"headers": {"Accept": "text/xml"},
}
},
)
assert 2 == mock_req.call_count
2016-10-31 04:51:03 +00:00
class TestRestSensor(unittest.TestCase):
"""Tests for REST sensor platform."""
def setUp(self):
2018-08-19 20:29:08 +00:00
"""Set up things to be run when tests are started."""
2016-10-31 04:51:03 +00:00
self.hass = get_test_home_assistant()
2019-07-31 19:25:30 +00:00
self.initial_state = "initial_state"
self.rest = Mock("rest.RestData")
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
'{ "key": "' + self.initial_state + '" }',
CaseInsensitiveDict({"Content-Type": "application/json"}),
2019-07-31 19:25:30 +00:00
),
)
self.name = "foo"
self.unit_of_measurement = DATA_MEGABYTES
self.device_class = None
2019-07-31 19:25:30 +00:00
self.value_template = template("{{ value_json.key }}")
self.json_attrs_path = None
2016-10-31 04:51:03 +00:00
self.value_template.hass = self.hass
self.force_update = False
self.resource_template = None
2016-10-31 04:51:03 +00:00
self.sensor = rest.RestSensor(
2019-07-31 19:25:30 +00:00
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
self.value_template,
[],
self.force_update,
self.resource_template,
self.json_attrs_path,
)
2016-10-31 04:51:03 +00:00
def tearDown(self):
"""Stop everything that was started."""
self.hass.stop()
def update_side_effect(self, data, headers):
2016-10-31 04:51:03 +00:00
"""Side effect function for mocking RestData.update()."""
self.rest.data = data
self.rest.headers = headers
2016-10-31 04:51:03 +00:00
def test_name(self):
"""Test the name."""
assert self.name == self.sensor.name
2016-10-31 04:51:03 +00:00
def test_unit_of_measurement(self):
"""Test the unit of measurement."""
assert self.unit_of_measurement == self.sensor.unit_of_measurement
2016-10-31 04:51:03 +00:00
def test_force_update(self):
"""Test the unit of measurement."""
assert self.force_update == self.sensor.force_update
2016-10-31 04:51:03 +00:00
def test_state(self):
"""Test the initial state."""
self.sensor.update()
assert self.initial_state == self.sensor.state
2016-10-31 04:51:03 +00:00
def test_update_when_value_is_none(self):
"""Test state gets updated to unknown when sensor returns no data."""
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(None, CaseInsensitiveDict()),
2019-07-31 19:25:30 +00:00
)
2016-10-31 04:51:03 +00:00
self.sensor.update()
assert self.sensor.state is None
assert not self.sensor.available
2016-10-31 04:51:03 +00:00
def test_update_when_value_changed(self):
"""Test state gets updated when sensor returns a new status."""
2019-07-31 19:25:30 +00:00
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
'{ "key": "updated_state" }',
CaseInsensitiveDict({"Content-Type": "application/json"}),
),
2019-07-31 19:25:30 +00:00
)
2016-10-31 04:51:03 +00:00
self.sensor.update()
2019-07-31 19:25:30 +00:00
assert "updated_state" == self.sensor.state
assert self.sensor.available
2016-10-31 04:51:03 +00:00
def test_update_with_no_template(self):
"""Test update when there is no value template."""
2019-07-31 19:25:30 +00:00
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
"plain_state", CaseInsensitiveDict({"Content-Type": "application/json"})
),
2019-07-31 19:25:30 +00:00
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
None,
[],
self.force_update,
self.resource_template,
self.json_attrs_path,
2019-07-31 19:25:30 +00:00
)
2016-10-31 04:51:03 +00:00
self.sensor.update()
2019-07-31 19:25:30 +00:00
assert "plain_state" == self.sensor.state
assert self.sensor.available
2016-10-31 04:51:03 +00:00
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
def test_update_with_json_attrs(self):
"""Test attributes get extracted from a JSON result."""
2019-07-31 19:25:30 +00:00
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
'{ "key": "some_json_value" }',
CaseInsensitiveDict({"Content-Type": "application/json"}),
),
2019-07-31 19:25:30 +00:00
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
None,
["key"],
self.force_update,
self.resource_template,
self.json_attrs_path,
2019-07-31 19:25:30 +00:00
)
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
self.sensor.update()
2019-07-31 19:25:30 +00:00
assert "some_json_value" == self.sensor.device_state_attributes["key"]
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
def test_update_with_json_attrs_list_dict(self):
"""Test attributes get extracted from a JSON list[0] result."""
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
'[{ "key": "another_value" }]',
CaseInsensitiveDict({"Content-Type": "application/json"}),
),
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
None,
["key"],
self.force_update,
self.resource_template,
self.json_attrs_path,
)
self.sensor.update()
assert "another_value" == self.sensor.device_state_attributes["key"]
2019-07-31 19:25:30 +00:00
@patch("homeassistant.components.rest.sensor._LOGGER")
def test_update_with_json_attrs_no_data(self, mock_logger):
"""Test attributes when no JSON result fetched."""
2019-07-31 19:25:30 +00:00
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
None, CaseInsensitiveDict({"Content-Type": "application/json"})
),
2019-07-31 19:25:30 +00:00
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
None,
["key"],
self.force_update,
self.resource_template,
self.json_attrs_path,
2019-07-31 19:25:30 +00:00
)
self.sensor.update()
assert {} == self.sensor.device_state_attributes
assert mock_logger.warning.called
2019-07-31 19:25:30 +00:00
@patch("homeassistant.components.rest.sensor._LOGGER")
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
def test_update_with_json_attrs_not_dict(self, mock_logger):
"""Test attributes get extracted from a JSON result."""
2019-07-31 19:25:30 +00:00
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
'["list", "of", "things"]',
CaseInsensitiveDict({"Content-Type": "application/json"}),
),
2019-07-31 19:25:30 +00:00
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
None,
["key"],
self.force_update,
self.resource_template,
self.json_attrs_path,
2019-07-31 19:25:30 +00:00
)
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
self.sensor.update()
assert {} == self.sensor.device_state_attributes
assert mock_logger.warning.called
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
2019-07-31 19:25:30 +00:00
@patch("homeassistant.components.rest.sensor._LOGGER")
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
def test_update_with_json_attrs_bad_JSON(self, mock_logger):
"""Test attributes get extracted from a JSON result."""
2019-07-31 19:25:30 +00:00
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
"This is text rather than JSON data.",
CaseInsensitiveDict({"Content-Type": "text/plain"}),
),
2019-07-31 19:25:30 +00:00
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
None,
["key"],
self.force_update,
self.resource_template,
self.json_attrs_path,
2019-07-31 19:25:30 +00:00
)
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
self.sensor.update()
assert {} == self.sensor.device_state_attributes
assert mock_logger.warning.called
assert mock_logger.debug.called
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
def test_update_with_json_attrs_and_template(self):
"""Test attributes get extracted from a JSON result."""
2019-07-31 19:25:30 +00:00
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
'{ "key": "json_state_updated_value" }',
CaseInsensitiveDict({"Content-Type": "application/json"}),
2019-07-31 19:25:30 +00:00
),
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
self.value_template,
["key"],
self.force_update,
self.resource_template,
self.json_attrs_path,
2019-07-31 19:25:30 +00:00
)
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
self.sensor.update()
2019-07-31 19:25:30 +00:00
assert "json_state_updated_value" == self.sensor.state
assert (
"json_state_updated_value" == self.sensor.device_state_attributes["key"]
), self.force_update
Unpacking RESTful sensor JSON results into attributes. (#10753) * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * sensor.envirophat: add missing requirement (#7451) Adding requirements that is not explicitly pulled in by the library that manages the Enviro pHAT. * PyPI Openzwave (#7415) * Remove default zwave config path PYOZW now has much more comprehensive default handling for the config path (in src-lib/libopenzwave/libopenzwave.pyx:getConfig()). It looks in the same place we were looking, plus _many_ more. It will certainly do a much better job of finding the config files than we will (and will be updated as the library is changed, so we don't end up chasing it). The getConfig() method has been there for a while, but was subsntially improved recently. This change simply leaves the config_path as None if it is not specified, which will trigger the default handling in PYOZW. * Install python-openzwave from PyPI As of version 0.4, python-openzwave supports installation from PyPI, which means we can use our 'normal' dependency management tooling to install it. Yay. This uses the default 'embed' build (which goes and downloads statically sources to avoid having to compile anything locally). Check out the python-openzwave readme for more details. * Add python-openzwave deps to .travis.yml Python OpenZwave require the libudev headers to build. This adds the libudev-dev package to Travis runs via the 'apt' addon for Travis. Thanks to @MartinHjelmare for this fix. * Update docker build for PyPI openzwave Now that PYOZW can be install from PyPI, the docker image build process can be simplified to remove the explicit compilation of PYOZW. * Add datadog component (#7158) * Add datadog component * Improve test_invalid_config datadog test * Use assert_setup_component for test setup * Fix object type for default KNX port #7429 describes a TypeError that is raised if the port is omitted in the config for the KNX component (integer is required (got type str)). This commit changes the default port from a string to an integer. I expect this will resolve that issue... * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Added support for extracting JSON attributes from RESTful values Setting the json_attributes configuration option to true on the RESTful sensor will cause the result of the REST request to be parsed as a JSON string and if successful the resulting dictionary will be used for the attributes of the sensor. * Added requirement that RESTful JSON results used as attributes must be objects, not lists. * Expanded test coverage to test REFTful JSON attributes with and without a value template. * Fixed breaks cause by manual upstream merge. * Added one extra blank line to make PyLint happy. * Switched json_attributes to be a list of keys rather than a boolean. The value of json_attributes can now be either a comma sepaated list of key names or a YAML list of key names. Only matching keys in a retuned JSON dictionary will be mapped to sensor attributes. Updated test cases to handle json_attributes being a list. Also fixed two minor issues arrising from manual merge with 0.58 master. * Added an explicit default value to the json_attributes config entry. * Removed self.update() from __init__() body. * Expended unit tests for error cases of json_attributes processing. * Align quotes
2017-12-03 15:30:25 +00:00
def test_update_with_json_attrs_with_json_attrs_path(self):
"""Test attributes get extracted from a JSON result with a template for the attributes."""
json_attrs_path = "$.toplevel.second_level"
value_template = template("{{ value_json.toplevel.master_value }}")
value_template.hass = self.hass
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
'{ "toplevel": {"master_value": "master", "second_level": {"some_json_key": "some_json_value", "some_json_key2": "some_json_value2" } } }',
CaseInsensitiveDict({"Content-Type": "application/json"}),
),
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
value_template,
["some_json_key", "some_json_key2"],
self.force_update,
self.resource_template,
json_attrs_path,
)
self.sensor.update()
assert "some_json_value" == self.sensor.device_state_attributes["some_json_key"]
assert (
"some_json_value2" == self.sensor.device_state_attributes["some_json_key2"]
)
assert "master" == self.sensor.state
def test_update_with_xml_convert_json_attrs_with_json_attrs_path(self):
"""Test attributes get extracted from a JSON result that was converted from XML with a template for the attributes."""
json_attrs_path = "$.toplevel.second_level"
value_template = template("{{ value_json.toplevel.master_value }}")
value_template.hass = self.hass
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
"<toplevel><master_value>master</master_value><second_level><some_json_key>some_json_value</some_json_key><some_json_key2>some_json_value2</some_json_key2></second_level></toplevel>",
CaseInsensitiveDict({"Content-Type": "text/xml+svg"}),
),
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
value_template,
["some_json_key", "some_json_key2"],
self.force_update,
self.resource_template,
json_attrs_path,
)
self.sensor.update()
assert "some_json_value" == self.sensor.device_state_attributes["some_json_key"]
assert (
"some_json_value2" == self.sensor.device_state_attributes["some_json_key2"]
)
assert "master" == self.sensor.state
def test_update_with_xml_convert_json_attrs_with_jsonattr_template(self):
"""Test attributes get extracted from a JSON result that was converted from XML."""
json_attrs_path = "$.response"
value_template = template("{{ value_json.response.bss.wlan }}")
value_template.hass = self.hass
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
'<?xml version="1.0" encoding="utf-8"?><response><scan>0</scan><ver>12556</ver><count>48</count><ssid>alexander</ssid><bss><valid>0</valid><name>0</name><privacy>0</privacy><wlan>bogus</wlan><strength>0</strength></bss><led0>0</led0><led1>0</led1><led2>0</led2><led3>0</led3><led4>0</led4><led5>0</led5><led6>0</led6><led7>0</led7><btn0>up</btn0><btn1>up</btn1><btn2>up</btn2><btn3>up</btn3><pot0>0</pot0><usr0>0</usr0><temp0>0x0XF0x0XF</temp0><time0> 0</time0></response>',
CaseInsensitiveDict({"Content-Type": "text/xml"}),
),
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
value_template,
["led0", "led1", "temp0", "time0", "ver"],
self.force_update,
self.resource_template,
json_attrs_path,
)
self.sensor.update()
assert "0" == self.sensor.device_state_attributes["led0"]
assert "0" == self.sensor.device_state_attributes["led1"]
assert "0x0XF0x0XF" == self.sensor.device_state_attributes["temp0"]
assert "0" == self.sensor.device_state_attributes["time0"]
assert "12556" == self.sensor.device_state_attributes["ver"]
assert "bogus" == self.sensor.state
def test_update_with_application_xml_convert_json_attrs_with_jsonattr_template(
self,
):
"""Test attributes get extracted from a JSON result that was converted from XML with application/xml mime type."""
json_attrs_path = "$.main"
value_template = template("{{ value_json.main.dog }}")
value_template.hass = self.hass
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
"<main><dog>1</dog><cat>3</cat></main>",
CaseInsensitiveDict({"Content-Type": "application/xml"}),
),
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
value_template,
["dog", "cat"],
self.force_update,
self.resource_template,
json_attrs_path,
)
self.sensor.update()
assert "3" == self.sensor.device_state_attributes["cat"]
assert "1" == self.sensor.device_state_attributes["dog"]
assert "1" == self.sensor.state
@patch("homeassistant.components.rest.sensor._LOGGER")
def test_update_with_xml_convert_bad_xml(self, mock_logger):
"""Test attributes get extracted from a XML result with bad xml."""
value_template = template("{{ value_json.toplevel.master_value }}")
value_template.hass = self.hass
self.rest.update = Mock(
"rest.RestData.update",
side_effect=self.update_side_effect(
"this is not xml", CaseInsensitiveDict({"Content-Type": "text/xml"})
),
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
value_template,
["key"],
self.force_update,
self.resource_template,
self.json_attrs_path,
)
self.sensor.update()
assert {} == self.sensor.device_state_attributes
assert mock_logger.warning.called
assert mock_logger.debug.called
@patch("homeassistant.components.rest.sensor._LOGGER")
def test_update_with_failed_get(self, mock_logger):
"""Test attributes get extracted from a XML result with bad xml."""
value_template = template("{{ value_json.toplevel.master_value }}")
value_template.hass = self.hass
self.rest.update = Mock(
"rest.RestData.update", side_effect=self.update_side_effect(None, None),
)
self.sensor = rest.RestSensor(
self.hass,
self.rest,
self.name,
self.unit_of_measurement,
self.device_class,
value_template,
["key"],
self.force_update,
self.resource_template,
self.json_attrs_path,
)
self.sensor.update()
assert {} == self.sensor.device_state_attributes
assert mock_logger.warning.called
assert mock_logger.debug.called
assert self.sensor.state is None
assert self.sensor.available is False
2016-10-31 04:51:03 +00:00
class TestRestData(unittest.TestCase):
"""Tests for RestData."""
def setUp(self):
2018-08-19 20:29:08 +00:00
"""Set up things to be run when tests are started."""
2016-10-31 04:51:03 +00:00
self.method = "GET"
self.resource = "http://localhost"
self.verify_ssl = True
self.timeout = 10
self.rest = rest.RestData(
2019-07-31 19:25:30 +00:00
self.method, self.resource, None, None, None, self.verify_ssl, self.timeout
)
2016-10-31 04:51:03 +00:00
@requests_mock.Mocker()
def test_update(self, mock_req):
"""Test update."""
2019-07-31 19:25:30 +00:00
mock_req.get("http://localhost", text="test data")
2016-10-31 04:51:03 +00:00
self.rest.update()
2019-07-31 19:25:30 +00:00
assert "test data" == self.rest.data
2016-10-31 04:51:03 +00:00
@patch("requests.request", side_effect=RequestException)
2016-10-31 04:51:03 +00:00
def test_update_request_exception(self, mock_req):
"""Test update when a request exception occurs."""
self.rest.update()
assert self.rest.data is None