From d888579cbd076aed915b6787b3b1e4d3032ebd41 Mon Sep 17 00:00:00 2001 From: Robin Lintermann Date: Fri, 13 Feb 2026 21:41:05 +0100 Subject: [PATCH] Bump pysmarlaapi to 1.0.1 and compatibility changes (#162911) --- homeassistant/components/smarla/__init__.py | 10 ++++++++-- .../components/smarla/config_flow.py | 8 +++++++- homeassistant/components/smarla/manifest.json | 2 +- homeassistant/components/smarla/number.py | 2 +- homeassistant/components/smarla/sensor.py | 2 +- homeassistant/components/smarla/switch.py | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/smarla/conftest.py | 5 ++--- tests/components/smarla/test_config_flow.py | 20 ++++++++++--------- tests/components/smarla/test_init.py | 3 ++- 11 files changed, 36 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/smarla/__init__.py b/homeassistant/components/smarla/__init__.py index 533acb3375b..1dbae0e2346 100644 --- a/homeassistant/components/smarla/__init__.py +++ b/homeassistant/components/smarla/__init__.py @@ -1,6 +1,10 @@ """The Swing2Sleep Smarla integration.""" from pysmarlaapi import Connection, Federwiege +from pysmarlaapi.connection.exceptions import ( + AuthenticationException, + ConnectionException, +) from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_ACCESS_TOKEN @@ -17,8 +21,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: FederwiegeConfigEntry) - connection = Connection(HOST, token_b64=entry.data[CONF_ACCESS_TOKEN]) # Check if token still has access - if not await connection.refresh_token(): - raise ConfigEntryError("Invalid authentication") + try: + await connection.refresh_token() + except (ConnectionException, AuthenticationException) as e: + raise ConfigEntryError("Invalid authentication") from e federwiege = Federwiege(hass.loop, connection) federwiege.register() diff --git a/homeassistant/components/smarla/config_flow.py b/homeassistant/components/smarla/config_flow.py index 816adc85d1a..779add55a07 100644 --- a/homeassistant/components/smarla/config_flow.py +++ b/homeassistant/components/smarla/config_flow.py @@ -5,6 +5,10 @@ from __future__ import annotations from typing import Any from pysmarlaapi import Connection +from pysmarlaapi.connection.exceptions import ( + AuthenticationException, + ConnectionException, +) import voluptuous as vol from homeassistant.config_entries import ConfigFlow, ConfigFlowResult @@ -30,7 +34,9 @@ class SmarlaConfigFlow(ConfigFlow, domain=DOMAIN): errors["base"] = "malformed_token" return errors, None - if not await conn.refresh_token(): + try: + await conn.refresh_token() + except ConnectionException, AuthenticationException: errors["base"] = "invalid_auth" return errors, None diff --git a/homeassistant/components/smarla/manifest.json b/homeassistant/components/smarla/manifest.json index ca73f891587..ef2f3ae8e34 100644 --- a/homeassistant/components/smarla/manifest.json +++ b/homeassistant/components/smarla/manifest.json @@ -8,5 +8,5 @@ "iot_class": "cloud_push", "loggers": ["pysmarlaapi", "pysignalr"], "quality_scale": "bronze", - "requirements": ["pysmarlaapi==0.13.0"] + "requirements": ["pysmarlaapi==1.0.1"] } diff --git a/homeassistant/components/smarla/number.py b/homeassistant/components/smarla/number.py index b20afe8ae68..f6c4cd0df4c 100644 --- a/homeassistant/components/smarla/number.py +++ b/homeassistant/components/smarla/number.py @@ -2,7 +2,7 @@ from dataclasses import dataclass -from pysmarlaapi.federwiege.classes import Property +from pysmarlaapi.federwiege.services.classes import Property from homeassistant.components.number import ( NumberEntity, diff --git a/homeassistant/components/smarla/sensor.py b/homeassistant/components/smarla/sensor.py index 887bccf2e8c..9ab1c265485 100644 --- a/homeassistant/components/smarla/sensor.py +++ b/homeassistant/components/smarla/sensor.py @@ -2,7 +2,7 @@ from dataclasses import dataclass -from pysmarlaapi.federwiege.classes import Property +from pysmarlaapi.federwiege.services.classes import Property from homeassistant.components.sensor import ( SensorEntity, diff --git a/homeassistant/components/smarla/switch.py b/homeassistant/components/smarla/switch.py index d1cbb1364c4..108f4d227c0 100644 --- a/homeassistant/components/smarla/switch.py +++ b/homeassistant/components/smarla/switch.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from typing import Any -from pysmarlaapi.federwiege.classes import Property +from pysmarlaapi.federwiege.services.classes import Property from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription from homeassistant.core import HomeAssistant diff --git a/requirements_all.txt b/requirements_all.txt index 54dbe6391c9..1c345e31167 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2451,7 +2451,7 @@ pysma==1.1.0 pysmappee==0.2.29 # homeassistant.components.smarla -pysmarlaapi==0.13.0 +pysmarlaapi==1.0.1 # homeassistant.components.smartthings pysmartthings==3.5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d52b8891fb0..42fc631565d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2080,7 +2080,7 @@ pysma==1.1.0 pysmappee==0.2.29 # homeassistant.components.smarla -pysmarlaapi==0.13.0 +pysmarlaapi==1.0.1 # homeassistant.components.smartthings pysmartthings==3.5.2 diff --git a/tests/components/smarla/conftest.py b/tests/components/smarla/conftest.py index d25dab2446f..d711a936abd 100644 --- a/tests/components/smarla/conftest.py +++ b/tests/components/smarla/conftest.py @@ -5,8 +5,8 @@ from __future__ import annotations from collections.abc import Generator from unittest.mock import MagicMock, patch -from pysmarlaapi.classes import AuthToken -from pysmarlaapi.federwiege.classes import Property, Service +from pysmarlaapi import AuthToken +from pysmarlaapi.federwiege.services.classes import Property, Service import pytest from homeassistant.components.smarla.const import DOMAIN @@ -49,7 +49,6 @@ def mock_connection() -> Generator[MagicMock]: ): connection = mock_connection.return_value connection.token = AuthToken.from_json(MOCK_ACCESS_TOKEN_JSON) - connection.refresh_token.return_value = True yield connection diff --git a/tests/components/smarla/test_config_flow.py b/tests/components/smarla/test_config_flow.py index beccf6e4b95..3a7a0274618 100644 --- a/tests/components/smarla/test_config_flow.py +++ b/tests/components/smarla/test_config_flow.py @@ -1,7 +1,8 @@ """Test config flow for Swing2Sleep Smarla integration.""" -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock, patch +from pysmarlaapi.connection.exceptions import AuthenticationException import pytest from homeassistant.components.smarla.const import DOMAIN @@ -63,14 +64,15 @@ async def test_malformed_token(hass: HomeAssistant) -> None: @pytest.mark.usefixtures("mock_setup_entry") async def test_invalid_auth(hass: HomeAssistant, mock_connection: MagicMock) -> None: """Test we show user form on invalid auth.""" - with patch.object( - mock_connection, "refresh_token", new=AsyncMock(return_value=False) - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_USER}, - data=MOCK_USER_INPUT, - ) + mock_connection.refresh_token.side_effect = AuthenticationException + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_USER}, + data=MOCK_USER_INPUT, + ) + + mock_connection.refresh_token.side_effect = None assert result["type"] is FlowResultType.FORM assert result["step_id"] == "user" diff --git a/tests/components/smarla/test_init.py b/tests/components/smarla/test_init.py index 9523772d914..ea39ef55e00 100644 --- a/tests/components/smarla/test_init.py +++ b/tests/components/smarla/test_init.py @@ -2,6 +2,7 @@ from unittest.mock import MagicMock +from pysmarlaapi.connection.exceptions import AuthenticationException import pytest from homeassistant.config_entries import ConfigEntryState @@ -17,7 +18,7 @@ async def test_init_invalid_auth( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_connection: MagicMock ) -> None: """Test init invalid authentication behavior.""" - mock_connection.refresh_token.return_value = False + mock_connection.refresh_token.side_effect = AuthenticationException assert not await setup_integration(hass, mock_config_entry)