From 71a351605382136c5580a2eb8f46d5b24216ac64 Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 4 Oct 2019 22:28:55 -0400 Subject: [PATCH] Guard against network errors for Dark Sky (#27141) * Guard against network errors for Dark Sky - Prevents network errors from throwing an exception during state updates for the Dark Sky weather component. * Implement `available` for Dark Sky component * unknown -> unavailable --- homeassistant/components/darksky/weather.py | 8 +++++++- tests/components/darksky/test_weather.py | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/darksky/weather.py b/homeassistant/components/darksky/weather.py index 5296f346626..dc5708d12a0 100644 --- a/homeassistant/components/darksky/weather.py +++ b/homeassistant/components/darksky/weather.py @@ -102,6 +102,11 @@ class DarkSkyWeather(WeatherEntity): self._ds_hourly = None self._ds_daily = None + @property + def available(self): + """Return if weather data is available from Dark Sky.""" + return self._ds_data is not None + @property def attribution(self): """Return the attribution.""" @@ -215,7 +220,8 @@ class DarkSkyWeather(WeatherEntity): self._dark_sky.update() self._ds_data = self._dark_sky.data - self._ds_currently = self._dark_sky.currently.d + currently = self._dark_sky.currently + self._ds_currently = currently.d if currently else {} self._ds_hourly = self._dark_sky.hourly self._ds_daily = self._dark_sky.daily diff --git a/tests/components/darksky/test_weather.py b/tests/components/darksky/test_weather.py index ea28d3facb9..ca328f45839 100644 --- a/tests/components/darksky/test_weather.py +++ b/tests/components/darksky/test_weather.py @@ -6,6 +6,8 @@ from unittest.mock import patch import forecastio import requests_mock +from requests.exceptions import ConnectionError + from homeassistant.components import weather from homeassistant.util.unit_system import METRIC_SYSTEM from homeassistant.setup import setup_component @@ -48,3 +50,16 @@ class TestDarkSky(unittest.TestCase): state = self.hass.states.get("weather.test") assert state.state == "sunny" + + @patch("forecastio.load_forecast", side_effect=ConnectionError()) + def test_failed_setup(self, mock_load_forecast): + """Test to ensure that a network error does not break component state.""" + + assert setup_component( + self.hass, + weather.DOMAIN, + {"weather": {"name": "test", "platform": "darksky", "api_key": "foo"}}, + ) + + state = self.hass.states.get("weather.test") + assert state.state == "unavailable"