diff --git a/.strict-typing b/.strict-typing index 45f060c6690..a1353afb657 100644 --- a/.strict-typing +++ b/.strict-typing @@ -175,6 +175,7 @@ homeassistant.components.jewish_calendar.* homeassistant.components.kaleidescape.* homeassistant.components.knx.* homeassistant.components.kraken.* +homeassistant.components.lacrosse.* homeassistant.components.lacrosse_view.* homeassistant.components.lametric.* homeassistant.components.laundrify.* diff --git a/homeassistant/components/lacrosse/sensor.py b/homeassistant/components/lacrosse/sensor.py index a9edea22b0d..fb2c60b32c9 100644 --- a/homeassistant/components/lacrosse/sensor.py +++ b/homeassistant/components/lacrosse/sensor.py @@ -1,8 +1,9 @@ """Support for LaCrosse sensor components.""" from __future__ import annotations -from datetime import timedelta +from datetime import datetime, timedelta import logging +from typing import Any import pylacrosse from serial import SerialException @@ -25,7 +26,7 @@ from homeassistant.const import ( PERCENTAGE, UnitOfTemperature, ) -from homeassistant.core import HomeAssistant, callback +from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import async_generate_entity_id from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -44,7 +45,7 @@ CONF_TOGGLE_INTERVAL = "toggle_interval" CONF_TOGGLE_MASK = "toggle_mask" DEFAULT_DEVICE = "/dev/ttyUSB0" -DEFAULT_BAUD = "57600" +DEFAULT_BAUD = 57600 DEFAULT_EXPIRE_AFTER = 300 TYPES = ["battery", "humidity", "temperature"] @@ -61,7 +62,7 @@ SENSOR_SCHEMA = vol.Schema( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_SENSORS): cv.schema_with_slug_keys(SENSOR_SCHEMA), - vol.Optional(CONF_BAUD, default=DEFAULT_BAUD): cv.string, + vol.Optional(CONF_BAUD, default=DEFAULT_BAUD): cv.positive_int, vol.Optional(CONF_DATARATE): cv.positive_int, vol.Optional(CONF_DEVICE, default=DEFAULT_DEVICE): cv.string, vol.Optional(CONF_FREQUENCY): cv.positive_int, @@ -79,9 +80,9 @@ def setup_platform( discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up the LaCrosse sensors.""" - usb_device = config[CONF_DEVICE] - baud = int(config[CONF_BAUD]) - expire_after = config.get(CONF_EXPIRE_AFTER) + usb_device: str = config[CONF_DEVICE] + baud: int = config[CONF_BAUD] + expire_after: int | None = config.get(CONF_EXPIRE_AFTER) _LOGGER.debug("%s %s", usb_device, baud) @@ -92,7 +93,7 @@ def setup_platform( _LOGGER.warning("Unable to open serial port: %s", exc) return - hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, lambda event: lacrosse.close()) + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, lambda event: lacrosse.close()) # type: ignore[no-any-return] if CONF_JEELINK_LED in config: lacrosse.led_mode_state(config.get(CONF_JEELINK_LED)) @@ -107,13 +108,13 @@ def setup_platform( lacrosse.start_scan() - sensors = [] + sensors: list[LaCrosseSensor] = [] for device, device_config in config[CONF_SENSORS].items(): _LOGGER.debug("%s %s", device, device_config) - typ = device_config.get(CONF_TYPE) + typ: str = device_config[CONF_TYPE] sensor_class = TYPE_CLASSES[typ] - name = device_config.get(CONF_NAME, device) + name: str = device_config.get(CONF_NAME, device) sensors.append( sensor_class(hass, lacrosse, device, name, expire_after, device_config) @@ -125,21 +126,28 @@ def setup_platform( class LaCrosseSensor(SensorEntity): """Implementation of a Lacrosse sensor.""" - _temperature = None - _humidity = None - _low_battery = None - _new_battery = None + _temperature: float | None = None + _humidity: int | None = None + _low_battery: bool | None = None + _new_battery: bool | None = None - def __init__(self, hass, lacrosse, device_id, name, expire_after, config): + def __init__( + self, + hass: HomeAssistant, + lacrosse: pylacrosse.LaCrosse, + device_id: str, + name: str, + expire_after: int | None, + config: ConfigType, + ) -> None: """Initialize the sensor.""" self.hass = hass self.entity_id = async_generate_entity_id( ENTITY_ID_FORMAT, device_id, hass=hass ) self._config = config - self._value = None self._expire_after = expire_after - self._expiration_trigger = None + self._expiration_trigger: CALLBACK_TYPE | None = None self._attr_name = name lacrosse.register_callback( @@ -147,14 +155,16 @@ class LaCrosseSensor(SensorEntity): ) @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> dict[str, Any]: """Return the state attributes.""" return { "low_battery": self._low_battery, "new_battery": self._new_battery, } - def _callback_lacrosse(self, lacrosse_sensor, user_data): + def _callback_lacrosse( + self, lacrosse_sensor: pylacrosse.LaCrosseSensor, user_data: None + ) -> None: """Handle a function that is called from pylacrosse with new values.""" if self._expire_after is not None and self._expire_after > 0: # Reset old trigger @@ -175,10 +185,9 @@ class LaCrosseSensor(SensorEntity): self._new_battery = lacrosse_sensor.new_battery @callback - def value_is_expired(self, *_): + def value_is_expired(self, *_: datetime) -> None: """Triggered when value is expired.""" self._expiration_trigger = None - self._value = None self.async_write_ha_state() @@ -190,7 +199,7 @@ class LaCrosseTemperature(LaCrosseSensor): _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS @property - def native_value(self): + def native_value(self) -> float | None: """Return the state of the sensor.""" return self._temperature @@ -203,7 +212,7 @@ class LaCrosseHumidity(LaCrosseSensor): _attr_icon = "mdi:water-percent" @property - def native_value(self): + def native_value(self) -> int | None: """Return the state of the sensor.""" return self._humidity @@ -212,7 +221,7 @@ class LaCrosseBattery(LaCrosseSensor): """Implementation of a Lacrosse battery sensor.""" @property - def native_value(self): + def native_value(self) -> str | None: """Return the state of the sensor.""" if self._low_battery is None: return None @@ -221,7 +230,7 @@ class LaCrosseBattery(LaCrosseSensor): return "ok" @property - def icon(self): + def icon(self) -> str: """Icon to use in the frontend.""" if self._low_battery is None: return "mdi:battery-unknown" @@ -230,7 +239,7 @@ class LaCrosseBattery(LaCrosseSensor): return "mdi:battery" -TYPE_CLASSES = { +TYPE_CLASSES: dict[str, type[LaCrosseSensor]] = { "temperature": LaCrosseTemperature, "humidity": LaCrosseHumidity, "battery": LaCrosseBattery, diff --git a/mypy.ini b/mypy.ini index e9cfe18f9ce..9dee493bf28 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1504,6 +1504,16 @@ disallow_untyped_defs = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.lacrosse.*] +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.lacrosse_view.*] check_untyped_defs = true disallow_incomplete_defs = true