diff --git a/homeassistant/components/fritz/__init__.py b/homeassistant/components/fritz/__init__.py index 28036ef37e7..858bd74bb38 100644 --- a/homeassistant/components/fritz/__init__.py +++ b/homeassistant/components/fritz/__init__.py @@ -1,15 +1,19 @@ """Support for AVM Fritz!Box functions.""" import logging -from fritzconnection.core.exceptions import FritzConnectionException - from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from .common import AvmWrapper, FritzData -from .const import DATA_FRITZ, DOMAIN, FRITZ_EXCEPTIONS, PLATFORMS +from .const import ( + DATA_FRITZ, + DOMAIN, + FRITZ_AUTH_EXCEPTIONS, + FRITZ_EXCEPTIONS, + PLATFORMS, +) from .services import async_setup_services, async_unload_services _LOGGER = logging.getLogger(__name__) @@ -28,10 +32,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: try: await avm_wrapper.async_setup(entry.options) + except FRITZ_AUTH_EXCEPTIONS as ex: + raise ConfigEntryAuthFailed from ex except FRITZ_EXCEPTIONS as ex: raise ConfigEntryNotReady from ex - except FritzConnectionException as ex: - raise ConfigEntryAuthFailed from ex if ( "X_AVM-DE_UPnP1" in avm_wrapper.connection.services diff --git a/homeassistant/components/fritz/config_flow.py b/homeassistant/components/fritz/config_flow.py index df0277494ec..5474a171798 100644 --- a/homeassistant/components/fritz/config_flow.py +++ b/homeassistant/components/fritz/config_flow.py @@ -9,7 +9,7 @@ from typing import Any from urllib.parse import ParseResult, urlparse from fritzconnection import FritzConnection -from fritzconnection.core.exceptions import FritzConnectionException, FritzSecurityError +from fritzconnection.core.exceptions import FritzConnectionException import voluptuous as vol from homeassistant.components import ssdp @@ -32,6 +32,7 @@ from .const import ( ERROR_CANNOT_CONNECT, ERROR_UNKNOWN, ERROR_UPNP_NOT_CONFIGURED, + FRITZ_AUTH_EXCEPTIONS, ) _LOGGER = logging.getLogger(__name__) @@ -70,7 +71,7 @@ class FritzBoxToolsFlowHandler(ConfigFlow, domain=DOMAIN): timeout=60.0, pool_maxsize=30, ) - except FritzSecurityError: + except FRITZ_AUTH_EXCEPTIONS: return ERROR_AUTH_INVALID except FritzConnectionException: return ERROR_CANNOT_CONNECT diff --git a/homeassistant/components/fritz/const.py b/homeassistant/components/fritz/const.py index 77c5c02c288..d43ba2eda62 100644 --- a/homeassistant/components/fritz/const.py +++ b/homeassistant/components/fritz/const.py @@ -5,8 +5,11 @@ from typing import Literal from fritzconnection.core.exceptions import ( FritzActionError, FritzActionFailedError, + FritzAuthorizationError, + FritzConnectionException, FritzInternalError, FritzLookUpError, + FritzSecurityError, FritzServiceError, ) @@ -66,9 +69,12 @@ UPTIME_DEVIATION = 5 FRITZ_EXCEPTIONS = ( FritzActionError, FritzActionFailedError, + FritzConnectionException, FritzInternalError, FritzServiceError, FritzLookUpError, ) +FRITZ_AUTH_EXCEPTIONS = (FritzAuthorizationError, FritzSecurityError) + WIFI_STANDARD = {1: "2.4Ghz", 2: "5Ghz", 3: "5Ghz", 4: "Guest"} diff --git a/homeassistant/components/fritz/manifest.json b/homeassistant/components/fritz/manifest.json index d05668b9917..fe55f4dc0f6 100644 --- a/homeassistant/components/fritz/manifest.json +++ b/homeassistant/components/fritz/manifest.json @@ -2,7 +2,7 @@ "domain": "fritz", "name": "AVM FRITZ!Box Tools", "documentation": "https://www.home-assistant.io/integrations/fritz", - "requirements": ["fritzconnection==1.10.3", "xmltodict==0.13.0"], + "requirements": ["fritzconnection==1.11.0", "xmltodict==0.13.0"], "dependencies": ["network"], "codeowners": ["@mammuth", "@AaronDavidSchneider", "@chemelli74", "@mib1185"], "config_flow": true, diff --git a/homeassistant/components/fritzbox_callmonitor/manifest.json b/homeassistant/components/fritzbox_callmonitor/manifest.json index 79ca743bbeb..7f6839f975e 100644 --- a/homeassistant/components/fritzbox_callmonitor/manifest.json +++ b/homeassistant/components/fritzbox_callmonitor/manifest.json @@ -4,7 +4,7 @@ "integration_type": "device", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/fritzbox_callmonitor", - "requirements": ["fritzconnection==1.10.3"], + "requirements": ["fritzconnection==1.11.0"], "codeowners": ["@cdce8p"], "iot_class": "local_polling", "loggers": ["fritzconnection"] diff --git a/requirements_all.txt b/requirements_all.txt index 952e15dde50..0264365cdcc 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -748,7 +748,7 @@ freesms==0.2.0 # homeassistant.components.fritz # homeassistant.components.fritzbox_callmonitor -fritzconnection==1.10.3 +fritzconnection==1.11.0 # homeassistant.components.google_translate gTTS==2.2.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 4191d24756f..6751e2d07db 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -567,7 +567,7 @@ freebox-api==1.0.1 # homeassistant.components.fritz # homeassistant.components.fritzbox_callmonitor -fritzconnection==1.10.3 +fritzconnection==1.11.0 # homeassistant.components.google_translate gTTS==2.2.4 diff --git a/tests/components/fritz/test_config_flow.py b/tests/components/fritz/test_config_flow.py index 1eeb779da1f..800b1e68183 100644 --- a/tests/components/fritz/test_config_flow.py +++ b/tests/components/fritz/test_config_flow.py @@ -2,7 +2,12 @@ import dataclasses from unittest.mock import patch -from fritzconnection.core.exceptions import FritzConnectionException, FritzSecurityError +from fritzconnection.core.exceptions import ( + FritzAuthorizationError, + FritzConnectionException, + FritzSecurityError, +) +import pytest from homeassistant.components.device_tracker import ( CONF_CONSIDER_HOME, @@ -13,6 +18,7 @@ from homeassistant.components.fritz.const import ( ERROR_AUTH_INVALID, ERROR_CANNOT_CONNECT, ERROR_UNKNOWN, + FRITZ_AUTH_EXCEPTIONS, ) from homeassistant.components.ssdp import ATTR_UPNP_UDN from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_SSDP, SOURCE_USER @@ -120,7 +126,11 @@ async def test_user_already_configured( assert result["errors"]["base"] == "already_configured" -async def test_exception_security(hass: HomeAssistant, mock_get_source_ip): +@pytest.mark.parametrize( + "error", + FRITZ_AUTH_EXCEPTIONS, +) +async def test_exception_security(hass: HomeAssistant, mock_get_source_ip, error): """Test starting a flow by user with invalid credentials.""" result = await hass.config_entries.flow.async_init( @@ -131,7 +141,7 @@ async def test_exception_security(hass: HomeAssistant, mock_get_source_ip): with patch( "homeassistant.components.fritz.config_flow.FritzConnection", - side_effect=FritzSecurityError, + side_effect=error, ): result = await hass.config_entries.flow.async_configure( @@ -239,8 +249,16 @@ async def test_reauth_successful( assert mock_setup_entry.called +@pytest.mark.parametrize( + "side_effect,error", + [ + (FritzAuthorizationError, ERROR_AUTH_INVALID), + (FritzConnectionException, ERROR_CANNOT_CONNECT), + (FritzSecurityError, ERROR_AUTH_INVALID), + ], +) async def test_reauth_not_successful( - hass: HomeAssistant, fc_class_mock, mock_get_source_ip + hass: HomeAssistant, fc_class_mock, mock_get_source_ip, side_effect, error ): """Test starting a reauthentication flow but no connection found.""" @@ -249,7 +267,7 @@ async def test_reauth_not_successful( with patch( "homeassistant.components.fritz.config_flow.FritzConnection", - side_effect=FritzConnectionException, + side_effect=side_effect, ): result = await hass.config_entries.flow.async_init( @@ -271,7 +289,7 @@ async def test_reauth_not_successful( assert result["type"] == FlowResultType.FORM assert result["step_id"] == "reauth_confirm" - assert result["errors"]["base"] == "cannot_connect" + assert result["errors"]["base"] == error async def test_ssdp_already_configured( diff --git a/tests/components/fritz/test_init.py b/tests/components/fritz/test_init.py index ae05a5b31d6..a1fb25e1cb6 100644 --- a/tests/components/fritz/test_init.py +++ b/tests/components/fritz/test_init.py @@ -1,14 +1,17 @@ """Tests for Fritz!Tools.""" from unittest.mock import patch -from fritzconnection.core.exceptions import FritzSecurityError import pytest from homeassistant.components.device_tracker import ( CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME, ) -from homeassistant.components.fritz.const import DOMAIN, FRITZ_EXCEPTIONS +from homeassistant.components.fritz.const import ( + DOMAIN, + FRITZ_AUTH_EXCEPTIONS, + FRITZ_EXCEPTIONS, +) from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -60,7 +63,11 @@ async def test_options_reload(hass: HomeAssistant, fc_class_mock, fh_class_mock) mock_reload.assert_called_once() -async def test_setup_auth_fail(hass: HomeAssistant): +@pytest.mark.parametrize( + "error", + FRITZ_AUTH_EXCEPTIONS, +) +async def test_setup_auth_fail(hass: HomeAssistant, error): """Test starting a flow by user with an already configured device.""" entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) @@ -68,7 +75,7 @@ async def test_setup_auth_fail(hass: HomeAssistant): with patch( "homeassistant.components.fritz.common.FritzConnection", - side_effect=FritzSecurityError, + side_effect=error, ): assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done()