Catch all library errors in La Marzocco entity actions (#184057)

This commit is contained in:
epenet
2026-10-02 15:21:27 +02:00
committed by GitHub
parent 391259bc4d
commit 2ebbbcebe9
11 changed files with 69 additions and 29 deletions
@@ -5,7 +5,7 @@ from collections.abc import Callable, Coroutine
from dataclasses import dataclass
from typing import Any, override
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import LaMarzoccoError
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.core import HomeAssistant
@@ -75,7 +75,7 @@ class LaMarzoccoButtonEntity(LaMarzoccoEntity, ButtonEntity):
"""Press button."""
try:
await self.entity_description.press_fn(self.coordinator)
except RequestNotSuccessful as exc:
except (LaMarzoccoError, TimeoutError) as exc:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="button_error",
@@ -6,7 +6,7 @@ from typing import Any, cast, override
from pylamarzocco import LaMarzoccoMachine
from pylamarzocco.const import DoseMode, ModelName, PreExtractionMode, WidgetType
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import LaMarzoccoError
from pylamarzocco.models import (
BrewByWeightDoses,
CoffeeBoiler,
@@ -363,7 +363,7 @@ class LaMarzoccoNumberEntity(LaMarzoccoEntity, NumberEntity):
await self.entity_description.set_value_fn(
self.coordinator.device, value
)
except RequestNotSuccessful as exc:
except (LaMarzoccoError, TimeoutError) as exc:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="number_exception",
@@ -35,10 +35,7 @@ rules:
unique-config-entry: done
# Silver
action-exceptions:
status: exempt
comment: |
No custom actions are defined.
action-exceptions: done
config-entry-unloading: done
docs-configuration-parameters: done
docs-installation-parameters: done
@@ -13,7 +13,7 @@ from pylamarzocco.const import (
WidgetType,
)
from pylamarzocco.devices import LaMarzoccoMachine
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import LaMarzoccoError
from pylamarzocco.models import BrewByWeightDoses, PreBrewing, SteamBoilerLevel
from homeassistant.components.select import SelectEntity, SelectEntityDescription
@@ -198,7 +198,7 @@ class LaMarzoccoSelectEntity(LaMarzoccoEntity, SelectEntity):
await self.entity_description.select_option_fn(
self.coordinator.device, option
)
except RequestNotSuccessful as exc:
except (LaMarzoccoError, TimeoutError) as exc:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="select_option_error",
@@ -6,7 +6,7 @@ from typing import Any, cast, override
from pylamarzocco import LaMarzoccoMachine
from pylamarzocco.const import MachineMode, ModelName, WidgetType
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import LaMarzoccoError
from pylamarzocco.models import (
MachineStatus,
SteamBoilerLevel,
@@ -155,7 +155,7 @@ class LaMarzoccoSwitchEntity(LaMarzoccoEntity, SwitchEntity):
"""Turn device on."""
try:
await self.entity_description.control_fn(self.coordinator.device, True)
except RequestNotSuccessful as exc:
except (LaMarzoccoError, TimeoutError) as exc:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="switch_on_error",
@@ -168,7 +168,7 @@ class LaMarzoccoSwitchEntity(LaMarzoccoEntity, SwitchEntity):
"""Turn device off."""
try:
await self.entity_description.control_fn(self.coordinator.device, False)
except RequestNotSuccessful as exc:
except (LaMarzoccoError, TimeoutError) as exc:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="switch_off_error",
@@ -219,7 +219,7 @@ class LaMarzoccoAutoOnOffSwitchEntity(LaMarzoccoBaseEntity, SwitchEntity):
self._schedule_entry.enabled = state
try:
await self.coordinator.device.set_wakeup_schedule(self._schedule_entry)
except RequestNotSuccessful as exc:
except (LaMarzoccoError, TimeoutError) as exc:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="auto_on_off_error",
@@ -5,7 +5,7 @@ from dataclasses import dataclass
from typing import Any, override
from pylamarzocco.const import FirmwareType, UpdateStatus
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import LaMarzoccoError
from homeassistant.components.update import (
UpdateDeviceClass,
@@ -138,7 +138,7 @@ class LaMarzoccoUpdateEntity(LaMarzoccoEntity, UpdateEntity):
await asyncio.sleep(3)
counter += 1
except (TimeoutError, RequestNotSuccessful) as exc:
except (TimeoutError, LaMarzoccoError) as exc:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="update_failed",
+11 -2
View File
@@ -2,7 +2,7 @@
from unittest.mock import AsyncMock, MagicMock, patch
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import AuthFail, RequestNotSuccessful
import pytest
from syrupy.assertion import SnapshotAssertion
@@ -50,9 +50,18 @@ async def test_start_backflush(
mock_lamarzocco.start_backflush.assert_called_once()
@pytest.mark.parametrize(
"side_effect",
[
pytest.param(RequestNotSuccessful("Boom"), id="request_not_successful"),
pytest.param(AuthFail("Boom"), id="auth_fail"),
pytest.param(TimeoutError, id="timeout"),
],
)
async def test_button_error(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
side_effect: Exception | type[Exception],
) -> None:
"""Test the La Marzocco button error."""
serial_number = mock_lamarzocco.serial_number
@@ -60,7 +69,7 @@ async def test_button_error(
state = hass.states.get(f"button.{serial_number}_start_backflush")
assert state
mock_lamarzocco.start_backflush.side_effect = RequestNotSuccessful("Boom.")
mock_lamarzocco.start_backflush.side_effect = side_effect
with pytest.raises(HomeAssistantError) as exc_info:
await hass.services.async_call(
BUTTON_DOMAIN,
+11 -4
View File
@@ -10,7 +10,7 @@ from pylamarzocco.const import (
SmartStandByType,
WidgetType,
)
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import AuthFail, RequestNotSuccessful
import pytest
from syrupy.assertion import SnapshotAssertion
@@ -230,11 +230,20 @@ async def test_prebrew_off(
)
@pytest.mark.parametrize(
"side_effect",
[
pytest.param(RequestNotSuccessful("Boom"), id="request_not_successful"),
pytest.param(AuthFail("Boom"), id="auth_fail"),
pytest.param(TimeoutError, id="timeout"),
],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_number_error(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
side_effect: Exception | type[Exception],
) -> None:
"""Test number entities raise error on service call."""
await async_init_integration(hass, mock_config_entry)
@@ -243,9 +252,7 @@ async def test_number_error(
state = hass.states.get(f"number.{serial_number}_coffee_target_temperature")
assert state
mock_lamarzocco.set_coffee_target_temperature.side_effect = RequestNotSuccessful(
"Boom"
)
mock_lamarzocco.set_coffee_target_temperature.side_effect = side_effect
with pytest.raises(HomeAssistantError) as exc_info:
await hass.services.async_call(
NUMBER_DOMAIN,
+11 -2
View File
@@ -9,7 +9,7 @@ from pylamarzocco.const import (
SmartStandByType,
SteamTargetLevel,
)
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import AuthFail, RequestNotSuccessful
import pytest
from syrupy.assertion import SnapshotAssertion
@@ -169,10 +169,19 @@ async def test_smart_standby_mode(
)
@pytest.mark.parametrize(
"side_effect",
[
pytest.param(RequestNotSuccessful("Boom"), id="request_not_successful"),
pytest.param(AuthFail("Boom"), id="auth_fail"),
pytest.param(TimeoutError, id="timeout"),
],
)
@pytest.mark.usefixtures("init_integration")
async def test_select_errors(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
side_effect: Exception | type[Exception],
) -> None:
"""Test select errors."""
serial_number = mock_lamarzocco.serial_number
@@ -180,7 +189,7 @@ async def test_select_errors(
state = hass.states.get(f"select.{serial_number}_prebrew_infusion_mode")
assert state
mock_lamarzocco.set_pre_extraction_mode.side_effect = RequestNotSuccessful("Boom")
mock_lamarzocco.set_pre_extraction_mode.side_effect = side_effect
# Test setting invalid option
with pytest.raises(HomeAssistantError) as exc_info:
+12 -3
View File
@@ -4,7 +4,7 @@ from typing import Any
from unittest.mock import MagicMock, patch
from pylamarzocco.const import MachineState, SmartStandByType, WidgetType
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import AuthFail, RequestNotSuccessful
import pytest
from syrupy.assertion import SnapshotAssertion
@@ -150,10 +150,19 @@ async def test_auto_on_off_switches(
mock_lamarzocco.set_wakeup_schedule.assert_called_with(wake_up_sleep_entry)
@pytest.mark.parametrize(
"side_effect",
[
pytest.param(RequestNotSuccessful("Boom"), id="request_not_successful"),
pytest.param(AuthFail("Boom"), id="auth_fail"),
pytest.param(TimeoutError, id="timeout"),
],
)
async def test_switch_exceptions(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
side_effect: Exception | type[Exception],
) -> None:
"""Test the La Marzocco switches."""
await async_init_integration(hass, mock_config_entry)
@@ -163,7 +172,7 @@ async def test_switch_exceptions(
state = hass.states.get(f"switch.{serial_number}")
assert state
mock_lamarzocco.set_power.side_effect = RequestNotSuccessful("Boom")
mock_lamarzocco.set_power.side_effect = side_effect
with pytest.raises(HomeAssistantError) as exc_info:
await hass.services.async_call(
@@ -190,7 +199,7 @@ async def test_switch_exceptions(
state = hass.states.get(f"switch.{serial_number}_auto_on_off_os2oswx")
assert state
mock_lamarzocco.set_wakeup_schedule.side_effect = RequestNotSuccessful("Boom")
mock_lamarzocco.set_wakeup_schedule.side_effect = side_effect
with pytest.raises(HomeAssistantError) as exc_info:
await hass.services.async_call(
SWITCH_DOMAIN,
+11 -2
View File
@@ -4,7 +4,7 @@ from collections.abc import Generator
from unittest.mock import AsyncMock, MagicMock, patch
from pylamarzocco.const import FirmwareType, UpdateProgressInfo, UpdateStatus
from pylamarzocco.exceptions import RequestNotSuccessful
from pylamarzocco.exceptions import AuthFail, RequestNotSuccessful
from pylamarzocco.models import UpdateDetails
import pytest
from syrupy.assertion import SnapshotAssertion
@@ -100,10 +100,19 @@ async def test_update_process(
mock_lamarzocco.update_firmware.assert_called_once_with()
@pytest.mark.parametrize(
"side_effect",
[
pytest.param(RequestNotSuccessful("Boom"), id="request_not_successful"),
pytest.param(AuthFail("Boom"), id="auth_fail"),
pytest.param(TimeoutError, id="timeout"),
],
)
async def test_update_error(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
side_effect: Exception | type[Exception],
) -> None:
"""Test error during update."""
@@ -112,7 +121,7 @@ async def test_update_error(
state = hass.states.get(f"update.{mock_lamarzocco.serial_number}_gateway_firmware")
assert state
mock_lamarzocco.update_firmware.side_effect = RequestNotSuccessful("Boom")
mock_lamarzocco.update_firmware.side_effect = side_effect
with pytest.raises(HomeAssistantError) as exc_info:
await hass.services.async_call(