mirror of
https://github.com/home-assistant/core.git
synced 2025-04-19 14:57:52 +00:00
Enable strict typing for generic_hygrostat (#107272)
This commit is contained in:
parent
265f587768
commit
5ae419367e
@ -177,6 +177,7 @@ homeassistant.components.fritzbox_callmonitor.*
|
||||
homeassistant.components.fronius.*
|
||||
homeassistant.components.frontend.*
|
||||
homeassistant.components.fully_kiosk.*
|
||||
homeassistant.components.generic_hygrostat.*
|
||||
homeassistant.components.geo_location.*
|
||||
homeassistant.components.geocaching.*
|
||||
homeassistant.components.gios.*
|
||||
|
@ -2,7 +2,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from homeassistant.components.humidifier import (
|
||||
ATTR_HUMIDITY,
|
||||
@ -27,7 +30,13 @@ from homeassistant.const import (
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.core import DOMAIN as HA_DOMAIN, HomeAssistant, callback
|
||||
from homeassistant.core import (
|
||||
DOMAIN as HA_DOMAIN,
|
||||
Event,
|
||||
HomeAssistant,
|
||||
State,
|
||||
callback,
|
||||
)
|
||||
from homeassistant.helpers import condition
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.event import (
|
||||
@ -72,22 +81,22 @@ async def async_setup_platform(
|
||||
"""Set up the generic hygrostat platform."""
|
||||
if discovery_info:
|
||||
config = discovery_info
|
||||
name = config[CONF_NAME]
|
||||
switch_entity_id = config[CONF_HUMIDIFIER]
|
||||
sensor_entity_id = config[CONF_SENSOR]
|
||||
min_humidity = config.get(CONF_MIN_HUMIDITY)
|
||||
max_humidity = config.get(CONF_MAX_HUMIDITY)
|
||||
target_humidity = config.get(CONF_TARGET_HUMIDITY)
|
||||
device_class = config.get(CONF_DEVICE_CLASS)
|
||||
min_cycle_duration = config.get(CONF_MIN_DUR)
|
||||
sensor_stale_duration = config.get(CONF_STALE_DURATION)
|
||||
dry_tolerance = config[CONF_DRY_TOLERANCE]
|
||||
wet_tolerance = config[CONF_WET_TOLERANCE]
|
||||
keep_alive = config.get(CONF_KEEP_ALIVE)
|
||||
initial_state = config.get(CONF_INITIAL_STATE)
|
||||
away_humidity = config.get(CONF_AWAY_HUMIDITY)
|
||||
away_fixed = config.get(CONF_AWAY_FIXED)
|
||||
unique_id = config.get(CONF_UNIQUE_ID)
|
||||
name: str = config[CONF_NAME]
|
||||
switch_entity_id: str = config[CONF_HUMIDIFIER]
|
||||
sensor_entity_id: str = config[CONF_SENSOR]
|
||||
min_humidity: int | None = config.get(CONF_MIN_HUMIDITY)
|
||||
max_humidity: int | None = config.get(CONF_MAX_HUMIDITY)
|
||||
target_humidity: int | None = config.get(CONF_TARGET_HUMIDITY)
|
||||
device_class: HumidifierDeviceClass | None = config.get(CONF_DEVICE_CLASS)
|
||||
min_cycle_duration: timedelta | None = config.get(CONF_MIN_DUR)
|
||||
sensor_stale_duration: timedelta | None = config.get(CONF_STALE_DURATION)
|
||||
dry_tolerance: float = config[CONF_DRY_TOLERANCE]
|
||||
wet_tolerance: float = config[CONF_WET_TOLERANCE]
|
||||
keep_alive: timedelta | None = config.get(CONF_KEEP_ALIVE)
|
||||
initial_state: bool | None = config.get(CONF_INITIAL_STATE)
|
||||
away_humidity: int | None = config.get(CONF_AWAY_HUMIDITY)
|
||||
away_fixed: bool | None = config.get(CONF_AWAY_FIXED)
|
||||
unique_id: str | None = config.get(CONF_UNIQUE_ID)
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
@ -120,28 +129,28 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
switch_entity_id,
|
||||
sensor_entity_id,
|
||||
min_humidity,
|
||||
max_humidity,
|
||||
target_humidity,
|
||||
device_class,
|
||||
min_cycle_duration,
|
||||
dry_tolerance,
|
||||
wet_tolerance,
|
||||
keep_alive,
|
||||
initial_state,
|
||||
away_humidity,
|
||||
away_fixed,
|
||||
sensor_stale_duration,
|
||||
unique_id,
|
||||
):
|
||||
name: str,
|
||||
switch_entity_id: str,
|
||||
sensor_entity_id: str,
|
||||
min_humidity: int | None,
|
||||
max_humidity: int | None,
|
||||
target_humidity: int | None,
|
||||
device_class: HumidifierDeviceClass | None,
|
||||
min_cycle_duration: timedelta | None,
|
||||
dry_tolerance: float,
|
||||
wet_tolerance: float,
|
||||
keep_alive: timedelta | None,
|
||||
initial_state: bool | None,
|
||||
away_humidity: int | None,
|
||||
away_fixed: bool | None,
|
||||
sensor_stale_duration: timedelta | None,
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the hygrostat."""
|
||||
self._name = name
|
||||
self._switch_entity_id = switch_entity_id
|
||||
self._sensor_entity_id = sensor_entity_id
|
||||
self._device_class = device_class
|
||||
self._device_class = device_class or HumidifierDeviceClass.HUMIDIFIER
|
||||
self._min_cycle_duration = min_cycle_duration
|
||||
self._dry_tolerance = dry_tolerance
|
||||
self._wet_tolerance = wet_tolerance
|
||||
@ -149,7 +158,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
self._state = initial_state
|
||||
self._saved_target_humidity = away_humidity or target_humidity
|
||||
self._active = False
|
||||
self._cur_humidity = None
|
||||
self._cur_humidity: float | None = None
|
||||
self._humidity_lock = asyncio.Lock()
|
||||
self._min_humidity = min_humidity
|
||||
self._max_humidity = max_humidity
|
||||
@ -159,14 +168,12 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
self._away_humidity = away_humidity
|
||||
self._away_fixed = away_fixed
|
||||
self._sensor_stale_duration = sensor_stale_duration
|
||||
self._remove_stale_tracking = None
|
||||
self._remove_stale_tracking: Callable[[], None] | None = None
|
||||
self._is_away = False
|
||||
if not self._device_class:
|
||||
self._device_class = HumidifierDeviceClass.HUMIDIFIER
|
||||
self._attr_action = HumidifierAction.IDLE
|
||||
self._attr_unique_id = unique_id
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Run when entity about to be added."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
@ -185,7 +192,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
)
|
||||
)
|
||||
|
||||
async def _async_startup(event):
|
||||
async def _async_startup(event: Event | None) -> None:
|
||||
"""Init on startup."""
|
||||
sensor_state = self.hass.states.get(self._sensor_entity_id)
|
||||
if sensor_state is None or sensor_state.state in (
|
||||
@ -234,39 +241,39 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
return await super().async_will_remove_from_hass()
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return self._active
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
def extra_state_attributes(self) -> dict[str, Any] | None:
|
||||
"""Return the optional state attributes."""
|
||||
if self._saved_target_humidity:
|
||||
return {ATTR_SAVED_HUMIDITY: self._saved_target_humidity}
|
||||
return None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
def name(self) -> str:
|
||||
"""Return the name of the hygrostat."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if the hygrostat is on."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def current_humidity(self):
|
||||
def current_humidity(self) -> int | None:
|
||||
"""Return the measured humidity."""
|
||||
return self._cur_humidity
|
||||
return int(self._cur_humidity) if self._cur_humidity is not None else None
|
||||
|
||||
@property
|
||||
def target_humidity(self):
|
||||
def target_humidity(self) -> int | None:
|
||||
"""Return the humidity we try to reach."""
|
||||
return self._target_humidity
|
||||
|
||||
@property
|
||||
def mode(self):
|
||||
def mode(self) -> str | None:
|
||||
"""Return the current mode."""
|
||||
if self._away_humidity is None:
|
||||
return None
|
||||
@ -275,18 +282,18 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
return MODE_NORMAL
|
||||
|
||||
@property
|
||||
def available_modes(self):
|
||||
def available_modes(self) -> list[str] | None:
|
||||
"""Return a list of available modes."""
|
||||
if self._away_humidity:
|
||||
return [MODE_NORMAL, MODE_AWAY]
|
||||
return None
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
def device_class(self) -> HumidifierDeviceClass:
|
||||
"""Return the device class of the humidifier."""
|
||||
return self._device_class
|
||||
|
||||
async def async_turn_on(self, **kwargs):
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn hygrostat on."""
|
||||
if not self._active:
|
||||
return
|
||||
@ -294,7 +301,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
await self._async_operate(force=True)
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_turn_off(self, **kwargs):
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn hygrostat off."""
|
||||
if not self._active:
|
||||
return
|
||||
@ -306,7 +313,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
async def async_set_humidity(self, humidity: int) -> None:
|
||||
"""Set new target humidity."""
|
||||
if humidity is None:
|
||||
return
|
||||
return # type: ignore[unreachable]
|
||||
|
||||
if self._is_away and self._away_fixed:
|
||||
self._saved_target_humidity = humidity
|
||||
@ -318,7 +325,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def min_humidity(self):
|
||||
def min_humidity(self) -> int:
|
||||
"""Return the minimum humidity."""
|
||||
if self._min_humidity:
|
||||
return self._min_humidity
|
||||
@ -327,7 +334,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
return super().min_humidity
|
||||
|
||||
@property
|
||||
def max_humidity(self):
|
||||
def max_humidity(self) -> int:
|
||||
"""Return the maximum humidity."""
|
||||
if self._max_humidity:
|
||||
return self._max_humidity
|
||||
@ -335,7 +342,9 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
# Get default humidity from super class
|
||||
return super().max_humidity
|
||||
|
||||
async def _async_sensor_changed(self, entity_id, old_state, new_state):
|
||||
async def _async_sensor_changed(
|
||||
self, entity_id: str, old_state: State | None, new_state: State | None
|
||||
) -> None:
|
||||
"""Handle ambient humidity changes."""
|
||||
if new_state is None:
|
||||
return
|
||||
@ -353,18 +362,21 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
await self._async_operate()
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def _async_sensor_not_responding(self, now=None):
|
||||
async def _async_sensor_not_responding(self, now: datetime | None = None) -> None:
|
||||
"""Handle sensor stale event."""
|
||||
|
||||
state = self.hass.states.get(self._sensor_entity_id)
|
||||
_LOGGER.debug(
|
||||
"Sensor has not been updated for %s",
|
||||
now - self.hass.states.get(self._sensor_entity_id).last_updated,
|
||||
now - state.last_updated if now and state else "---",
|
||||
)
|
||||
_LOGGER.warning("Sensor is stalled, call the emergency stop")
|
||||
await self._async_update_humidity("Stalled")
|
||||
|
||||
@callback
|
||||
def _async_switch_changed(self, entity_id, old_state, new_state):
|
||||
def _async_switch_changed(
|
||||
self, entity_id: str, old_state: State | None, new_state: State | None
|
||||
) -> None:
|
||||
"""Handle humidifier switch state changes."""
|
||||
if new_state is None:
|
||||
return
|
||||
@ -379,7 +391,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
async def _async_update_humidity(self, humidity):
|
||||
async def _async_update_humidity(self, humidity: str) -> None:
|
||||
"""Update hygrostat with latest state from sensor."""
|
||||
try:
|
||||
self._cur_humidity = float(humidity)
|
||||
@ -390,7 +402,9 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
if self._is_device_active:
|
||||
await self._async_device_turn_off()
|
||||
|
||||
async def _async_operate(self, time=None, force=False):
|
||||
async def _async_operate(
|
||||
self, time: datetime | None = None, force: bool = False
|
||||
) -> None:
|
||||
"""Check if we need to turn humidifying on or off."""
|
||||
async with self._humidity_lock:
|
||||
if not self._active and None not in (
|
||||
@ -432,12 +446,15 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
|
||||
if force:
|
||||
# Ignore the tolerance when switched on manually
|
||||
dry_tolerance = 0
|
||||
wet_tolerance = 0
|
||||
dry_tolerance: float = 0
|
||||
wet_tolerance: float = 0
|
||||
else:
|
||||
dry_tolerance = self._dry_tolerance
|
||||
wet_tolerance = self._wet_tolerance
|
||||
|
||||
if TYPE_CHECKING:
|
||||
assert self._target_humidity is not None
|
||||
assert self._cur_humidity is not None
|
||||
too_dry = self._target_humidity - self._cur_humidity >= dry_tolerance
|
||||
too_wet = self._cur_humidity - self._target_humidity >= wet_tolerance
|
||||
if self._is_device_active:
|
||||
@ -461,16 +478,16 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
||||
await self._async_device_turn_off()
|
||||
|
||||
@property
|
||||
def _is_device_active(self):
|
||||
def _is_device_active(self) -> bool:
|
||||
"""If the toggleable device is currently active."""
|
||||
return self.hass.states.is_state(self._switch_entity_id, STATE_ON)
|
||||
|
||||
async def _async_device_turn_on(self):
|
||||
async def _async_device_turn_on(self) -> None:
|
||||
"""Turn humidifier toggleable device on."""
|
||||
data = {ATTR_ENTITY_ID: self._switch_entity_id}
|
||||
await self.hass.services.async_call(HA_DOMAIN, SERVICE_TURN_ON, data)
|
||||
|
||||
async def _async_device_turn_off(self):
|
||||
async def _async_device_turn_off(self) -> None:
|
||||
"""Turn humidifier toggleable device off."""
|
||||
data = {ATTR_ENTITY_ID: self._switch_entity_id}
|
||||
await self.hass.services.async_call(HA_DOMAIN, SERVICE_TURN_OFF, data)
|
||||
|
10
mypy.ini
10
mypy.ini
@ -1531,6 +1531,16 @@ disallow_untyped_defs = true
|
||||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
|
||||
[mypy-homeassistant.components.generic_hygrostat.*]
|
||||
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.geo_location.*]
|
||||
check_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
|
Loading…
x
Reference in New Issue
Block a user