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
pull/103324/head
starkillerOG 2023-11-03 17:05:27 +01:00 committed by GitHub
parent c1d979dc07
commit 1df69f52e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 37 additions and 29 deletions

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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."""

View File

@ -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"]
}

View File

@ -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)

View File

@ -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

View File

@ -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."""

View File

@ -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

View File

@ -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