From 93baf2439452839c3cef4769a0326499229ac028 Mon Sep 17 00:00:00 2001 From: j4n-e4t <130256240+j4n-e4t@users.noreply.github.com> Date: Mon, 5 Jun 2023 19:53:24 +0200 Subject: [PATCH 01/25] Add error handling to input_select integration (#93940) --- .../components/input_select/__init__.py | 7 ++--- tests/components/input_select/test_init.py | 26 ++++++++++--------- .../input_select/test_reproduce_state.py | 4 ++- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/input_select/__init__.py b/homeassistant/components/input_select/__init__.py index 186ab84fb81..2c5a1c87f29 100644 --- a/homeassistant/components/input_select/__init__.py +++ b/homeassistant/components/input_select/__init__.py @@ -302,12 +302,9 @@ class InputSelect(collection.CollectionEntity, SelectEntity, RestoreEntity): async def async_select_option(self, option: str) -> None: """Select new option.""" if option not in self.options: - _LOGGER.warning( - "Invalid option: %s (possible options: %s)", - option, - ", ".join(self.options), + raise HomeAssistantError( + f"Invalid option: {option} (possible options: {', '.join(self.options)})" ) - return self._attr_current_option = option self.async_write_ha_state() diff --git a/tests/components/input_select/test_init.py b/tests/components/input_select/test_init.py index 315392702eb..6908a1c532e 100644 --- a/tests/components/input_select/test_init.py +++ b/tests/components/input_select/test_init.py @@ -102,12 +102,13 @@ async def test_select_option(hass: HomeAssistant) -> None: state = hass.states.get(entity_id) assert state.state == "another option" - await hass.services.async_call( - DOMAIN, - SERVICE_SELECT_OPTION, - {ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "non existing option"}, - blocking=True, - ) + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + DOMAIN, + SERVICE_SELECT_OPTION, + {ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "non existing option"}, + blocking=True, + ) state = hass.states.get(entity_id) assert state.state == "another option" @@ -305,12 +306,13 @@ async def test_set_options_service(hass: HomeAssistant) -> None: state = hass.states.get(entity_id) assert state.state == "test1" - await hass.services.async_call( - DOMAIN, - SERVICE_SELECT_OPTION, - {ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "first option"}, - blocking=True, - ) + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + DOMAIN, + SERVICE_SELECT_OPTION, + {ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "first option"}, + blocking=True, + ) state = hass.states.get(entity_id) assert state.state == "test1" diff --git a/tests/components/input_select/test_reproduce_state.py b/tests/components/input_select/test_reproduce_state.py index d6e9274fa8d..a00b6b02ade 100644 --- a/tests/components/input_select/test_reproduce_state.py +++ b/tests/components/input_select/test_reproduce_state.py @@ -2,6 +2,7 @@ import pytest from homeassistant.core import HomeAssistant, State +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.state import async_reproduce_state from homeassistant.setup import async_setup_component @@ -60,7 +61,8 @@ async def test_reproducing_states( assert hass.states.get(ENTITY).state == VALID_OPTION3 # Test setting state to invalid state - await async_reproduce_state(hass, [State(ENTITY, INVALID_OPTION)]) + with pytest.raises(HomeAssistantError): + await async_reproduce_state(hass, [State(ENTITY, INVALID_OPTION)]) # The entity state should be unchanged assert hass.states.get(ENTITY).state == VALID_OPTION3 From e1c47fdb61d79497d0d18a006a814bf1bde3b9e3 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 7 Jun 2023 18:42:40 +0200 Subject: [PATCH 02/25] Fix OTBR reset (#94157) --- homeassistant/components/otbr/manifest.json | 2 +- homeassistant/components/otbr/util.py | 5 +++ .../components/otbr/websocket_api.py | 6 ++++ homeassistant/components/thread/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/otbr/test_websocket_api.py | 33 +++++++++++++++++-- 7 files changed, 46 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/otbr/manifest.json b/homeassistant/components/otbr/manifest.json index f04e15a549c..94659df8547 100644 --- a/homeassistant/components/otbr/manifest.json +++ b/homeassistant/components/otbr/manifest.json @@ -8,5 +8,5 @@ "documentation": "https://www.home-assistant.io/integrations/otbr", "integration_type": "service", "iot_class": "local_polling", - "requirements": ["python-otbr-api==2.1.0"] + "requirements": ["python-otbr-api==2.2.0"] } diff --git a/homeassistant/components/otbr/util.py b/homeassistant/components/otbr/util.py index 5caebba5eb5..2d6217ea585 100644 --- a/homeassistant/components/otbr/util.py +++ b/homeassistant/components/otbr/util.py @@ -95,6 +95,11 @@ class OTBRData: """Create an active operational dataset.""" return await self.api.create_active_dataset(dataset) + @_handle_otbr_error + async def delete_active_dataset(self) -> None: + """Delete the active operational dataset.""" + return await self.api.delete_active_dataset() + @_handle_otbr_error async def set_active_dataset_tlvs(self, dataset: bytes) -> None: """Set current active operational dataset in TLVS format.""" diff --git a/homeassistant/components/otbr/websocket_api.py b/homeassistant/components/otbr/websocket_api.py index 0dcce288348..06bbca3a4ab 100644 --- a/homeassistant/components/otbr/websocket_api.py +++ b/homeassistant/components/otbr/websocket_api.py @@ -81,6 +81,12 @@ async def websocket_create_network( connection.send_error(msg["id"], "set_enabled_failed", str(exc)) return + try: + await data.delete_active_dataset() + except HomeAssistantError as exc: + connection.send_error(msg["id"], "delete_active_dataset_failed", str(exc)) + return + try: await data.create_active_dataset( python_otbr_api.ActiveDataSet( diff --git a/homeassistant/components/thread/manifest.json b/homeassistant/components/thread/manifest.json index 9a6a64481cd..0ce54496539 100644 --- a/homeassistant/components/thread/manifest.json +++ b/homeassistant/components/thread/manifest.json @@ -7,6 +7,6 @@ "documentation": "https://www.home-assistant.io/integrations/thread", "integration_type": "service", "iot_class": "local_polling", - "requirements": ["python-otbr-api==2.1.0", "pyroute2==0.7.5"], + "requirements": ["python-otbr-api==2.2.0", "pyroute2==0.7.5"], "zeroconf": ["_meshcop._udp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 8bb4580aa61..20df7fca52b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2106,7 +2106,7 @@ python-opensky==0.0.7 # homeassistant.components.otbr # homeassistant.components.thread -python-otbr-api==2.1.0 +python-otbr-api==2.2.0 # homeassistant.components.picnic python-picnic-api==1.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index bc1cae28d09..36941aceeb4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1532,7 +1532,7 @@ python-nest==4.2.0 # homeassistant.components.otbr # homeassistant.components.thread -python-otbr-api==2.1.0 +python-otbr-api==2.2.0 # homeassistant.components.picnic python-picnic-api==1.1.0 diff --git a/tests/components/otbr/test_websocket_api.py b/tests/components/otbr/test_websocket_api.py index 1feebe9c02c..65bec9e8408 100644 --- a/tests/components/otbr/test_websocket_api.py +++ b/tests/components/otbr/test_websocket_api.py @@ -84,6 +84,8 @@ async def test_create_network( with patch( "python_otbr_api.OTBR.create_active_dataset" ) as create_dataset_mock, patch( + "python_otbr_api.OTBR.delete_active_dataset" + ) as delete_dataset_mock, patch( "python_otbr_api.OTBR.set_enabled" ) as set_enabled_mock, patch( "python_otbr_api.OTBR.get_active_dataset_tlvs", return_value=DATASET_CH16 @@ -99,6 +101,7 @@ async def test_create_network( create_dataset_mock.assert_called_once_with( python_otbr_api.models.ActiveDataSet(channel=15, network_name="home-assistant") ) + delete_dataset_mock.assert_called_once_with() assert len(set_enabled_mock.mock_calls) == 2 assert set_enabled_mock.mock_calls[0][1][0] is False assert set_enabled_mock.mock_calls[1][1][0] is True @@ -151,7 +154,7 @@ async def test_create_network_fails_2( ), patch( "python_otbr_api.OTBR.create_active_dataset", side_effect=python_otbr_api.OTBRError, - ): + ), patch("python_otbr_api.OTBR.delete_active_dataset"): await websocket_client.send_json_auto_id({"type": "otbr/create_network"}) msg = await websocket_client.receive_json() @@ -171,6 +174,8 @@ async def test_create_network_fails_3( side_effect=[None, python_otbr_api.OTBRError], ), patch( "python_otbr_api.OTBR.create_active_dataset", + ), patch( + "python_otbr_api.OTBR.delete_active_dataset" ): await websocket_client.send_json_auto_id({"type": "otbr/create_network"}) msg = await websocket_client.receive_json() @@ -191,6 +196,8 @@ async def test_create_network_fails_4( ), patch( "python_otbr_api.OTBR.get_active_dataset_tlvs", side_effect=python_otbr_api.OTBRError, + ), patch( + "python_otbr_api.OTBR.delete_active_dataset" ): await websocket_client.send_json_auto_id({"type": "otbr/create_network"}) msg = await websocket_client.receive_json() @@ -208,7 +215,9 @@ async def test_create_network_fails_5( """Test create network.""" with patch("python_otbr_api.OTBR.set_enabled"), patch( "python_otbr_api.OTBR.create_active_dataset" - ), patch("python_otbr_api.OTBR.get_active_dataset_tlvs", return_value=None): + ), patch("python_otbr_api.OTBR.get_active_dataset_tlvs", return_value=None), patch( + "python_otbr_api.OTBR.delete_active_dataset" + ): await websocket_client.send_json_auto_id({"type": "otbr/create_network"}) msg = await websocket_client.receive_json() @@ -216,6 +225,26 @@ async def test_create_network_fails_5( assert msg["error"]["code"] == "get_active_dataset_tlvs_empty" +async def test_create_network_fails_6( + hass: HomeAssistant, + aioclient_mock: AiohttpClientMocker, + otbr_config_entry, + websocket_client, +) -> None: + """Test create network.""" + with patch("python_otbr_api.OTBR.set_enabled"), patch( + "python_otbr_api.OTBR.create_active_dataset" + ), patch("python_otbr_api.OTBR.get_active_dataset_tlvs", return_value=None), patch( + "python_otbr_api.OTBR.delete_active_dataset", + side_effect=python_otbr_api.OTBRError, + ): + await websocket_client.send_json_auto_id({"type": "otbr/create_network"}) + msg = await websocket_client.receive_json() + + assert not msg["success"] + assert msg["error"]["code"] == "delete_active_dataset_failed" + + async def test_set_network( hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, From f24b514c9a999716048b091f8ef1878feaf94190 Mon Sep 17 00:00:00 2001 From: Justin Vanderhooft Date: Wed, 7 Jun 2023 17:17:01 +0100 Subject: [PATCH 03/25] Bump melnor-bluetooth to fix a timezone issue (#94159) --- homeassistant/components/melnor/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/melnor/manifest.json b/homeassistant/components/melnor/manifest.json index 185899a9656..45dce207f7e 100644 --- a/homeassistant/components/melnor/manifest.json +++ b/homeassistant/components/melnor/manifest.json @@ -12,5 +12,5 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/melnor", "iot_class": "local_polling", - "requirements": ["melnor-bluetooth==0.0.24"] + "requirements": ["melnor-bluetooth==0.0.25"] } diff --git a/requirements_all.txt b/requirements_all.txt index 20df7fca52b..9811498808b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1122,7 +1122,7 @@ mcstatus==6.0.0 meater-python==0.0.8 # homeassistant.components.melnor -melnor-bluetooth==0.0.24 +melnor-bluetooth==0.0.25 # homeassistant.components.message_bird messagebird==1.2.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 36941aceeb4..77b6710155f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -848,7 +848,7 @@ mcstatus==6.0.0 meater-python==0.0.8 # homeassistant.components.melnor -melnor-bluetooth==0.0.24 +melnor-bluetooth==0.0.25 # homeassistant.components.meteo_france meteofrance-api==1.2.0 From 74c0552a12c406fc29a1a413b7255ca2a0281480 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Wed, 7 Jun 2023 19:53:45 +0200 Subject: [PATCH 04/25] Fix Abode unit of measurement (#94168) Change unit of measurement to HA const --- homeassistant/components/abode/sensor.py | 3 ++- tests/components/abode/test_sensor.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/abode/sensor.py b/homeassistant/components/abode/sensor.py index 87a9f8e9a27..546d57ab3e7 100644 --- a/homeassistant/components/abode/sensor.py +++ b/homeassistant/components/abode/sensor.py @@ -12,6 +12,7 @@ from homeassistant.components.sensor import ( SensorEntityDescription, ) from homeassistant.config_entries import ConfigEntry +from homeassistant.const import LIGHT_LUX from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -71,7 +72,7 @@ class AbodeSensor(AbodeDevice, SensorEntity): elif description.key == CONST.HUMI_STATUS_KEY: self._attr_native_unit_of_measurement = device.humidity_unit elif description.key == CONST.LUX_STATUS_KEY: - self._attr_native_unit_of_measurement = device.lux_unit + self._attr_native_unit_of_measurement = LIGHT_LUX @property def native_value(self) -> float | None: diff --git a/tests/components/abode/test_sensor.py b/tests/components/abode/test_sensor.py index 5d074de214f..67892dfafb4 100644 --- a/tests/components/abode/test_sensor.py +++ b/tests/components/abode/test_sensor.py @@ -39,7 +39,7 @@ async def test_attributes(hass: HomeAssistant) -> None: state = hass.states.get("sensor.environment_sensor_lux") assert state.state == "1.0" - assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "lux" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "lx" state = hass.states.get("sensor.environment_sensor_temperature") # Abodepy device JSON reports 19.5, but Home Assistant shows 19.4 From c6a17d68320521866c7b374717c0bc4af8dd4fb7 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Thu, 8 Jun 2023 11:33:35 +0200 Subject: [PATCH 05/25] Bump pyoverkiz to 1.8.0 (#94176) --- homeassistant/components/overkiz/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/overkiz/manifest.json b/homeassistant/components/overkiz/manifest.json index 2d81b7bab07..b03b60cd753 100644 --- a/homeassistant/components/overkiz/manifest.json +++ b/homeassistant/components/overkiz/manifest.json @@ -13,7 +13,7 @@ "integration_type": "hub", "iot_class": "cloud_polling", "loggers": ["boto3", "botocore", "pyhumps", "pyoverkiz", "s3transfer"], - "requirements": ["pyoverkiz==1.7.9"], + "requirements": ["pyoverkiz==1.8.0"], "zeroconf": [ { "type": "_kizbox._tcp.local.", diff --git a/requirements_all.txt b/requirements_all.txt index 9811498808b..0a93bc39854 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1872,7 +1872,7 @@ pyotgw==2.1.3 pyotp==2.8.0 # homeassistant.components.overkiz -pyoverkiz==1.7.9 +pyoverkiz==1.8.0 # homeassistant.components.openweathermap pyowm==3.2.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 77b6710155f..5449b3d3b8f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1382,7 +1382,7 @@ pyotgw==2.1.3 pyotp==2.8.0 # homeassistant.components.overkiz -pyoverkiz==1.7.9 +pyoverkiz==1.8.0 # homeassistant.components.openweathermap pyowm==3.2.0 From f39a6b96ff6e55a63cbf1666f4f39227f3a27462 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 8 Jun 2023 09:56:49 -0400 Subject: [PATCH 06/25] Rename Local Media to My Media (#94201) Co-authored-by: Martin Hjelmare Co-authored-by: Franck Nijhof --- homeassistant/components/media_source/local_source.py | 2 +- tests/components/media_source/test_init.py | 2 +- tests/components/roku/test_media_player.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/media_source/local_source.py b/homeassistant/components/media_source/local_source.py index c29794ae8d7..89437a6b2e0 100644 --- a/homeassistant/components/media_source/local_source.py +++ b/homeassistant/components/media_source/local_source.py @@ -38,7 +38,7 @@ def async_setup(hass: HomeAssistant) -> None: class LocalSource(MediaSource): """Provide local directories as media sources.""" - name: str = "Local Media" + name: str = "My media" def __init__(self, hass: HomeAssistant) -> None: """Initialize local source.""" diff --git a/tests/components/media_source/test_init.py b/tests/components/media_source/test_init.py index ec374e6a6e1..4e512608abf 100644 --- a/tests/components/media_source/test_init.py +++ b/tests/components/media_source/test_init.py @@ -95,7 +95,7 @@ async def test_async_browse_media(hass: HomeAssistant) -> None: media = await media_source.async_browse_media(hass, const.URI_SCHEME) assert isinstance(media, media_source.models.BrowseMediaSource) assert len(media.children) == 1 - assert media.children[0].title == "Local Media" + assert media.children[0].title == "My media" async def test_async_resolve_media(hass: HomeAssistant) -> None: diff --git a/tests/components/roku/test_media_player.py b/tests/components/roku/test_media_player.py index 1363cf7e286..5d4568ce7ac 100644 --- a/tests/components/roku/test_media_player.py +++ b/tests/components/roku/test_media_player.py @@ -864,7 +864,7 @@ async def test_media_browse_local_source( assert msg["result"]["children"][0]["title"] == "Apps" assert msg["result"]["children"][0]["media_content_type"] == MediaType.APPS - assert msg["result"]["children"][1]["title"] == "Local Media" + assert msg["result"]["children"][1]["title"] == "My media" assert msg["result"]["children"][1]["media_class"] == MediaClass.DIRECTORY assert msg["result"]["children"][1]["media_content_type"] is None assert ( @@ -892,7 +892,7 @@ async def test_media_browse_local_source( assert msg["success"] assert msg["result"] - assert msg["result"]["title"] == "Local Media" + assert msg["result"]["title"] == "My media" assert msg["result"]["media_class"] == MediaClass.DIRECTORY assert msg["result"]["media_content_type"] is None assert len(msg["result"]["children"]) == 2 From 13029cf26fb248fcf7225cddf117ea8602fc6bc8 Mon Sep 17 00:00:00 2001 From: James Connor Date: Thu, 8 Jun 2023 08:43:30 +0100 Subject: [PATCH 07/25] Fix ambiclimate for Python 3.11 (#94203) Fix ambiclimate python 3.11 break --- homeassistant/components/ambiclimate/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/ambiclimate/climate.py b/homeassistant/components/ambiclimate/climate.py index 2bb2b441430..516ed319d01 100644 --- a/homeassistant/components/ambiclimate/climate.py +++ b/homeassistant/components/ambiclimate/climate.py @@ -98,7 +98,7 @@ async def async_setup_entry( tasks = [] for heater in data_connection.get_devices(): - tasks.append(heater.update_device_info()) + tasks.append(asyncio.create_task(heater.update_device_info())) await asyncio.wait(tasks) devs = [] From ac963a2b6e136db6b3c38156cc07aba8769f0429 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Thu, 8 Jun 2023 00:41:45 -0700 Subject: [PATCH 08/25] Require pydantic 1.10.8 or higher (#94208) * Requied pydantic 1.10.9 or higher * Simplify constraint to 2.0 * Drop constraint by one patch release to 1.10.8 or higher * Add package constraints to gen requirements script --- homeassistant/package_constraints.txt | 5 ++--- script/gen_requirements_all.py | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 22d47a0e430..60389bd5895 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -128,9 +128,8 @@ authlib<1.0 # Version 2.0 added typing, prevent accidental fallbacks backoff>=2.0 -# Breaking change in version -# https://github.com/samuelcolvin/pydantic/issues/4092 -pydantic!=1.9.1 +# Require to avoid issues with decorators (#93904). v2 has breaking changes. +pydantic>=1.10.8,<2.0 # Breaks asyncio # https://github.com/pubnub/python/issues/130 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index b51ddb46307..1b5969a6e86 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -132,9 +132,8 @@ authlib<1.0 # Version 2.0 added typing, prevent accidental fallbacks backoff>=2.0 -# Breaking change in version -# https://github.com/samuelcolvin/pydantic/issues/4092 -pydantic!=1.9.1 +# Require to avoid issues with decorators (#93904). v2 has breaking changes. +pydantic>=1.10.8,<2.0 # Breaks asyncio # https://github.com/pubnub/python/issues/130 From b508875f17fbc7624c240a82efdb93361702fbe1 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Thu, 8 Jun 2023 09:39:06 +0200 Subject: [PATCH 09/25] Set httpx log level to warning (#94217) Set log level of httpx to warning --- homeassistant/bootstrap.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 7e5aa853f12..6a667884962 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -391,6 +391,7 @@ def async_enable_logging( logging.getLogger("requests").setLevel(logging.WARNING) logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("aiohttp.access").setLevel(logging.WARNING) + logging.getLogger("httpx").setLevel(logging.WARNING) sys.excepthook = lambda *args: logging.getLogger(None).exception( "Uncaught exception", exc_info=args # type: ignore[arg-type] From 33bf8c600b58ac3ea21e7b1f330290ec74393118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 8 Jun 2023 11:34:56 +0200 Subject: [PATCH 10/25] Update aioairzone-cloud to v0.1.8 (#94223) --- homeassistant/components/airzone_cloud/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/airzone_cloud/manifest.json b/homeassistant/components/airzone_cloud/manifest.json index b2899a7c80c..e64a5d9a7e2 100644 --- a/homeassistant/components/airzone_cloud/manifest.json +++ b/homeassistant/components/airzone_cloud/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/airzone_cloud", "iot_class": "cloud_polling", "loggers": ["aioairzone_cloud"], - "requirements": ["aioairzone-cloud==0.1.7"] + "requirements": ["aioairzone-cloud==0.1.8"] } diff --git a/requirements_all.txt b/requirements_all.txt index 0a93bc39854..4e11e624a0d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -116,7 +116,7 @@ aio_georss_gdacs==0.8 aioairq==0.2.4 # homeassistant.components.airzone_cloud -aioairzone-cloud==0.1.7 +aioairzone-cloud==0.1.8 # homeassistant.components.airzone aioairzone==0.6.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5449b3d3b8f..c6deeee2761 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -106,7 +106,7 @@ aio_georss_gdacs==0.8 aioairq==0.2.4 # homeassistant.components.airzone_cloud -aioairzone-cloud==0.1.7 +aioairzone-cloud==0.1.8 # homeassistant.components.airzone aioairzone==0.6.3 From 4509e13cebdcd451bed9c84fbf330ae82c244a52 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 1 Jun 2023 17:01:51 +0200 Subject: [PATCH 11/25] Bump python-opensky (#93916) --- homeassistant/components/opensky/manifest.json | 2 +- homeassistant/components/opensky/sensor.py | 2 +- requirements_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/opensky/manifest.json b/homeassistant/components/opensky/manifest.json index 854f2ec840b..460453968b6 100644 --- a/homeassistant/components/opensky/manifest.json +++ b/homeassistant/components/opensky/manifest.json @@ -4,5 +4,5 @@ "codeowners": ["@joostlek"], "documentation": "https://www.home-assistant.io/integrations/opensky", "iot_class": "cloud_polling", - "requirements": ["python-opensky==0.0.7"] + "requirements": ["python-opensky==0.0.8"] } diff --git a/homeassistant/components/opensky/sensor.py b/homeassistant/components/opensky/sensor.py index f3704f8d547..cdedd0c9620 100644 --- a/homeassistant/components/opensky/sensor.py +++ b/homeassistant/components/opensky/sensor.py @@ -78,7 +78,7 @@ def setup_platform( latitude = config.get(CONF_LATITUDE, hass.config.latitude) longitude = config.get(CONF_LONGITUDE, hass.config.longitude) radius = config.get(CONF_RADIUS, 0) - bounding_box = OpenSky.get_bounding_box(latitude, longitude, radius) + bounding_box = OpenSky.get_bounding_box(latitude, longitude, radius * 1000) session = async_get_clientsession(hass) opensky = OpenSky(session=session) add_entities( diff --git a/requirements_all.txt b/requirements_all.txt index 4e11e624a0d..1e339f383f0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2102,7 +2102,7 @@ python-mystrom==2.2.0 python-nest==4.2.0 # homeassistant.components.opensky -python-opensky==0.0.7 +python-opensky==0.0.8 # homeassistant.components.otbr # homeassistant.components.thread From 3b27a3aabff1e8719044eb0c627fd9af814b8ee3 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 8 Jun 2023 11:13:24 +0200 Subject: [PATCH 12/25] Bump python-opensky to 0.0.9 (#94224) --- homeassistant/components/opensky/manifest.json | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/opensky/manifest.json b/homeassistant/components/opensky/manifest.json index 460453968b6..cda86006bbd 100644 --- a/homeassistant/components/opensky/manifest.json +++ b/homeassistant/components/opensky/manifest.json @@ -4,5 +4,5 @@ "codeowners": ["@joostlek"], "documentation": "https://www.home-assistant.io/integrations/opensky", "iot_class": "cloud_polling", - "requirements": ["python-opensky==0.0.8"] + "requirements": ["python-opensky==0.0.9"] } diff --git a/requirements_all.txt b/requirements_all.txt index 1e339f383f0..0fbe396033c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2102,7 +2102,7 @@ python-mystrom==2.2.0 python-nest==4.2.0 # homeassistant.components.opensky -python-opensky==0.0.8 +python-opensky==0.0.9 # homeassistant.components.otbr # homeassistant.components.thread From 413e1c97d701ab0ece401d46c012aba83ec272ae Mon Sep 17 00:00:00 2001 From: Kostas Chatzikokolakis Date: Thu, 8 Jun 2023 16:59:16 +0300 Subject: [PATCH 13/25] Bump pulsectl to 23.5.2 (#94227) --- homeassistant/components/pulseaudio_loopback/manifest.json | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/pulseaudio_loopback/manifest.json b/homeassistant/components/pulseaudio_loopback/manifest.json index f04538c01bb..a67dc614c50 100644 --- a/homeassistant/components/pulseaudio_loopback/manifest.json +++ b/homeassistant/components/pulseaudio_loopback/manifest.json @@ -4,5 +4,5 @@ "codeowners": [], "documentation": "https://www.home-assistant.io/integrations/pulseaudio_loopback", "iot_class": "local_polling", - "requirements": ["pulsectl==20.2.4"] + "requirements": ["pulsectl==23.5.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index 0fbe396033c..f1b8642fce3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1418,7 +1418,7 @@ psutil-home-assistant==0.0.1 psutil==5.9.5 # homeassistant.components.pulseaudio_loopback -pulsectl==20.2.4 +pulsectl==23.5.2 # homeassistant.components.androidtv pure-python-adb[async]==0.3.0.dev0 From 0cf3825183ab341aff146b62d2869aec97dcc9c5 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Thu, 8 Jun 2023 11:11:12 +0200 Subject: [PATCH 14/25] Fix imap crash on email without subject (#94230) --- homeassistant/components/imap/coordinator.py | 2 +- tests/components/imap/const.py | 20 ++++++++++ tests/components/imap/test_init.py | 41 +++++++++++++++++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/imap/coordinator.py b/homeassistant/components/imap/coordinator.py index d41aaf8c497..bf7f173e647 100644 --- a/homeassistant/components/imap/coordinator.py +++ b/homeassistant/components/imap/coordinator.py @@ -120,7 +120,7 @@ class ImapMessage: @property def subject(self) -> str: """Decode the message subject.""" - decoded_header = decode_header(self.email_message["Subject"]) + decoded_header = decode_header(self.email_message["Subject"] or "") subject_header = make_header(decoded_header) return str(subject_header) diff --git a/tests/components/imap/const.py b/tests/components/imap/const.py index 15b56547894..5dcce782a41 100644 --- a/tests/components/imap/const.py +++ b/tests/components/imap/const.py @@ -24,7 +24,12 @@ TEST_MESSAGE_HEADERS2 = ( b"Subject: Test subject\r\n" ) +TEST_MESSAGE_HEADERS3 = b"" + TEST_MESSAGE = TEST_MESSAGE_HEADERS1 + DATE_HEADER1 + TEST_MESSAGE_HEADERS2 +TEST_MESSAGE_NO_SUBJECT_TO_FROM = ( + TEST_MESSAGE_HEADERS1 + DATE_HEADER1 + TEST_MESSAGE_HEADERS3 +) TEST_MESSAGE_ALT = TEST_MESSAGE_HEADERS1 + DATE_HEADER2 + TEST_MESSAGE_HEADERS2 TEST_INVALID_DATE1 = ( TEST_MESSAGE_HEADERS1 + DATE_HEADER_INVALID1 + TEST_MESSAGE_HEADERS2 @@ -204,4 +209,19 @@ TEST_FETCH_RESPONSE_MULTIPART = ( ], ) + +TEST_FETCH_RESPONSE_NO_SUBJECT_TO_FROM = ( + "OK", + [ + b"1 FETCH (BODY[] {" + + str(len(TEST_MESSAGE_NO_SUBJECT_TO_FROM + TEST_CONTENT_TEXT_PLAIN)).encode( + "utf-8" + ) + + b"}", + bytearray(TEST_MESSAGE_NO_SUBJECT_TO_FROM + TEST_CONTENT_TEXT_PLAIN), + b")", + b"Fetch completed (0.0001 + 0.000 secs).", + ], +) + RESPONSE_BAD = ("BAD", []) diff --git a/tests/components/imap/test_init.py b/tests/components/imap/test_init.py index 712f159b4cb..2b7514cd3ea 100644 --- a/tests/components/imap/test_init.py +++ b/tests/components/imap/test_init.py @@ -1,6 +1,6 @@ """Test the imap entry initialization.""" import asyncio -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import Any from unittest.mock import AsyncMock, MagicMock, patch @@ -22,6 +22,7 @@ from .const import ( TEST_FETCH_RESPONSE_INVALID_DATE2, TEST_FETCH_RESPONSE_INVALID_DATE3, TEST_FETCH_RESPONSE_MULTIPART, + TEST_FETCH_RESPONSE_NO_SUBJECT_TO_FROM, TEST_FETCH_RESPONSE_TEXT_BARE, TEST_FETCH_RESPONSE_TEXT_OTHER, TEST_FETCH_RESPONSE_TEXT_PLAIN, @@ -153,6 +154,44 @@ async def test_receiving_message_successfully( ) +@pytest.mark.parametrize("imap_search", [TEST_SEARCH_RESPONSE]) +@pytest.mark.parametrize("imap_fetch", [TEST_FETCH_RESPONSE_NO_SUBJECT_TO_FROM]) +@pytest.mark.parametrize("imap_has_capability", [True, False], ids=["push", "poll"]) +async def test_receiving_message_no_subject_to_from( + hass: HomeAssistant, mock_imap_protocol: MagicMock +) -> None: + """Test receiving a message successfully without subject, to and from in body.""" + event_called = async_capture_events(hass, "imap_content") + + config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG) + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + # Make sure we have had one update (when polling) + async_fire_time_changed(hass, utcnow() + timedelta(seconds=5)) + await hass.async_block_till_done() + state = hass.states.get("sensor.imap_email_email_com") + # we should have received one message + assert state is not None + assert state.state == "1" + + # we should have received one event + assert len(event_called) == 1 + data: dict[str, Any] = event_called[0].data + assert data["server"] == "imap.server.com" + assert data["username"] == "email@email.com" + assert data["search"] == "UnSeen UnDeleted" + assert data["folder"] == "INBOX" + assert data["sender"] == "" + assert data["subject"] == "" + assert data["date"] == datetime( + 2023, 3, 24, 13, 52, tzinfo=timezone(timedelta(seconds=3600)) + ) + assert data["text"] == "Test body\r\n\r\n" + assert data["headers"]["Return-Path"] == ("",) + assert data["headers"]["Delivered-To"] == ("notify@example.com",) + + @pytest.mark.parametrize("imap_has_capability", [True, False], ids=["push", "poll"]) @pytest.mark.parametrize( ("imap_login_state", "success"), [(AUTH, True), (NONAUTH, False)] From 2b1c45c28c75a221c6c5d24d33d6ade1c9bef47e Mon Sep 17 00:00:00 2001 From: jan iversen Date: Thu, 8 Jun 2023 11:29:54 +0200 Subject: [PATCH 15/25] Solve wrong return code from modbus. (#94234) --- homeassistant/components/flexit/climate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/flexit/climate.py b/homeassistant/components/flexit/climate.py index ac8f4b4da8c..838d2c934f9 100644 --- a/homeassistant/components/flexit/climate.py +++ b/homeassistant/components/flexit/climate.py @@ -192,7 +192,7 @@ class Flexit(ClimateEntity): result = float( await self._async_read_int16_from_register(register_type, register) ) - if result == -1: + if not result: return -1 return result / 10.0 @@ -200,6 +200,6 @@ class Flexit(ClimateEntity): result = await self._hub.async_pymodbus_call( self._slave, register, value, CALL_TYPE_WRITE_REGISTER ) - if result == -1: + if not result: return False return True From 8705a26a1a6611c9a389b8fe229554cd1605e589 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 8 Jun 2023 16:08:18 +0200 Subject: [PATCH 16/25] Catch exception when user has no lastfm friends (#94235) --- homeassistant/components/lastfm/config_flow.py | 6 +++--- tests/components/lastfm/__init__.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/lastfm/config_flow.py b/homeassistant/components/lastfm/config_flow.py index f7d7a9fd314..9b7628cb39a 100644 --- a/homeassistant/components/lastfm/config_flow.py +++ b/homeassistant/components/lastfm/config_flow.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Any -from pylast import LastFMNetwork, User, WSError +from pylast import LastFMNetwork, PyLastError, User, WSError import voluptuous as vol from homeassistant.config_entries import ( @@ -132,7 +132,7 @@ class LastFmConfigFlowHandler(ConfigFlow, domain=DOMAIN): SelectOptionDict(value=friend.name, label=friend.get_name(True)) for friend in main_user.get_friends() ] - except WSError: + except PyLastError: friends = [] return self.async_show_form( step_id="friends", @@ -201,7 +201,7 @@ class LastFmOptionsFlowHandler(OptionsFlowWithConfigEntry): SelectOptionDict(value=friend.name, label=friend.get_name(True)) for friend in main_user.get_friends() ] - except WSError: + except PyLastError: friends = [] else: friends = [] diff --git a/tests/components/lastfm/__init__.py b/tests/components/lastfm/__init__.py index 568983f400d..7ee8665e28a 100644 --- a/tests/components/lastfm/__init__.py +++ b/tests/components/lastfm/__init__.py @@ -1,7 +1,7 @@ """The tests for lastfm.""" from unittest.mock import patch -from pylast import Track, WSError +from pylast import PyLastError, Track from homeassistant.components.lastfm.const import CONF_MAIN_USER, CONF_USERS from homeassistant.const import CONF_API_KEY @@ -65,7 +65,7 @@ class MockUser: def get_friends(self): """Get mock friends.""" if self._has_friends is False: - raise WSError("network", "status", "Page not found") + raise PyLastError("network", "status", "Page not found") return [MockUser(None, None, True, USERNAME_2)] From a3fda43c6426f97373c015b0fcc1c0401b18253f Mon Sep 17 00:00:00 2001 From: Jc2k Date: Thu, 8 Jun 2023 14:10:12 +0100 Subject: [PATCH 17/25] Bump aiohomekit to 2.6.5 (fixes python 3.11 regression) (#94245) --- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index 89261df8751..19167e762e9 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "iot_class": "local_push", "loggers": ["aiohomekit", "commentjson"], - "requirements": ["aiohomekit==2.6.4"], + "requirements": ["aiohomekit==2.6.5"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index f1b8642fce3..8fce6b13a04 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -177,7 +177,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.4 +aiohomekit==2.6.5 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c6deeee2761..9a73ebc5e05 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -164,7 +164,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.4 +aiohomekit==2.6.5 # homeassistant.components.emulated_hue # homeassistant.components.http From d861292900b0128c51f8fca04912e7c79420b344 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 8 Jun 2023 15:55:09 +0200 Subject: [PATCH 18/25] Retrieve friends in an async manner in Lastfm (#94255) --- homeassistant/components/lastfm/config_flow.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/lastfm/config_flow.py b/homeassistant/components/lastfm/config_flow.py index 9b7628cb39a..54406a6e03b 100644 --- a/homeassistant/components/lastfm/config_flow.py +++ b/homeassistant/components/lastfm/config_flow.py @@ -128,9 +128,12 @@ class LastFmConfigFlowHandler(ConfigFlow, domain=DOMAIN): main_user, _ = get_lastfm_user( self.data[CONF_API_KEY], self.data[CONF_MAIN_USER] ) + friends_response = await self.hass.async_add_executor_job( + main_user.get_friends + ) friends = [ SelectOptionDict(value=friend.name, label=friend.get_name(True)) - for friend in main_user.get_friends() + for friend in friends_response ] except PyLastError: friends = [] @@ -197,9 +200,12 @@ class LastFmOptionsFlowHandler(OptionsFlowWithConfigEntry): self.options[CONF_API_KEY], self.options[CONF_MAIN_USER], ) + friends_response = await self.hass.async_add_executor_job( + main_user.get_friends + ) friends = [ SelectOptionDict(value=friend.name, label=friend.get_name(True)) - for friend in main_user.get_friends() + for friend in friends_response ] except PyLastError: friends = [] From 5da0ef36eacbdc2e870ff8aa8b5bbcc0d8f1e187 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 8 Jun 2023 15:59:56 +0200 Subject: [PATCH 19/25] Update frontend to 20230608.0 (#94256) --- homeassistant/components/frontend/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index af8898f28e2..00753021b4c 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -20,5 +20,5 @@ "documentation": "https://www.home-assistant.io/integrations/frontend", "integration_type": "system", "quality_scale": "internal", - "requirements": ["home-assistant-frontend==20230607.0"] + "requirements": ["home-assistant-frontend==20230608.0"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 60389bd5895..a7688415905 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -25,7 +25,7 @@ ha-av==10.1.0 hass-nabucasa==0.67.1 hassil==1.0.6 home-assistant-bluetooth==1.10.0 -home-assistant-frontend==20230607.0 +home-assistant-frontend==20230608.0 home-assistant-intents==2023.6.5 httpx==0.24.1 ifaddr==0.2.0 diff --git a/requirements_all.txt b/requirements_all.txt index 8fce6b13a04..14e41852492 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -924,7 +924,7 @@ hole==0.8.0 holidays==0.21.13 # homeassistant.components.frontend -home-assistant-frontend==20230607.0 +home-assistant-frontend==20230608.0 # homeassistant.components.conversation home-assistant-intents==2023.6.5 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9a73ebc5e05..e79f30e5c7c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -716,7 +716,7 @@ hole==0.8.0 holidays==0.21.13 # homeassistant.components.frontend -home-assistant-frontend==20230607.0 +home-assistant-frontend==20230608.0 # homeassistant.components.conversation home-assistant-intents==2023.6.5 From 2801ba6cad30216eda5e1250c3554ab2a6372113 Mon Sep 17 00:00:00 2001 From: Christopher Bailey Date: Thu, 8 Jun 2023 11:08:52 -0400 Subject: [PATCH 20/25] Bump unifiprotect to 4.10.2 (#94263) --- homeassistant/components/unifiprotect/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/unifiprotect/manifest.json b/homeassistant/components/unifiprotect/manifest.json index 78e2ee3012c..a414c03a0d4 100644 --- a/homeassistant/components/unifiprotect/manifest.json +++ b/homeassistant/components/unifiprotect/manifest.json @@ -41,7 +41,7 @@ "iot_class": "local_push", "loggers": ["pyunifiprotect", "unifi_discovery"], "quality_scale": "platinum", - "requirements": ["pyunifiprotect==4.10.1", "unifi-discovery==1.1.7"], + "requirements": ["pyunifiprotect==4.10.2", "unifi-discovery==1.1.7"], "ssdp": [ { "manufacturer": "Ubiquiti Networks", diff --git a/requirements_all.txt b/requirements_all.txt index 14e41852492..eca5516f7ec 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2168,7 +2168,7 @@ pytrafikverket==0.3.3 pyudev==0.23.2 # homeassistant.components.unifiprotect -pyunifiprotect==4.10.1 +pyunifiprotect==4.10.2 # homeassistant.components.uptimerobot pyuptimerobot==22.2.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e79f30e5c7c..7f48debc62b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1579,7 +1579,7 @@ pytrafikverket==0.3.3 pyudev==0.23.2 # homeassistant.components.unifiprotect -pyunifiprotect==4.10.1 +pyunifiprotect==4.10.2 # homeassistant.components.uptimerobot pyuptimerobot==22.2.0 From 40bb796f03fd4d223de3043128427464ce51aa57 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 8 Jun 2023 12:00:34 -0400 Subject: [PATCH 21/25] Fix default value when logger used (#94269) --- homeassistant/components/logger/__init__.py | 5 +---- homeassistant/components/logger/helpers.py | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/logger/__init__.py b/homeassistant/components/logger/__init__.py index fe29447aeba..b1086d7f780 100644 --- a/homeassistant/components/logger/__init__.py +++ b/homeassistant/components/logger/__init__.py @@ -13,7 +13,6 @@ from homeassistant.helpers.typing import ConfigType from . import websocket_api from .const import ( ATTR_LEVEL, - DEFAULT_LOGSEVERITY, DOMAIN, LOGGER_DEFAULT, LOGGER_FILTERS, @@ -39,9 +38,7 @@ CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema( { - vol.Optional( - LOGGER_DEFAULT, default=DEFAULT_LOGSEVERITY - ): _VALID_LOG_LEVEL, + vol.Optional(LOGGER_DEFAULT): _VALID_LOG_LEVEL, vol.Optional(LOGGER_LOGS): vol.Schema({cv.string: _VALID_LOG_LEVEL}), vol.Optional(LOGGER_FILTERS): vol.Schema({cv.string: [cv.is_regex]}), } diff --git a/homeassistant/components/logger/helpers.py b/homeassistant/components/logger/helpers.py index 0f1751c1b2e..dcd4348a561 100644 --- a/homeassistant/components/logger/helpers.py +++ b/homeassistant/components/logger/helpers.py @@ -119,7 +119,7 @@ class LoggerSettings: self._yaml_config = yaml_config self._default_level = logging.INFO - if DOMAIN in yaml_config: + if DOMAIN in yaml_config and LOGGER_DEFAULT in yaml_config[DOMAIN]: self._default_level = yaml_config[DOMAIN][LOGGER_DEFAULT] self._store: Store[dict[str, dict[str, dict[str, Any]]]] = Store( hass, STORAGE_VERSION, STORAGE_KEY From b39b0a960eef176164212ed18df09bfc3dd71670 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 8 Jun 2023 18:22:34 +0200 Subject: [PATCH 22/25] Fix repair issue about no yaml for config entries (#94271) --- homeassistant/setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/setup.py b/homeassistant/setup.py index d4b9be05ef4..fc5aa8291b7 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -245,7 +245,10 @@ async def _async_setup_component( severity=IssueSeverity.ERROR, issue_domain=domain, translation_key="integration_key_no_support", - translation_placeholders={"domain": domain}, + translation_placeholders={ + "domain": domain, + "add_integration": f"/config/integrations/dashboard/add?domain={domain}", + }, ) start = timer() From 602fcd6b1b1b886f88d3dce5c628740afb30ef81 Mon Sep 17 00:00:00 2001 From: Tom Harris Date: Thu, 1 Jun 2023 08:50:35 +0200 Subject: [PATCH 23/25] Restructure Insteon start-up (#92818) * Restructure startup * Code review * Further typing * Fix circular import --- .../components/insteon/binary_sensor.py | 9 +++- homeassistant/components/insteon/climate.py | 9 +++- homeassistant/components/insteon/cover.py | 9 +++- homeassistant/components/insteon/fan.py | 9 +++- homeassistant/components/insteon/ipdb.py | 15 +++--- homeassistant/components/insteon/light.py | 9 +++- homeassistant/components/insteon/lock.py | 9 +++- homeassistant/components/insteon/switch.py | 9 +++- homeassistant/components/insteon/utils.py | 51 ++++++++++++++----- 9 files changed, 97 insertions(+), 32 deletions(-) diff --git a/homeassistant/components/insteon/binary_sensor.py b/homeassistant/components/insteon/binary_sensor.py index 9d1ec352bed..f895b9c7f6a 100644 --- a/homeassistant/components/insteon/binary_sensor.py +++ b/homeassistant/components/insteon/binary_sensor.py @@ -25,7 +25,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import SIGNAL_ADD_ENTITIES from .insteon_entity import InsteonEntity -from .utils import async_add_insteon_entities +from .utils import async_add_insteon_devices, async_add_insteon_entities SENSOR_TYPES = { OPEN_CLOSE_SENSOR: BinarySensorDeviceClass.OPENING, @@ -62,7 +62,12 @@ async def async_setup_entry( signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.BINARY_SENSOR}" async_dispatcher_connect(hass, signal, async_add_insteon_binary_sensor_entities) - async_add_insteon_binary_sensor_entities() + async_add_insteon_devices( + hass, + Platform.BINARY_SENSOR, + InsteonBinarySensorEntity, + async_add_entities, + ) class InsteonBinarySensorEntity(InsteonEntity, BinarySensorEntity): diff --git a/homeassistant/components/insteon/climate.py b/homeassistant/components/insteon/climate.py index cf5f4ac2c0c..48ff898d6aa 100644 --- a/homeassistant/components/insteon/climate.py +++ b/homeassistant/components/insteon/climate.py @@ -23,7 +23,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import SIGNAL_ADD_ENTITIES from .insteon_entity import InsteonEntity -from .utils import async_add_insteon_entities +from .utils import async_add_insteon_devices, async_add_insteon_entities FAN_ONLY = "fan_only" @@ -71,7 +71,12 @@ async def async_setup_entry( signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.CLIMATE}" async_dispatcher_connect(hass, signal, async_add_insteon_climate_entities) - async_add_insteon_climate_entities() + async_add_insteon_devices( + hass, + Platform.CLIMATE, + InsteonClimateEntity, + async_add_entities, + ) class InsteonClimateEntity(InsteonEntity, ClimateEntity): diff --git a/homeassistant/components/insteon/cover.py b/homeassistant/components/insteon/cover.py index 69a66d304ce..0756e603579 100644 --- a/homeassistant/components/insteon/cover.py +++ b/homeassistant/components/insteon/cover.py @@ -15,7 +15,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import SIGNAL_ADD_ENTITIES from .insteon_entity import InsteonEntity -from .utils import async_add_insteon_entities +from .utils import async_add_insteon_devices, async_add_insteon_entities async def async_setup_entry( @@ -34,7 +34,12 @@ async def async_setup_entry( signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.COVER}" async_dispatcher_connect(hass, signal, async_add_insteon_cover_entities) - async_add_insteon_cover_entities() + async_add_insteon_devices( + hass, + Platform.COVER, + InsteonCoverEntity, + async_add_entities, + ) class InsteonCoverEntity(InsteonEntity, CoverEntity): diff --git a/homeassistant/components/insteon/fan.py b/homeassistant/components/insteon/fan.py index b0d664a821b..92f56098a91 100644 --- a/homeassistant/components/insteon/fan.py +++ b/homeassistant/components/insteon/fan.py @@ -17,7 +17,7 @@ from homeassistant.util.percentage import ( from .const import SIGNAL_ADD_ENTITIES from .insteon_entity import InsteonEntity -from .utils import async_add_insteon_entities +from .utils import async_add_insteon_devices, async_add_insteon_entities SPEED_RANGE = (1, 255) # off is not included @@ -38,7 +38,12 @@ async def async_setup_entry( signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.FAN}" async_dispatcher_connect(hass, signal, async_add_insteon_fan_entities) - async_add_insteon_fan_entities() + async_add_insteon_devices( + hass, + Platform.FAN, + InsteonFanEntity, + async_add_entities, + ) class InsteonFanEntity(InsteonEntity, FanEntity): diff --git a/homeassistant/components/insteon/ipdb.py b/homeassistant/components/insteon/ipdb.py index ee799e103f9..de3ba7d55f2 100644 --- a/homeassistant/components/insteon/ipdb.py +++ b/homeassistant/components/insteon/ipdb.py @@ -1,4 +1,7 @@ """Utility methods for the Insteon platform.""" +from collections.abc import Iterable + +from pyinsteon.device_types.device_base import Device from pyinsteon.device_types.ipdb import ( AccessControl_Morningstar, ClimateControl_Thermostat, @@ -44,7 +47,7 @@ from pyinsteon.device_types.ipdb import ( from homeassistant.const import Platform -DEVICE_PLATFORM = { +DEVICE_PLATFORM: dict[Device, dict[Platform, Iterable[int]]] = { AccessControl_Morningstar: {Platform.LOCK: [1]}, DimmableLightingControl: {Platform.LIGHT: [1]}, DimmableLightingControl_Dial: {Platform.LIGHT: [1]}, @@ -101,11 +104,11 @@ DEVICE_PLATFORM = { } -def get_device_platforms(device): +def get_device_platforms(device) -> dict[Platform, Iterable[int]]: """Return the HA platforms for a device type.""" - return DEVICE_PLATFORM.get(type(device), {}).keys() + return DEVICE_PLATFORM.get(type(device), {}) -def get_platform_groups(device, domain) -> dict: - """Return the platforms that a device belongs in.""" - return DEVICE_PLATFORM.get(type(device), {}).get(domain, {}) # type: ignore[attr-defined] +def get_device_platform_groups(device: Device, platform: Platform) -> Iterable[int]: + """Return the list of device groups for a platform.""" + return get_device_platforms(device).get(platform, []) diff --git a/homeassistant/components/insteon/light.py b/homeassistant/components/insteon/light.py index 44574c696b4..1c12bc794f9 100644 --- a/homeassistant/components/insteon/light.py +++ b/homeassistant/components/insteon/light.py @@ -12,7 +12,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import SIGNAL_ADD_ENTITIES from .insteon_entity import InsteonEntity -from .utils import async_add_insteon_entities +from .utils import async_add_insteon_devices, async_add_insteon_entities MAX_BRIGHTNESS = 255 @@ -37,7 +37,12 @@ async def async_setup_entry( signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.LIGHT}" async_dispatcher_connect(hass, signal, async_add_insteon_light_entities) - async_add_insteon_light_entities() + async_add_insteon_devices( + hass, + Platform.LIGHT, + InsteonDimmerEntity, + async_add_entities, + ) class InsteonDimmerEntity(InsteonEntity, LightEntity): diff --git a/homeassistant/components/insteon/lock.py b/homeassistant/components/insteon/lock.py index 75487e7696c..27fb0fd42d8 100644 --- a/homeassistant/components/insteon/lock.py +++ b/homeassistant/components/insteon/lock.py @@ -11,7 +11,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import SIGNAL_ADD_ENTITIES from .insteon_entity import InsteonEntity -from .utils import async_add_insteon_entities +from .utils import async_add_insteon_devices, async_add_insteon_entities async def async_setup_entry( @@ -30,7 +30,12 @@ async def async_setup_entry( signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.LOCK}" async_dispatcher_connect(hass, signal, async_add_insteon_lock_entities) - async_add_insteon_lock_entities() + async_add_insteon_devices( + hass, + Platform.LOCK, + InsteonLockEntity, + async_add_entities, + ) class InsteonLockEntity(InsteonEntity, LockEntity): diff --git a/homeassistant/components/insteon/switch.py b/homeassistant/components/insteon/switch.py index 8f7c396f213..8acde0429cd 100644 --- a/homeassistant/components/insteon/switch.py +++ b/homeassistant/components/insteon/switch.py @@ -10,7 +10,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import SIGNAL_ADD_ENTITIES from .insteon_entity import InsteonEntity -from .utils import async_add_insteon_entities +from .utils import async_add_insteon_devices, async_add_insteon_entities async def async_setup_entry( @@ -33,7 +33,12 @@ async def async_setup_entry( signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.SWITCH}" async_dispatcher_connect(hass, signal, async_add_insteon_switch_entities) - async_add_insteon_switch_entities() + async_add_insteon_devices( + hass, + Platform.SWITCH, + InsteonSwitchEntity, + async_add_entities, + ) class InsteonSwitchEntity(InsteonEntity, SwitchEntity): diff --git a/homeassistant/components/insteon/utils.py b/homeassistant/components/insteon/utils.py index 58b2430092c..2ef9913ab8c 100644 --- a/homeassistant/components/insteon/utils.py +++ b/homeassistant/components/insteon/utils.py @@ -1,7 +1,10 @@ """Utilities used by insteon component.""" +from __future__ import annotations + import asyncio from collections.abc import Callable import logging +from typing import TYPE_CHECKING, Any from pyinsteon import devices from pyinsteon.address import Address @@ -30,6 +33,7 @@ from homeassistant.const import ( CONF_ENTITY_ID, CONF_PLATFORM, ENTITY_MATCH_ALL, + Platform, ) from homeassistant.core import HomeAssistant, ServiceCall, callback from homeassistant.helpers import device_registry as dr @@ -38,6 +42,7 @@ from homeassistant.helpers.dispatcher import ( async_dispatcher_send, dispatcher_send, ) +from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import ( CONF_CAT, @@ -78,7 +83,7 @@ from .const import ( SRV_X10_ALL_LIGHTS_ON, SRV_X10_ALL_UNITS_OFF, ) -from .ipdb import get_device_platforms, get_platform_groups +from .ipdb import get_device_platform_groups, get_device_platforms from .schemas import ( ADD_ALL_LINK_SCHEMA, ADD_DEFAULT_LINKS_SCHEMA, @@ -89,6 +94,9 @@ from .schemas import ( X10_HOUSECODE_SCHEMA, ) +if TYPE_CHECKING: + from .insteon_entity import InsteonEntity + _LOGGER = logging.getLogger(__name__) @@ -160,6 +168,7 @@ def register_new_device_callback(hass): for platform in platforms: signal = f"{SIGNAL_ADD_ENTITIES}_{platform}" dispatcher_send(hass, signal, {"address": device.address}) + add_insteon_events(hass, device) devices.subscribe(async_new_insteon_device, force_strong_ref=True) @@ -383,20 +392,38 @@ def print_aldb_to_log(aldb): @callback def async_add_insteon_entities( - hass, platform, entity_type, async_add_entities, discovery_info -): - """Add Insteon devices to a platform.""" - new_entities = [] - device_list = [discovery_info.get("address")] if discovery_info else devices - - for address in device_list: - device = devices[address] - groups = get_platform_groups(device, platform) - for group in groups: - new_entities.append(entity_type(device, group)) + hass: HomeAssistant, + platform: Platform, + entity_type: type[InsteonEntity], + async_add_entities: AddEntitiesCallback, + discovery_info: dict[str, Any], +) -> None: + """Add an Insteon group to a platform.""" + address = discovery_info["address"] + device = devices[address] + new_entities = [ + entity_type(device=device, group=group) for group in discovery_info["groups"] + ] async_add_entities(new_entities) +@callback +def async_add_insteon_devices( + hass: HomeAssistant, + platform: Platform, + entity_type: type[InsteonEntity], + async_add_entities: AddEntitiesCallback, +) -> None: + """Add all entities to a platform.""" + for address in devices: + device = devices[address] + groups = get_device_platform_groups(device, platform) + discovery_info = {"address": address, "groups": groups} + async_add_insteon_entities( + hass, platform, entity_type, async_add_entities, discovery_info + ) + + def get_usb_ports() -> dict[str, str]: """Return a dict of USB ports and their friendly names.""" ports = list_ports.comports() From d745b4418070f1882bc5c75e2b86a154c5d4f28c Mon Sep 17 00:00:00 2001 From: Tom Harris Date: Thu, 8 Jun 2023 12:36:42 -0400 Subject: [PATCH 24/25] Fix Insteon startup for users with X10 devices (#94277) --- homeassistant/components/insteon/utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/insteon/utils.py b/homeassistant/components/insteon/utils.py index 2ef9913ab8c..f9c22ef62a5 100644 --- a/homeassistant/components/insteon/utils.py +++ b/homeassistant/components/insteon/utils.py @@ -140,6 +140,9 @@ def add_insteon_events(hass: HomeAssistant, device: Device) -> None: _LOGGER.debug("Firing event %s with %s", event, schema) hass.bus.async_fire(event, schema) + if str(device.address).startswith("X10"): + return + for name_or_group, event in device.events.items(): if isinstance(name_or_group, int): for _, event in device.events[name_or_group].items(): @@ -166,8 +169,9 @@ def register_new_device_callback(hass): await device.async_status() platforms = get_device_platforms(device) for platform in platforms: + groups = get_device_platform_groups(device, platform) signal = f"{SIGNAL_ADD_ENTITIES}_{platform}" - dispatcher_send(hass, signal, {"address": device.address}) + dispatcher_send(hass, signal, {"address": device.address, "groups": groups}) add_insteon_events(hass, device) devices.subscribe(async_new_insteon_device, force_strong_ref=True) From d9919707547cf6059974d4ffa7387e972412d91e Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 8 Jun 2023 13:39:33 -0400 Subject: [PATCH 25/25] Bumped version to 2023.6.1 --- homeassistant/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 9308d364ecb..3392b6dabd8 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -8,7 +8,7 @@ from .backports.enum import StrEnum APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 6 -PATCH_VERSION: Final = "0" +PATCH_VERSION: Final = "1" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0) diff --git a/pyproject.toml b/pyproject.toml index 2ece07d96e6..ca4f61a5ccc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.6.0" +version = "2023.6.1" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"