diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index b9575b7f21aab..b957ef1389559 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -3,7 +3,7 @@ "name": "Home Assistant Frontend", "documentation": "https://www.home-assistant.io/integrations/frontend", "requirements": [ - "home-assistant-frontend==20200220.4" + "home-assistant-frontend==20200220.5" ], "dependencies": [ "api", diff --git a/homeassistant/components/lovelace/__init__.py b/homeassistant/components/lovelace/__init__.py index fc8cb67894bc4..b986c61ea36b6 100644 --- a/homeassistant/components/lovelace/__init__.py +++ b/homeassistant/components/lovelace/__init__.py @@ -104,6 +104,9 @@ async def async_load(self, force): async def async_save(self, config): """Save config.""" + if self._hass.config.safe_mode: + raise HomeAssistantError("Deleting not supported in safe mode") + if self._data is None: await self._load() self._data["config"] = config @@ -112,6 +115,9 @@ async def async_save(self, config): async def async_delete(self): """Delete config.""" + if self._hass.config.safe_mode: + raise HomeAssistantError("Deleting not supported in safe mode") + await self.async_save(None) async def _load(self): diff --git a/homeassistant/components/rest/sensor.py b/homeassistant/components/rest/sensor.py index 70424325241bf..7c8cfb9d3d02d 100644 --- a/homeassistant/components/rest/sensor.py +++ b/homeassistant/components/rest/sensor.py @@ -202,17 +202,19 @@ def update(self): self.rest.update() value = self.rest.data _LOGGER.debug("Data fetched from resource: %s", value) - content_type = self.rest.headers.get("content-type") - - if content_type and content_type.startswith("text/xml"): - try: - value = json.dumps(xmltodict.parse(value)) - _LOGGER.debug("JSON converted from XML: %s", value) - except ExpatError: - _LOGGER.warning( - "REST xml result could not be parsed and converted to JSON." - ) - _LOGGER.debug("Erroneous XML: %s", value) + if self.rest.headers is not None: + # If the http request failed, headers will be None + content_type = self.rest.headers.get("content-type") + + if content_type and content_type.startswith("text/xml"): + try: + value = json.dumps(xmltodict.parse(value)) + _LOGGER.debug("JSON converted from XML: %s", value) + except ExpatError: + _LOGGER.warning( + "REST xml result could not be parsed and converted to JSON." + ) + _LOGGER.debug("Erroneous XML: %s", value) if self._json_attrs: self._attributes = {} diff --git a/homeassistant/components/unifi/device_tracker.py b/homeassistant/components/unifi/device_tracker.py index 52370fb0e3db3..b398dad488bcc 100644 --- a/homeassistant/components/unifi/device_tracker.py +++ b/homeassistant/components/unifi/device_tracker.py @@ -338,4 +338,4 @@ def device_state_attributes(self): @property def should_poll(self): """No polling needed.""" - return False + return True diff --git a/homeassistant/components/unifi/unifi_client.py b/homeassistant/components/unifi/unifi_client.py index 2e18f55a57bad..f9e77d47c0e37 100644 --- a/homeassistant/components/unifi/unifi_client.py +++ b/homeassistant/components/unifi/unifi_client.py @@ -62,4 +62,4 @@ def device_info(self) -> dict: @property def should_poll(self) -> bool: """No polling needed.""" - return False + return True diff --git a/homeassistant/const.py b/homeassistant/const.py index f453e2118977e..11b3c87db279d 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 106 -PATCH_VERSION = "1" +PATCH_VERSION = "2" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER = (3, 7, 0) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 7d6f445c1e4c3..d8450d873b788 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -11,7 +11,7 @@ cryptography==2.8 defusedxml==0.6.0 distro==1.4.0 hass-nabucasa==0.31 -home-assistant-frontend==20200220.4 +home-assistant-frontend==20200220.5 importlib-metadata==1.5.0 jinja2>=2.10.3 netdisco==2.6.0 diff --git a/requirements_all.txt b/requirements_all.txt index 252b6d9c6a13d..d3f81477a8018 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -683,7 +683,7 @@ hole==0.5.0 holidays==0.10.1 # homeassistant.components.frontend -home-assistant-frontend==20200220.4 +home-assistant-frontend==20200220.5 # homeassistant.components.zwave homeassistant-pyozw==0.1.8 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3b0480ffe642d..bf9106725b5a8 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -254,7 +254,7 @@ hole==0.5.0 holidays==0.10.1 # homeassistant.components.frontend -home-assistant-frontend==20200220.4 +home-assistant-frontend==20200220.5 # homeassistant.components.zwave homeassistant-pyozw==0.1.8 diff --git a/tests/components/lovelace/test_init.py b/tests/components/lovelace/test_init.py index 82e7b3bc2acb6..c79e447f5afa6 100644 --- a/tests/components/lovelace/test_init.py +++ b/tests/components/lovelace/test_init.py @@ -45,6 +45,16 @@ async def test_lovelace_from_storage(hass, hass_ws_client, hass_storage): assert not response["success"] assert response["error"]["code"] == "config_not_found" + await client.send_json( + {"id": 9, "type": "lovelace/config/save", "config": {"yo": "hello"}} + ) + response = await client.receive_json() + assert not response["success"] + + await client.send_json({"id": 10, "type": "lovelace/config/delete"}) + response = await client.receive_json() + assert not response["success"] + async def test_lovelace_from_storage_save_before_load( hass, hass_ws_client, hass_storage diff --git a/tests/components/rest/test_sensor.py b/tests/components/rest/test_sensor.py index 30eeae9a8e38e..5018418f4931d 100644 --- a/tests/components/rest/test_sensor.py +++ b/tests/components/rest/test_sensor.py @@ -589,6 +589,35 @@ def test_update_with_xml_convert_bad_xml(self, mock_logger): 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 + class TestRestData(unittest.TestCase): """Tests for RestData."""