Enable strict typing for timer (#107915)

This commit is contained in:
Marc Mueller 2024-01-14 09:40:14 +01:00 committed by GitHub
parent ec708811d0
commit 01204356fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 20 deletions

View File

@ -407,6 +407,7 @@ homeassistant.components.tile.*
homeassistant.components.tilt_ble.* homeassistant.components.tilt_ble.*
homeassistant.components.time.* homeassistant.components.time.*
homeassistant.components.time_date.* homeassistant.components.time_date.*
homeassistant.components.timer.*
homeassistant.components.tod.* homeassistant.components.tod.*
homeassistant.components.todo.* homeassistant.components.todo.*
homeassistant.components.tolo.* homeassistant.components.tolo.*

View File

@ -4,7 +4,7 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from datetime import datetime, timedelta from datetime import datetime, timedelta
import logging import logging
from typing import Self from typing import Any, Self, TypeVar
import voluptuous as vol import voluptuous as vol
@ -28,6 +28,7 @@ from homeassistant.helpers.storage import Store
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
_T = TypeVar("_T")
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = "timer" DOMAIN = "timer"
@ -73,14 +74,14 @@ STORAGE_FIELDS = {
} }
def _format_timedelta(delta: timedelta): def _format_timedelta(delta: timedelta) -> str:
total_seconds = delta.total_seconds() total_seconds = delta.total_seconds()
hours, remainder = divmod(total_seconds, 3600) hours, remainder = divmod(total_seconds, 3600)
minutes, seconds = divmod(remainder, 60) minutes, seconds = divmod(remainder, 60)
return f"{int(hours)}:{int(minutes):02}:{int(seconds):02}" return f"{int(hours)}:{int(minutes):02}:{int(seconds):02}"
def _none_to_empty_dict(value): def _none_to_empty_dict(value: _T | None) -> _T | dict[Any, Any]:
if value is None: if value is None:
return {} return {}
return value return value
@ -185,7 +186,7 @@ class TimerStorageCollection(collection.DictStorageCollection):
@callback @callback
def _get_suggested_id(self, info: dict) -> str: def _get_suggested_id(self, info: dict) -> str:
"""Suggest an ID based on the config.""" """Suggest an ID based on the config."""
return info[CONF_NAME] return info[CONF_NAME] # type: ignore[no-any-return]
async def _update_data(self, item: dict, update_data: dict) -> dict: async def _update_data(self, item: dict, update_data: dict) -> dict:
"""Return a new updated data object.""" """Return a new updated data object."""
@ -193,7 +194,7 @@ class TimerStorageCollection(collection.DictStorageCollection):
# make duration JSON serializeable # make duration JSON serializeable
if CONF_DURATION in update_data: if CONF_DURATION in update_data:
data[CONF_DURATION] = _format_timedelta(data[CONF_DURATION]) data[CONF_DURATION] = _format_timedelta(data[CONF_DURATION])
return data return data # type: ignore[no-any-return]
class Timer(collection.CollectionEntity, RestoreEntity): class Timer(collection.CollectionEntity, RestoreEntity):
@ -231,24 +232,24 @@ class Timer(collection.CollectionEntity, RestoreEntity):
return timer return timer
@property @property
def name(self): def name(self) -> str | None:
"""Return name of the timer.""" """Return name of the timer."""
return self._config.get(CONF_NAME) return self._config.get(CONF_NAME)
@property @property
def icon(self): def icon(self) -> str | None:
"""Return the icon to be used for this entity.""" """Return the icon to be used for this entity."""
return self._config.get(CONF_ICON) return self._config.get(CONF_ICON)
@property @property
def state(self): def state(self) -> str:
"""Return the current value of the timer.""" """Return the current value of the timer."""
return self._state return self._state
@property @property
def extra_state_attributes(self): def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes.""" """Return the state attributes."""
attrs = { attrs: dict[str, Any] = {
ATTR_DURATION: _format_timedelta(self._running_duration), ATTR_DURATION: _format_timedelta(self._running_duration),
ATTR_EDITABLE: self.editable, ATTR_EDITABLE: self.editable,
} }
@ -264,9 +265,9 @@ class Timer(collection.CollectionEntity, RestoreEntity):
@property @property
def unique_id(self) -> str | None: def unique_id(self) -> str | None:
"""Return unique id for the entity.""" """Return unique id for the entity."""
return self._config[CONF_ID] return self._config[CONF_ID] # type: ignore[no-any-return]
async def async_added_to_hass(self): async def async_added_to_hass(self) -> None:
"""Call when entity is about to be added to Home Assistant.""" """Call when entity is about to be added to Home Assistant."""
# If we don't need to restore a previous state or no previous state exists, # If we don't need to restore a previous state or no previous state exists,
# start at idle # start at idle
@ -302,7 +303,7 @@ class Timer(collection.CollectionEntity, RestoreEntity):
self.async_finish() self.async_finish()
@callback @callback
def async_start(self, duration: timedelta | None = None): def async_start(self, duration: timedelta | None = None) -> None:
"""Start a timer.""" """Start a timer."""
if self._listener: if self._listener:
self._listener() self._listener()
@ -356,9 +357,9 @@ class Timer(collection.CollectionEntity, RestoreEntity):
self.async_write_ha_state() self.async_write_ha_state()
@callback @callback
def async_pause(self): def async_pause(self) -> None:
"""Pause a timer.""" """Pause a timer."""
if self._listener is None: if self._listener is None or self._end is None:
return return
self._listener() self._listener()
@ -370,7 +371,7 @@ class Timer(collection.CollectionEntity, RestoreEntity):
self.async_write_ha_state() self.async_write_ha_state()
@callback @callback
def async_cancel(self): def async_cancel(self) -> None:
"""Cancel a timer.""" """Cancel a timer."""
if self._listener: if self._listener:
self._listener() self._listener()
@ -385,9 +386,9 @@ class Timer(collection.CollectionEntity, RestoreEntity):
self.async_write_ha_state() self.async_write_ha_state()
@callback @callback
def async_finish(self): def async_finish(self) -> None:
"""Reset and updates the states, fire finished event.""" """Reset and updates the states, fire finished event."""
if self._state != STATUS_ACTIVE: if self._state != STATUS_ACTIVE or self._end is None:
return return
if self._listener: if self._listener:
@ -405,9 +406,9 @@ class Timer(collection.CollectionEntity, RestoreEntity):
self.async_write_ha_state() self.async_write_ha_state()
@callback @callback
def _async_finished(self, time): def _async_finished(self, time: datetime) -> None:
"""Reset and updates the states, fire finished event.""" """Reset and updates the states, fire finished event."""
if self._state != STATUS_ACTIVE: if self._state != STATUS_ACTIVE or self._end is None:
return return
self._listener = None self._listener = None

View File

@ -3832,6 +3832,16 @@ disallow_untyped_defs = true
warn_return_any = true warn_return_any = true
warn_unreachable = true warn_unreachable = true
[mypy-homeassistant.components.timer.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.tod.*] [mypy-homeassistant.components.tod.*]
check_untyped_defs = true check_untyped_defs = true
disallow_incomplete_defs = true disallow_incomplete_defs = true