From 1df69f52e5cb602ed65f16de447490063a731050 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 3 Nov 2023 17:05:27 +0100 Subject: [PATCH] Bump reolink-aio to 0.7.14 and improve typing of Reolink (#103129) * Improve typing * fix mypy * Further improve typing * Restore Literal typing * Bump reolink_aio to 0.7.13 * Bump reolink-aio to 0.7.14 --- homeassistant/components/reolink/__init__.py | 11 ++++++++--- .../components/reolink/binary_sensor.py | 6 +++--- homeassistant/components/reolink/host.py | 18 ++++++++++-------- homeassistant/components/reolink/light.py | 16 ++++++++-------- homeassistant/components/reolink/manifest.json | 2 +- homeassistant/components/reolink/number.py | 4 ++-- homeassistant/components/reolink/sensor.py | 2 +- homeassistant/components/reolink/update.py | 3 ++- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 10 files changed, 37 insertions(+), 29 deletions(-) diff --git a/homeassistant/components/reolink/__init__.py b/homeassistant/components/reolink/__init__.py index fd62f8451fb..8425f29fbe8 100644 --- a/homeassistant/components/reolink/__init__.py +++ b/homeassistant/components/reolink/__init__.py @@ -10,6 +10,7 @@ from typing import Literal from reolink_aio.api import RETRY_ATTEMPTS from reolink_aio.exceptions import CredentialsInvalidError, ReolinkError +from reolink_aio.software_version import NewSoftwareVersion from homeassistant.config_entries import ConfigEntry from homeassistant.const import EVENT_HOMEASSISTANT_STOP, Platform @@ -45,7 +46,9 @@ class ReolinkData: host: ReolinkHost device_coordinator: DataUpdateCoordinator[None] - firmware_coordinator: DataUpdateCoordinator[str | Literal[False]] + firmware_coordinator: DataUpdateCoordinator[ + str | Literal[False] | NewSoftwareVersion + ] async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: @@ -86,7 +89,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b async with asyncio.timeout(host.api.timeout * (RETRY_ATTEMPTS + 2)): await host.renew() - async def async_check_firmware_update() -> str | Literal[False]: + async def async_check_firmware_update() -> str | Literal[ + False + ] | NewSoftwareVersion: """Check for firmware updates.""" if not host.api.supported(None, "update"): return False @@ -153,7 +158,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b return True -async def entry_update_listener(hass: HomeAssistant, config_entry: ConfigEntry): +async def entry_update_listener(hass: HomeAssistant, config_entry: ConfigEntry) -> None: """Update the configuration of the host entity.""" await hass.config_entries.async_reload(config_entry.entry_id) diff --git a/homeassistant/components/reolink/binary_sensor.py b/homeassistant/components/reolink/binary_sensor.py index 49e964e2b3f..7f2ff3e0053 100644 --- a/homeassistant/components/reolink/binary_sensor.py +++ b/homeassistant/components/reolink/binary_sensor.py @@ -32,7 +32,7 @@ from .entity import ReolinkChannelCoordinatorEntity class ReolinkBinarySensorEntityDescriptionMixin: """Mixin values for Reolink binary sensor entities.""" - value: Callable[[Host, int | None], bool] + value: Callable[[Host, int], bool] @dataclass @@ -43,7 +43,7 @@ class ReolinkBinarySensorEntityDescription( icon: str = "mdi:motion-sensor" icon_off: str = "mdi:motion-sensor-off" - supported: Callable[[Host, int | None], bool] = lambda host, ch: True + supported: Callable[[Host, int], bool] = lambda host, ch: True BINARY_SENSORS = ( @@ -169,6 +169,6 @@ class ReolinkBinarySensorEntity(ReolinkChannelCoordinatorEntity, BinarySensorEnt ) ) - async def _async_handle_event(self, event): + async def _async_handle_event(self, event: str) -> None: """Handle incoming event for motion detection.""" self.async_write_ha_state() diff --git a/homeassistant/components/reolink/host.py b/homeassistant/components/reolink/host.py index d470711267d..0075bbac4e6 100644 --- a/homeassistant/components/reolink/host.py +++ b/homeassistant/components/reolink/host.py @@ -4,7 +4,7 @@ from __future__ import annotations import asyncio from collections.abc import Mapping import logging -from typing import Any +from typing import Any, Literal import aiohttp from aiohttp.web import Request @@ -81,7 +81,7 @@ class ReolinkHost: return self._unique_id @property - def api(self): + def api(self) -> Host: """Return the API object.""" return self._api @@ -313,7 +313,7 @@ class ReolinkHost: """Call the API of the camera device to update the internal states.""" await self._api.get_states() - async def disconnect(self): + async def disconnect(self) -> None: """Disconnect from the API, so the connection will be released.""" try: await self._api.unsubscribe() @@ -335,7 +335,7 @@ class ReolinkHost: err, ) - async def _async_start_long_polling(self, initial=False): + async def _async_start_long_polling(self, initial=False) -> None: """Start ONVIF long polling task.""" if self._long_poll_task is None: try: @@ -364,7 +364,7 @@ class ReolinkHost: self._lost_subscription = False self._long_poll_task = asyncio.create_task(self._async_long_polling()) - async def _async_stop_long_polling(self): + async def _async_stop_long_polling(self) -> None: """Stop ONVIF long polling task.""" if self._long_poll_task is not None: self._long_poll_task.cancel() @@ -372,7 +372,7 @@ class ReolinkHost: await self._api.unsubscribe(sub_type=SubType.long_poll) - async def stop(self, event=None): + async def stop(self, event=None) -> None: """Disconnect the API.""" if self._cancel_poll is not None: self._cancel_poll() @@ -433,7 +433,7 @@ class ReolinkHost: else: self._lost_subscription = False - async def _renew(self, sub_type: SubType) -> None: + async def _renew(self, sub_type: Literal[SubType.push, SubType.long_poll]) -> None: """Execute the renew of the subscription.""" if not self._api.subscribed(sub_type): _LOGGER.debug( @@ -512,8 +512,10 @@ class ReolinkHost: _LOGGER.debug("Registered webhook: %s", event_id) - def unregister_webhook(self): + def unregister_webhook(self) -> None: """Unregister the webhook for motion events.""" + if self.webhook_id is None: + return _LOGGER.debug("Unregistering webhook %s", self.webhook_id) webhook.async_unregister(self._hass, self.webhook_id) self.webhook_id = None diff --git a/homeassistant/components/reolink/light.py b/homeassistant/components/reolink/light.py index 4ac8166410f..938093df4a3 100644 --- a/homeassistant/components/reolink/light.py +++ b/homeassistant/components/reolink/light.py @@ -38,8 +38,8 @@ class ReolinkLightEntityDescription( """A class that describes light entities.""" supported_fn: Callable[[Host, int], bool] = lambda api, ch: True - get_brightness_fn: Callable[[Host, int], int] | None = None - set_brightness_fn: Callable[[Host, int, float], Any] | None = None + get_brightness_fn: Callable[[Host, int], int | None] | None = None + set_brightness_fn: Callable[[Host, int, int], Any] | None = None LIGHT_ENTITIES = ( @@ -127,13 +127,13 @@ class ReolinkLightEntity(ReolinkChannelCoordinatorEntity, LightEntity): if self.entity_description.get_brightness_fn is None: return None - return round( - 255 - * ( - self.entity_description.get_brightness_fn(self._host.api, self._channel) - / 100.0 - ) + bright_pct = self.entity_description.get_brightness_fn( + self._host.api, self._channel ) + if bright_pct is None: + return None + + return round(255 * bright_pct / 100.0) async def async_turn_off(self, **kwargs: Any) -> None: """Turn light off.""" diff --git a/homeassistant/components/reolink/manifest.json b/homeassistant/components/reolink/manifest.json index 1c1d8dd96b1..9189de89efa 100644 --- a/homeassistant/components/reolink/manifest.json +++ b/homeassistant/components/reolink/manifest.json @@ -18,5 +18,5 @@ "documentation": "https://www.home-assistant.io/integrations/reolink", "iot_class": "local_push", "loggers": ["reolink_aio"], - "requirements": ["reolink-aio==0.7.12"] + "requirements": ["reolink-aio==0.7.14"] } diff --git a/homeassistant/components/reolink/number.py b/homeassistant/components/reolink/number.py index 24e5d1bd72b..6be0cef1670 100644 --- a/homeassistant/components/reolink/number.py +++ b/homeassistant/components/reolink/number.py @@ -26,7 +26,7 @@ from .entity import ReolinkChannelCoordinatorEntity class ReolinkNumberEntityDescriptionMixin: """Mixin values for Reolink number entities.""" - value: Callable[[Host, int], float] + value: Callable[[Host, int], float | None] method: Callable[[Host, int, float], Any] @@ -354,7 +354,7 @@ class ReolinkNumberEntity(ReolinkChannelCoordinatorEntity, NumberEntity): ) @property - def native_value(self) -> float: + def native_value(self) -> float | None: """State of the number entity.""" return self.entity_description.value(self._host.api, self._channel) diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index 6282f29e442..b9e8ddb8e73 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -44,7 +44,7 @@ class ReolinkSensorEntityDescription( class ReolinkHostSensorEntityDescriptionMixin: """Mixin values for Reolink host sensor entities.""" - value: Callable[[Host], int] + value: Callable[[Host], int | None] @dataclass diff --git a/homeassistant/components/reolink/update.py b/homeassistant/components/reolink/update.py index 57efe1d9e92..1c10671550d 100644 --- a/homeassistant/components/reolink/update.py +++ b/homeassistant/components/reolink/update.py @@ -35,7 +35,8 @@ async def async_setup_entry( class ReolinkUpdateEntity( - ReolinkBaseCoordinatorEntity[str | Literal[False]], UpdateEntity + ReolinkBaseCoordinatorEntity[str | Literal[False] | NewSoftwareVersion], + UpdateEntity, ): """Update entity for a Netgear device.""" diff --git a/requirements_all.txt b/requirements_all.txt index 668157c9f9b..b44bde07de5 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2322,7 +2322,7 @@ renault-api==0.2.0 renson-endura-delta==1.6.0 # homeassistant.components.reolink -reolink-aio==0.7.12 +reolink-aio==0.7.14 # homeassistant.components.idteck_prox rfk101py==0.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 7763382824e..fddf181b168 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1733,7 +1733,7 @@ renault-api==0.2.0 renson-endura-delta==1.6.0 # homeassistant.components.reolink -reolink-aio==0.7.12 +reolink-aio==0.7.14 # homeassistant.components.rflink rflink==0.0.65