diff --git a/homeassistant/components/devolo_home_control/__init__.py b/homeassistant/components/devolo_home_control/__init__.py index c955bf77096..69327f96510 100644 --- a/homeassistant/components/devolo_home_control/__init__.py +++ b/homeassistant/components/devolo_home_control/__init__.py @@ -1,4 +1,5 @@ """The devolo_home_control integration.""" +import asyncio from functools import partial from devolo_home_control_api.homecontrol import HomeControl @@ -71,8 +72,13 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool async def async_unload_entry(hass, config_entry): """Unload a config entry.""" - unload = await hass.config_entries.async_forward_entry_unload( - config_entry, "switch" + unload = all( + await asyncio.gather( + *[ + hass.config_entries.async_forward_entry_unload(config_entry, platform) + for platform in PLATFORMS + ] + ) ) await hass.async_add_executor_job( diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index 6732f6e99c3..fd3d4a497ab 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -2,7 +2,7 @@ "domain": "frontend", "name": "Home Assistant Frontend", "documentation": "https://www.home-assistant.io/integrations/frontend", - "requirements": ["home-assistant-frontend==20201001.1"], + "requirements": ["home-assistant-frontend==20201001.2"], "dependencies": [ "api", "auth", diff --git a/homeassistant/components/hive/manifest.json b/homeassistant/components/hive/manifest.json index 060a1a0a200..f8fb9bc8c2a 100644 --- a/homeassistant/components/hive/manifest.json +++ b/homeassistant/components/hive/manifest.json @@ -2,6 +2,6 @@ "domain": "hive", "name": "Hive", "documentation": "https://www.home-assistant.io/integrations/hive", - "requirements": ["pyhiveapi==0.2.20.1"], + "requirements": ["pyhiveapi==0.2.20.2"], "codeowners": ["@Rendili", "@KJonline"] } diff --git a/homeassistant/components/media_player/group.py b/homeassistant/components/media_player/group.py index b612165fa19..6ecf90fc0a1 100644 --- a/homeassistant/components/media_player/group.py +++ b/homeassistant/components/media_player/group.py @@ -2,16 +2,22 @@ from homeassistant.components.group import GroupIntegrationRegistry -from homeassistant.const import STATE_OFF +from homeassistant.const import ( + STATE_IDLE, + STATE_OFF, + STATE_ON, + STATE_PAUSED, + STATE_PLAYING, +) from homeassistant.core import callback from homeassistant.helpers.typing import HomeAssistantType -from . import STATE_IDLE, STATE_PLAYING - @callback def async_describe_on_off_states( hass: HomeAssistantType, registry: GroupIntegrationRegistry ) -> None: """Describe group on off states.""" - registry.on_off_states({STATE_PLAYING, STATE_IDLE}, STATE_OFF) + registry.on_off_states( + {STATE_ON, STATE_PAUSED, STATE_PLAYING, STATE_IDLE}, STATE_OFF + ) diff --git a/homeassistant/components/mqtt/manifest.json b/homeassistant/components/mqtt/manifest.json index 4d44090a4e3..8b293eb06f6 100644 --- a/homeassistant/components/mqtt/manifest.json +++ b/homeassistant/components/mqtt/manifest.json @@ -3,7 +3,7 @@ "name": "MQTT", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/mqtt", - "requirements": ["paho-mqtt==1.5.1"], + "requirements": ["paho-mqtt==1.5.0"], "dependencies": ["http"], "codeowners": ["@home-assistant/core", "@emontnemery"] } diff --git a/homeassistant/components/netatmo/manifest.json b/homeassistant/components/netatmo/manifest.json index b7205431bb5..12c9220c361 100644 --- a/homeassistant/components/netatmo/manifest.json +++ b/homeassistant/components/netatmo/manifest.json @@ -3,7 +3,7 @@ "name": "Netatmo", "documentation": "https://www.home-assistant.io/integrations/netatmo", "requirements": [ - "pyatmo==4.0.0" + "pyatmo==4.1.0" ], "after_dependencies": [ "cloud", diff --git a/homeassistant/components/recorder/__init__.py b/homeassistant/components/recorder/__init__.py index 63d466fa4d1..9630f94d807 100644 --- a/homeassistant/components/recorder/__init__.py +++ b/homeassistant/components/recorder/__init__.py @@ -494,7 +494,8 @@ class Recorder(threading.Thread): for dbstate in self._pending_expunge: # Expunge the state so its not expired # until we use it later for dbstate.old_state - self.event_session.expunge(dbstate) + if dbstate in self.event_session: + self.event_session.expunge(dbstate) self._pending_expunge = [] self.event_session.commit() except Exception as err: diff --git a/homeassistant/const.py b/homeassistant/const.py index 35b4b234597..bbf942c94d3 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 116 -PATCH_VERSION = "0" +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER = (3, 7, 1) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index cdda546a4e1..c510ded1e5f 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -13,11 +13,11 @@ defusedxml==0.6.0 distro==1.5.0 emoji==0.5.4 hass-nabucasa==0.37.0 -home-assistant-frontend==20201001.1 +home-assistant-frontend==20201001.2 importlib-metadata==1.6.0;python_version<'3.8' jinja2>=2.11.2 netdisco==2.8.2 -paho-mqtt==1.5.1 +paho-mqtt==1.5.0 pillow==7.2.0 pip>=8.0.3 python-slugify==4.0.1 diff --git a/requirements_all.txt b/requirements_all.txt index 6aa3e39b844..c291319b2f3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -753,7 +753,7 @@ hole==0.5.1 holidays==0.10.3 # homeassistant.components.frontend -home-assistant-frontend==20201001.1 +home-assistant-frontend==20201001.2 # homeassistant.components.zwave homeassistant-pyozw==0.1.10 @@ -1058,6 +1058,8 @@ orvibo==1.1.1 ovoenergy==1.1.7 # homeassistant.components.mqtt +paho-mqtt==1.5.0 + # homeassistant.components.shiftr paho-mqtt==1.5.1 @@ -1250,7 +1252,7 @@ pyarlo==0.2.3 pyatag==0.3.4.4 # homeassistant.components.netatmo -pyatmo==4.0.0 +pyatmo==4.1.0 # homeassistant.components.atome pyatome==0.1.1 @@ -1401,7 +1403,7 @@ pyheos==0.6.0 pyhik==0.2.7 # homeassistant.components.hive -pyhiveapi==0.2.20.1 +pyhiveapi==0.2.20.2 # homeassistant.components.homematic pyhomematic==0.1.68 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index deff4c9aafc..a977daa08e0 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -376,7 +376,7 @@ hole==0.5.1 holidays==0.10.3 # homeassistant.components.frontend -home-assistant-frontend==20201001.1 +home-assistant-frontend==20201001.2 # homeassistant.components.zwave homeassistant-pyozw==0.1.10 @@ -499,8 +499,7 @@ openerz-api==0.1.0 ovoenergy==1.1.7 # homeassistant.components.mqtt -# homeassistant.components.shiftr -paho-mqtt==1.5.1 +paho-mqtt==1.5.0 # homeassistant.components.panasonic_viera panasonic_viera==0.3.6 @@ -616,7 +615,7 @@ pyarlo==0.2.3 pyatag==0.3.4.4 # homeassistant.components.netatmo -pyatmo==4.0.0 +pyatmo==4.1.0 # homeassistant.components.blackbird pyblackbird==0.5 diff --git a/tests/components/recorder/test_init.py b/tests/components/recorder/test_init.py index 08af027bce3..c33455c0858 100644 --- a/tests/components/recorder/test_init.py +++ b/tests/components/recorder/test_init.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta import unittest import pytest +from sqlalchemy.exc import OperationalError from homeassistant.components.recorder import ( CONFIG_SCHEMA, @@ -452,3 +453,41 @@ def test_run_information(hass_recorder): class CannotSerializeMe: """A class that the JSONEncoder cannot serialize.""" + + +def test_saving_state_with_exception(hass, hass_recorder, caplog): + """Test saving and restoring a state.""" + hass = hass_recorder() + + entity_id = "test.recorder" + state = "restoring_from_db" + attributes = {"test_attr": 5, "test_attr_10": "nice"} + + def _throw_if_state_in_session(*args, **kwargs): + for obj in hass.data[DATA_INSTANCE].event_session: + if isinstance(obj, States): + raise OperationalError( + "insert the state", "fake params", "forced to fail" + ) + + with patch("time.sleep"), patch.object( + hass.data[DATA_INSTANCE].event_session, + "flush", + side_effect=_throw_if_state_in_session, + ): + hass.states.set(entity_id, "fail", attributes) + wait_recording_done(hass) + + assert "Error executing query" in caplog.text + assert "Error saving events" not in caplog.text + + caplog.clear() + hass.states.set(entity_id, state, attributes) + wait_recording_done(hass) + + with session_scope(hass=hass) as session: + db_states = list(session.query(States)) + assert len(db_states) >= 1 + + assert "Error executing query" not in caplog.text + assert "Error saving events" not in caplog.text