Small cleanup of sonarr sensor platform (#65962)

This commit is contained in:
Chris Talkington 2022-02-07 02:53:23 -06:00 committed by GitHub
parent 18ac72f613
commit f05caf451e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 8 deletions

View File

@ -1,11 +1,14 @@
"""Support for Sonarr sensors.""" """Support for Sonarr sensors."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Awaitable, Callable, Coroutine
from datetime import timedelta from datetime import timedelta
from functools import wraps
import logging import logging
from typing import Any from typing import Any, TypeVar
from sonarr import Sonarr, SonarrConnectionError, SonarrError from sonarr import Sonarr, SonarrConnectionError, SonarrError
from typing_extensions import Concatenate, ParamSpec
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -64,6 +67,9 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
), ),
) )
_T = TypeVar("_T", bound="SonarrSensor")
_P = ParamSpec("_P")
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
@ -82,14 +88,17 @@ async def async_setup_entry(
async_add_entities(entities, True) async_add_entities(entities, True)
def sonarr_exception_handler(func): def sonarr_exception_handler(
func: Callable[Concatenate[_T, _P], Awaitable[None]] # type: ignore[misc]
) -> Callable[Concatenate[_T, _P], Coroutine[Any, Any, None]]: # type: ignore[misc]
"""Decorate Sonarr calls to handle Sonarr exceptions. """Decorate Sonarr calls to handle Sonarr exceptions.
A decorator that wraps the passed in function, catches Sonarr errors, A decorator that wraps the passed in function, catches Sonarr errors,
and handles the availability of the entity. and handles the availability of the entity.
""" """
async def handler(self, *args, **kwargs): @wraps(func)
async def wrapper(self: _T, *args: _P.args, **kwargs: _P.kwargs) -> None:
try: try:
await func(self, *args, **kwargs) await func(self, *args, **kwargs)
self.last_update_success = True self.last_update_success = True
@ -102,12 +111,17 @@ def sonarr_exception_handler(func):
_LOGGER.error("Invalid response from API: %s", error) _LOGGER.error("Invalid response from API: %s", error)
self.last_update_success = False self.last_update_success = False
return handler return wrapper
class SonarrSensor(SonarrEntity, SensorEntity): class SonarrSensor(SonarrEntity, SensorEntity):
"""Implementation of the Sonarr sensor.""" """Implementation of the Sonarr sensor."""
data: dict[str, Any]
last_update_success: bool
upcoming_days: int
wanted_max_items: int
def __init__( def __init__(
self, self,
sonarr: Sonarr, sonarr: Sonarr,
@ -119,10 +133,10 @@ class SonarrSensor(SonarrEntity, SensorEntity):
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{entry_id}_{description.key}" self._attr_unique_id = f"{entry_id}_{description.key}"
self.data: dict[str, Any] = {} self.data = {}
self.last_update_success: bool = False self.last_update_success = True
self.upcoming_days: int = options[CONF_UPCOMING_DAYS] self.upcoming_days = options[CONF_UPCOMING_DAYS]
self.wanted_max_items: int = options[CONF_WANTED_MAX_ITEMS] self.wanted_max_items = options[CONF_WANTED_MAX_ITEMS]
super().__init__( super().__init__(
sonarr=sonarr, sonarr=sonarr,

View File

@ -68,30 +68,36 @@ async def test_sensors(
assert state assert state
assert state.attributes.get(ATTR_ICON) == "mdi:harddisk" assert state.attributes.get(ATTR_ICON) == "mdi:harddisk"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == DATA_GIGABYTES assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == DATA_GIGABYTES
assert state.attributes.get("C:\\") == "263.10/465.42GB (56.53%)"
assert state.state == "263.10" assert state.state == "263.10"
state = hass.states.get("sensor.sonarr_queue") state = hass.states.get("sensor.sonarr_queue")
assert state assert state
assert state.attributes.get(ATTR_ICON) == "mdi:download" assert state.attributes.get(ATTR_ICON) == "mdi:download"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Episodes" assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Episodes"
assert state.attributes.get("The Andy Griffith Show S01E01") == "100.00%"
assert state.state == "1" assert state.state == "1"
state = hass.states.get("sensor.sonarr_shows") state = hass.states.get("sensor.sonarr_shows")
assert state assert state
assert state.attributes.get(ATTR_ICON) == "mdi:television" assert state.attributes.get(ATTR_ICON) == "mdi:television"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Series" assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Series"
assert state.attributes.get("The Andy Griffith Show") == "0/0 Episodes"
assert state.state == "1" assert state.state == "1"
state = hass.states.get("sensor.sonarr_upcoming") state = hass.states.get("sensor.sonarr_upcoming")
assert state assert state
assert state.attributes.get(ATTR_ICON) == "mdi:television" assert state.attributes.get(ATTR_ICON) == "mdi:television"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Episodes" assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Episodes"
assert state.attributes.get("Bob's Burgers") == "S04E11"
assert state.state == "1" assert state.state == "1"
state = hass.states.get("sensor.sonarr_wanted") state = hass.states.get("sensor.sonarr_wanted")
assert state assert state
assert state.attributes.get(ATTR_ICON) == "mdi:television" assert state.attributes.get(ATTR_ICON) == "mdi:television"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Episodes" assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Episodes"
assert state.attributes.get("Bob's Burgers S04E11") == "2014-01-26"
assert state.attributes.get("The Andy Griffith Show S01E01") == "1960-10-03"
assert state.state == "2" assert state.state == "2"