Enable strict typing for generic_thermostat (#108024)

This commit is contained in:
Marc Mueller 2024-01-15 09:19:50 +01:00 committed by GitHub
parent 9bca09a513
commit 84038fb119
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 50 deletions

View File

@ -183,6 +183,7 @@ homeassistant.components.fronius.*
homeassistant.components.frontend.*
homeassistant.components.fully_kiosk.*
homeassistant.components.generic_hygrostat.*
homeassistant.components.generic_thermostat.*
homeassistant.components.geo_location.*
homeassistant.components.geocaching.*
homeassistant.components.gios.*

View File

@ -2,6 +2,7 @@
from __future__ import annotations
import asyncio
from datetime import datetime, timedelta
import logging
import math
from typing import Any
@ -36,10 +37,12 @@ from homeassistant.const import (
STATE_ON,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
UnitOfTemperature,
)
from homeassistant.core import (
DOMAIN as HA_DOMAIN,
CoreState,
Event,
HomeAssistant,
State,
callback,
@ -126,25 +129,25 @@ async def async_setup_platform(
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
name = config.get(CONF_NAME)
heater_entity_id = config.get(CONF_HEATER)
sensor_entity_id = config.get(CONF_SENSOR)
min_temp = config.get(CONF_MIN_TEMP)
max_temp = config.get(CONF_MAX_TEMP)
target_temp = config.get(CONF_TARGET_TEMP)
ac_mode = config.get(CONF_AC_MODE)
min_cycle_duration = config.get(CONF_MIN_DUR)
cold_tolerance = config.get(CONF_COLD_TOLERANCE)
hot_tolerance = config.get(CONF_HOT_TOLERANCE)
keep_alive = config.get(CONF_KEEP_ALIVE)
initial_hvac_mode = config.get(CONF_INITIAL_HVAC_MODE)
presets = {
name: str = config[CONF_NAME]
heater_entity_id: str = config[CONF_HEATER]
sensor_entity_id: str = config[CONF_SENSOR]
min_temp: float | None = config.get(CONF_MIN_TEMP)
max_temp: float | None = config.get(CONF_MAX_TEMP)
target_temp: float | None = config.get(CONF_TARGET_TEMP)
ac_mode: bool | None = config.get(CONF_AC_MODE)
min_cycle_duration: timedelta | None = config.get(CONF_MIN_DUR)
cold_tolerance: float = config[CONF_COLD_TOLERANCE]
hot_tolerance: float = config[CONF_HOT_TOLERANCE]
keep_alive: timedelta | None = config.get(CONF_KEEP_ALIVE)
initial_hvac_mode: HVACMode | None = config.get(CONF_INITIAL_HVAC_MODE)
presets: dict[str, float] = {
key: config[value] for key, value in CONF_PRESETS.items() if value in config
}
precision = config.get(CONF_PRECISION)
target_temperature_step = config.get(CONF_TEMP_STEP)
precision: float | None = config.get(CONF_PRECISION)
target_temperature_step: float | None = config.get(CONF_TEMP_STEP)
unit = hass.config.units.temperature_unit
unique_id = config.get(CONF_UNIQUE_ID)
unique_id: str | None = config.get(CONF_UNIQUE_ID)
async_add_entities(
[
@ -178,24 +181,24 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
def __init__(
self,
name,
heater_entity_id,
sensor_entity_id,
min_temp,
max_temp,
target_temp,
ac_mode,
min_cycle_duration,
cold_tolerance,
hot_tolerance,
keep_alive,
initial_hvac_mode,
presets,
precision,
target_temperature_step,
unit,
unique_id,
):
name: str,
heater_entity_id: str,
sensor_entity_id: str,
min_temp: float | None,
max_temp: float | None,
target_temp: float | None,
ac_mode: bool | None,
min_cycle_duration: timedelta | None,
cold_tolerance: float,
hot_tolerance: float,
keep_alive: timedelta | None,
initial_hvac_mode: HVACMode | None,
presets: dict[str, float],
precision: float | None,
target_temperature_step: float | None,
unit: UnitOfTemperature,
unique_id: str | None,
) -> None:
"""Initialize the thermostat."""
self._attr_name = name
self.heater_entity_id = heater_entity_id
@ -214,7 +217,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
else:
self._attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF]
self._active = False
self._cur_temp = None
self._cur_temp: float | None = None
self._temp_lock = asyncio.Lock()
self._min_temp = min_temp
self._max_temp = max_temp
@ -254,7 +257,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
)
@callback
def _async_startup(*_):
def _async_startup(_: Event | None = None) -> None:
"""Init on startup."""
sensor_state = self.hass.states.get(self.sensor_entity_id)
if sensor_state and sensor_state.state not in (
@ -297,7 +300,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
):
self._attr_preset_mode = old_state.attributes.get(ATTR_PRESET_MODE)
if not self._hvac_mode and old_state.state:
self._hvac_mode = old_state.state
self._hvac_mode = HVACMode(old_state.state)
else:
# No previous state, try and restore defaults
@ -315,14 +318,14 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
self._hvac_mode = HVACMode.OFF
@property
def precision(self):
def precision(self) -> float:
"""Return the precision of the system."""
if self._temp_precision is not None:
return self._temp_precision
return super().precision
@property
def target_temperature_step(self):
def target_temperature_step(self) -> float:
"""Return the supported step of target temperature."""
if self._temp_target_temperature_step is not None:
return self._temp_target_temperature_step
@ -330,17 +333,17 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
return self.precision
@property
def current_temperature(self):
def current_temperature(self) -> float | None:
"""Return the sensor temperature."""
return self._cur_temp
@property
def hvac_mode(self):
def hvac_mode(self) -> HVACMode | None:
"""Return current operation."""
return self._hvac_mode
@property
def hvac_action(self):
def hvac_action(self) -> HVACAction:
"""Return the current running hvac operation if supported.
Need to be one of CURRENT_HVAC_*.
@ -354,7 +357,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
return HVACAction.HEATING
@property
def target_temperature(self):
def target_temperature(self) -> float | None:
"""Return the temperature we try to reach."""
return self._target_temp
@ -385,7 +388,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
self.async_write_ha_state()
@property
def min_temp(self):
def min_temp(self) -> float:
"""Return the minimum temperature."""
if self._min_temp is not None:
return self._min_temp
@ -394,7 +397,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
return super().min_temp
@property
def max_temp(self):
def max_temp(self) -> float:
"""Return the maximum temperature."""
if self._max_temp is not None:
return self._max_temp
@ -414,7 +417,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
await self._async_control_heating()
self.async_write_ha_state()
async def _check_switch_initial_state(self):
async def _check_switch_initial_state(self) -> None:
"""Prevent the device from keep running if HVACMode.OFF."""
if self._hvac_mode == HVACMode.OFF and self._is_device_active:
_LOGGER.warning(
@ -448,7 +451,9 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
except ValueError as ex:
_LOGGER.error("Unable to update from sensor: %s", ex)
async def _async_control_heating(self, time=None, force=False):
async def _async_control_heating(
self, time: datetime | None = None, force: bool = False
) -> None:
"""Check if we need to turn heating on or off."""
async with self._temp_lock:
if not self._active and None not in (
@ -490,6 +495,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
if not long_enough:
return
assert self._cur_temp is not None and self._target_temp is not None
too_cold = self._target_temp >= self._cur_temp + self._cold_tolerance
too_hot = self._cur_temp >= self._target_temp + self._hot_tolerance
if self._is_device_active:
@ -514,21 +520,21 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
await self._async_heater_turn_off()
@property
def _is_device_active(self):
def _is_device_active(self) -> bool | None:
"""If the toggleable device is currently active."""
if not self.hass.states.get(self.heater_entity_id):
return None
return self.hass.states.is_state(self.heater_entity_id, STATE_ON)
async def _async_heater_turn_on(self):
async def _async_heater_turn_on(self) -> None:
"""Turn heater toggleable device on."""
data = {ATTR_ENTITY_ID: self.heater_entity_id}
await self.hass.services.async_call(
HA_DOMAIN, SERVICE_TURN_ON, data, context=self._context
)
async def _async_heater_turn_off(self):
async def _async_heater_turn_off(self) -> None:
"""Turn heater toggleable device off."""
data = {ATTR_ENTITY_ID: self.heater_entity_id}
await self.hass.services.async_call(

View File

@ -1591,6 +1591,16 @@ disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.generic_thermostat.*]
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