From fcc66139f843a65ebf2f1b593ae9381bdefcd99f Mon Sep 17 00:00:00 2001 From: Ron Klinkien Date: Sat, 12 Jun 2021 10:05:27 +0200 Subject: [PATCH 1/5] Replace garminconnect_aio with garminconnect_ha (#51730) * Fixed config_flow for multiple account creation * Replaced python package to fix multiple accounts * Replaced python package to fix multiple accounts * Implemented config entries user * Config entries user * Fixed test code config flow * Fixed patch --- .../components/garmin_connect/__init__.py | 22 +++-- .../components/garmin_connect/config_flow.py | 8 +- .../components/garmin_connect/manifest.json | 4 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- .../garmin_connect/test_config_flow.py | 96 +++++++++---------- 6 files changed, 65 insertions(+), 69 deletions(-) diff --git a/homeassistant/components/garmin_connect/__init__.py b/homeassistant/components/garmin_connect/__init__.py index 45c71bf1f07..bd8920e43a8 100644 --- a/homeassistant/components/garmin_connect/__init__.py +++ b/homeassistant/components/garmin_connect/__init__.py @@ -2,7 +2,7 @@ from datetime import date import logging -from garminconnect_aio import ( +from garminconnect_ha import ( Garmin, GarminConnectAuthenticationError, GarminConnectConnectionError, @@ -13,7 +13,6 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady -from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.util import Throttle from .const import DEFAULT_UPDATE_INTERVAL, DOMAIN @@ -26,14 +25,13 @@ PLATFORMS = ["sensor"] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): """Set up Garmin Connect from a config entry.""" - websession = async_get_clientsession(hass) username: str = entry.data[CONF_USERNAME] password: str = entry.data[CONF_PASSWORD] - garmin_client = Garmin(websession, username, password) + api = Garmin(username, password) try: - await garmin_client.login() + await hass.async_add_executor_job(api.login) except ( GarminConnectAuthenticationError, GarminConnectTooManyRequestsError, @@ -49,7 +47,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): _LOGGER.exception("Unknown error occurred during Garmin Connect login request") return False - garmin_data = GarminConnectData(hass, garmin_client) + garmin_data = GarminConnectData(hass, api) hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = garmin_data @@ -81,14 +79,20 @@ class GarminConnectData: today = date.today() try: - summary = await self.client.get_user_summary(today.isoformat()) - body = await self.client.get_body_composition(today.isoformat()) + summary = await self.hass.async_add_executor_job( + self.client.get_user_summary, today.isoformat() + ) + body = await self.hass.async_add_executor_job( + self.client.get_body_composition, today.isoformat() + ) self.data = { **summary, **body["totalAverage"], } - self.data["nextAlarm"] = await self.client.get_device_alarms() + self.data["nextAlarm"] = await self.hass.async_add_executor_job( + self.client.get_device_alarms + ) except ( GarminConnectAuthenticationError, GarminConnectTooManyRequestsError, diff --git a/homeassistant/components/garmin_connect/config_flow.py b/homeassistant/components/garmin_connect/config_flow.py index 8f83a9e1071..e9966859f99 100644 --- a/homeassistant/components/garmin_connect/config_flow.py +++ b/homeassistant/components/garmin_connect/config_flow.py @@ -1,7 +1,7 @@ """Config flow for Garmin Connect integration.""" import logging -from garminconnect_aio import ( +from garminconnect_ha import ( Garmin, GarminConnectAuthenticationError, GarminConnectConnectionError, @@ -11,7 +11,6 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_ID, CONF_PASSWORD, CONF_USERNAME -from homeassistant.helpers.aiohttp_client import async_get_clientsession from .const import DOMAIN @@ -38,15 +37,14 @@ class GarminConnectConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): if user_input is None: return await self._show_setup_form() - websession = async_get_clientsession(self.hass) username = user_input[CONF_USERNAME] password = user_input[CONF_PASSWORD] - garmin_client = Garmin(websession, username, password) + api = Garmin(username, password) errors = {} try: - await garmin_client.login() + await self.hass.async_add_executor_job(api.login) except GarminConnectConnectionError: errors["base"] = "cannot_connect" return await self._show_setup_form(errors) diff --git a/homeassistant/components/garmin_connect/manifest.json b/homeassistant/components/garmin_connect/manifest.json index 22e115d0e06..43b4a028290 100644 --- a/homeassistant/components/garmin_connect/manifest.json +++ b/homeassistant/components/garmin_connect/manifest.json @@ -2,8 +2,8 @@ "domain": "garmin_connect", "name": "Garmin Connect", "documentation": "https://www.home-assistant.io/integrations/garmin_connect", - "requirements": ["garminconnect_aio==0.1.4"], + "requirements": ["garminconnect_ha==0.1.6"], "codeowners": ["@cyberjunky"], "config_flow": true, "iot_class": "cloud_polling" -} +} \ No newline at end of file diff --git a/requirements_all.txt b/requirements_all.txt index 48e5632b730..6804280928e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -635,7 +635,7 @@ gTTS==2.2.2 garages-amsterdam==2.1.1 # homeassistant.components.garmin_connect -garminconnect_aio==0.1.4 +garminconnect_ha==0.1.6 # homeassistant.components.geniushub geniushub-client==0.6.30 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b2d64664395..f0e5b5f0abf 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -341,7 +341,7 @@ gTTS==2.2.2 garages-amsterdam==2.1.1 # homeassistant.components.garmin_connect -garminconnect_aio==0.1.4 +garminconnect_ha==0.1.6 # homeassistant.components.geo_json_events # homeassistant.components.usgs_earthquakes_feed diff --git a/tests/components/garmin_connect/test_config_flow.py b/tests/components/garmin_connect/test_config_flow.py index 2ad36ffa29c..dd56fba9c1c 100644 --- a/tests/components/garmin_connect/test_config_flow.py +++ b/tests/components/garmin_connect/test_config_flow.py @@ -1,12 +1,11 @@ """Test the Garmin Connect config flow.""" from unittest.mock import patch -from garminconnect_aio import ( +from garminconnect_ha import ( GarminConnectAuthenticationError, GarminConnectConnectionError, GarminConnectTooManyRequestsError, ) -import pytest from homeassistant import config_entries, data_entry_flow from homeassistant.components.garmin_connect.const import DOMAIN @@ -21,37 +20,23 @@ MOCK_CONF = { } -@pytest.fixture(name="mock_garmin_connect") -def mock_garmin(): - """Mock Garmin Connect.""" - with patch( - "homeassistant.components.garmin_connect.config_flow.Garmin", - ) as garmin: - garmin.return_value.login.return_value = MOCK_CONF[CONF_ID] - yield garmin.return_value - - async def test_show_form(hass): """Test that the form is served with no input.""" - result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["errors"] == {} assert result["step_id"] == config_entries.SOURCE_USER async def test_step_user(hass): """Test registering an integration and finishing flow works.""" - with patch( - "homeassistant.components.garmin_connect.Garmin.login", - return_value="my@email.address", - ), patch( "homeassistant.components.garmin_connect.async_setup_entry", return_value=True - ): + ), patch( + "homeassistant.components.garmin_connect.config_flow.Garmin", + ) as garmin: + garmin.return_value.login.return_value = MOCK_CONF[CONF_ID] result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF ) @@ -59,60 +44,69 @@ async def test_step_user(hass): assert result["data"] == MOCK_CONF -async def test_connection_error(hass, mock_garmin_connect): +async def test_connection_error(hass): """Test for connection error.""" - mock_garmin_connect.login.side_effect = GarminConnectConnectionError("errormsg") - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF - ) + with patch( + "homeassistant.components.garmin_connect.Garmin.login", + side_effect=GarminConnectConnectionError("errormsg"), + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"}, data=MOCK_CONF + ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {"base": "cannot_connect"} -async def test_authentication_error(hass, mock_garmin_connect): +async def test_authentication_error(hass): """Test for authentication error.""" - mock_garmin_connect.login.side_effect = GarminConnectAuthenticationError("errormsg") - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF - ) + with patch( + "homeassistant.components.garmin_connect.Garmin.login", + side_effect=GarminConnectAuthenticationError("errormsg"), + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"}, data=MOCK_CONF + ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {"base": "invalid_auth"} -async def test_toomanyrequest_error(hass, mock_garmin_connect): +async def test_toomanyrequest_error(hass): """Test for toomanyrequests error.""" - mock_garmin_connect.login.side_effect = GarminConnectTooManyRequestsError( - "errormsg" - ) - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF - ) + with patch( + "homeassistant.components.garmin_connect.Garmin.login", + side_effect=GarminConnectTooManyRequestsError("errormsg"), + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"}, data=MOCK_CONF + ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {"base": "too_many_requests"} -async def test_unknown_error(hass, mock_garmin_connect): +async def test_unknown_error(hass): """Test for unknown error.""" - mock_garmin_connect.login.side_effect = Exception - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF - ) + with patch( + "homeassistant.components.garmin_connect.Garmin.login", + side_effect=Exception, + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"}, data=MOCK_CONF + ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {"base": "unknown"} async def test_abort_if_already_setup(hass): """Test abort if already setup.""" - MockConfigEntry( - domain=DOMAIN, data=MOCK_CONF, unique_id=MOCK_CONF[CONF_ID] - ).add_to_hass(hass) with patch( - "homeassistant.components.garmin_connect.config_flow.Garmin", autospec=True - ) as garmin: - garmin.return_value.login.return_value = MOCK_CONF[CONF_ID] - + "homeassistant.components.garmin_connect.config_flow.Garmin", + ): + entry = MockConfigEntry( + domain=DOMAIN, data=MOCK_CONF, unique_id=MOCK_CONF[CONF_ID] + ) + entry.add_to_hass(hass) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "user"}, data=MOCK_CONF ) - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "already_configured" + assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT + assert result["reason"] == "already_configured" From 8f34d1cf3243fd30fac3c7de1c6420d2dc561116 Mon Sep 17 00:00:00 2001 From: Fredrik Erlandsson Date: Sun, 13 Jun 2021 11:38:55 +0200 Subject: [PATCH 2/5] Bump pydaikin, fix airbase issues (#51797) --- homeassistant/components/daikin/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/daikin/manifest.json b/homeassistant/components/daikin/manifest.json index 2db81e8f167..ec0b2716053 100644 --- a/homeassistant/components/daikin/manifest.json +++ b/homeassistant/components/daikin/manifest.json @@ -3,7 +3,7 @@ "name": "Daikin AC", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/daikin", - "requirements": ["pydaikin==2.4.1"], + "requirements": ["pydaikin==2.4.2"], "codeowners": ["@fredrike"], "zeroconf": ["_dkapi._tcp.local."], "quality_scale": "platinum", diff --git a/requirements_all.txt b/requirements_all.txt index 6804280928e..418a0561148 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1352,7 +1352,7 @@ pycsspeechtts==1.0.4 # pycups==1.9.73 # homeassistant.components.daikin -pydaikin==2.4.1 +pydaikin==2.4.2 # homeassistant.components.danfoss_air pydanfossair==0.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f0e5b5f0abf..10ff054154e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -747,7 +747,7 @@ pycomfoconnect==0.4 pycoolmasternet-async==0.1.2 # homeassistant.components.daikin -pydaikin==2.4.1 +pydaikin==2.4.2 # homeassistant.components.deconz pydeconz==79 From dcc7bc10e8cd42f8c958e41ca42807c892d5479c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Sun, 13 Jun 2021 10:21:26 +0200 Subject: [PATCH 3/5] Add httpcore with version 0.13.3 (#51799) --- homeassistant/package_constraints.txt | 4 ++++ script/gen_requirements_all.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index b4d8e99e54a..29af3f52a07 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -63,3 +63,7 @@ enum34==1000000000.0.0 typing==1000000000.0.0 uuid==1000000000.0.0 +# httpcore 0.13.4 breaks several integrations +# https://github.com/home-assistant/core/issues/51778 +httpcore==0.13.3 + diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 4fd96cb1b04..dc0c5fa2c10 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -83,6 +83,10 @@ enum34==1000000000.0.0 typing==1000000000.0.0 uuid==1000000000.0.0 +# httpcore 0.13.4 breaks several integrations +# https://github.com/home-assistant/core/issues/51778 +httpcore==0.13.3 + """ IGNORE_PRE_COMMIT_HOOK_ID = ( From ee7a2b29ad90ce63a7d77e7fb004b61cffd5276c Mon Sep 17 00:00:00 2001 From: Ludovico de Nittis Date: Mon, 14 Jun 2021 03:47:56 +0200 Subject: [PATCH 4/5] Bump pyialarm to 1.9.0 (#51804) --- homeassistant/components/ialarm/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ialarm/manifest.json b/homeassistant/components/ialarm/manifest.json index 08666129fd9..751faec56c7 100644 --- a/homeassistant/components/ialarm/manifest.json +++ b/homeassistant/components/ialarm/manifest.json @@ -2,7 +2,7 @@ "domain": "ialarm", "name": "Antifurto365 iAlarm", "documentation": "https://www.home-assistant.io/integrations/ialarm", - "requirements": ["pyialarm==1.8.1"], + "requirements": ["pyialarm==1.9.0"], "codeowners": ["@RyuzakiKK"], "config_flow": true, "iot_class": "local_polling" diff --git a/requirements_all.txt b/requirements_all.txt index 418a0561148..9b1cb90850d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1464,7 +1464,7 @@ pyhomematic==0.1.72 pyhomeworks==0.0.6 # homeassistant.components.ialarm -pyialarm==1.8.1 +pyialarm==1.9.0 # homeassistant.components.icloud pyicloud==0.10.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 10ff054154e..6ba61f4642e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -808,7 +808,7 @@ pyhiveapi==0.4.2 pyhomematic==0.1.72 # homeassistant.components.ialarm -pyialarm==1.8.1 +pyialarm==1.9.0 # homeassistant.components.icloud pyicloud==0.10.2 From fcb2c26a24d2eee9a0b8a276b44b3560b9ed23a6 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 15 Jun 2021 19:45:33 +0200 Subject: [PATCH 5/5] Bumped version to 2021.6.5 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 8eed701d74d..9c2c34c52f4 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -5,7 +5,7 @@ from typing import Final MAJOR_VERSION: Final = 2021 MINOR_VERSION: Final = 6 -PATCH_VERSION: Final = "4" +PATCH_VERSION: Final = "5" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 8, 0)