From bdf4c61a052a2e2b970b95e759f4c3e3e04737ff Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Wed, 29 Nov 2023 21:41:32 +0100 Subject: [PATCH] Add faa_delays to strict typing (#104720) --- .strict-typing | 1 + .../components/faa_delays/binary_sensor.py | 56 +++++++++++-------- .../components/faa_delays/config_flow.py | 6 +- .../components/faa_delays/coordinator.py | 8 +-- mypy.ini | 10 ++++ 5 files changed, 54 insertions(+), 27 deletions(-) diff --git a/.strict-typing b/.strict-typing index 3c18a1988f3..2c8717596c6 100644 --- a/.strict-typing +++ b/.strict-typing @@ -120,6 +120,7 @@ homeassistant.components.energy.* homeassistant.components.esphome.* homeassistant.components.event.* homeassistant.components.evil_genius_labs.* +homeassistant.components.faa_delays.* homeassistant.components.fan.* homeassistant.components.fastdotcom.* homeassistant.components.feedreader.* diff --git a/homeassistant/components/faa_delays/binary_sensor.py b/homeassistant/components/faa_delays/binary_sensor.py index 5cbb206f223..5a209a41de1 100644 --- a/homeassistant/components/faa_delays/binary_sensor.py +++ b/homeassistant/components/faa_delays/binary_sensor.py @@ -1,8 +1,12 @@ """Platform for FAA Delays sensor component.""" from __future__ import annotations +from collections.abc import Callable, Mapping +from dataclasses import dataclass from typing import Any +from faadelays import Airport + from homeassistant.components.binary_sensor import ( BinarySensorEntity, BinarySensorEntityDescription, @@ -12,33 +16,47 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity +from . import FAADataUpdateCoordinator from .const import DOMAIN -FAA_BINARY_SENSORS: tuple[BinarySensorEntityDescription, ...] = ( - BinarySensorEntityDescription( + +@dataclass(kw_only=True) +class FaaDelaysBinarySensorEntityDescription(BinarySensorEntityDescription): + """Mixin for required keys.""" + + is_on_fn: Callable[[Airport], bool | None] + + +FAA_BINARY_SENSORS: tuple[FaaDelaysBinarySensorEntityDescription, ...] = ( + FaaDelaysBinarySensorEntityDescription( key="GROUND_DELAY", name="Ground Delay", icon="mdi:airport", + is_on_fn=lambda airport: airport.ground_delay.status, ), - BinarySensorEntityDescription( + FaaDelaysBinarySensorEntityDescription( key="GROUND_STOP", name="Ground Stop", icon="mdi:airport", + is_on_fn=lambda airport: airport.ground_stop.status, ), - BinarySensorEntityDescription( + FaaDelaysBinarySensorEntityDescription( key="DEPART_DELAY", name="Departure Delay", icon="mdi:airplane-takeoff", + is_on_fn=lambda airport: airport.depart_delay.status, ), - BinarySensorEntityDescription( + FaaDelaysBinarySensorEntityDescription( key="ARRIVE_DELAY", name="Arrival Delay", icon="mdi:airplane-landing", + is_on_fn=lambda airport: airport.arrive_delay.status, ), - BinarySensorEntityDescription( + FaaDelaysBinarySensorEntityDescription( key="CLOSURE", name="Closure", icon="mdi:airplane:off", + is_on_fn=lambda airport: airport.closure.status, ), ) @@ -57,11 +75,16 @@ async def async_setup_entry( async_add_entities(entities) -class FAABinarySensor(CoordinatorEntity, BinarySensorEntity): +class FAABinarySensor(CoordinatorEntity[FAADataUpdateCoordinator], BinarySensorEntity): """Define a binary sensor for FAA Delays.""" + entity_description: FaaDelaysBinarySensorEntityDescription + def __init__( - self, coordinator, entry_id, description: BinarySensorEntityDescription + self, + coordinator: FAADataUpdateCoordinator, + entry_id: str, + description: FaaDelaysBinarySensorEntityDescription, ) -> None: """Initialize the sensor.""" super().__init__(coordinator) @@ -75,23 +98,12 @@ class FAABinarySensor(CoordinatorEntity, BinarySensorEntity): self._attr_unique_id = f"{_id}_{description.key}" @property - def is_on(self): + def is_on(self) -> bool | None: """Return the status of the sensor.""" - sensor_type = self.entity_description.key - if sensor_type == "GROUND_DELAY": - return self.coordinator.data.ground_delay.status - if sensor_type == "GROUND_STOP": - return self.coordinator.data.ground_stop.status - if sensor_type == "DEPART_DELAY": - return self.coordinator.data.depart_delay.status - if sensor_type == "ARRIVE_DELAY": - return self.coordinator.data.arrive_delay.status - if sensor_type == "CLOSURE": - return self.coordinator.data.closure.status - return None + return self.entity_description.is_on_fn(self.coordinator.data) @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> Mapping[str, Any]: """Return attributes for sensor.""" sensor_type = self.entity_description.key if sensor_type == "GROUND_DELAY": diff --git a/homeassistant/components/faa_delays/config_flow.py b/homeassistant/components/faa_delays/config_flow.py index b2f7f69dd49..2f91ce9f797 100644 --- a/homeassistant/components/faa_delays/config_flow.py +++ b/homeassistant/components/faa_delays/config_flow.py @@ -1,5 +1,6 @@ """Config flow for FAA Delays integration.""" import logging +from typing import Any from aiohttp import ClientConnectionError import faadelays @@ -7,6 +8,7 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_ID +from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import aiohttp_client from .const import DOMAIN @@ -21,7 +23,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 - async def async_step_user(self, user_input=None): + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle the initial step.""" errors = {} if user_input is not None: diff --git a/homeassistant/components/faa_delays/coordinator.py b/homeassistant/components/faa_delays/coordinator.py index f2aefdada66..2f110cf7730 100644 --- a/homeassistant/components/faa_delays/coordinator.py +++ b/homeassistant/components/faa_delays/coordinator.py @@ -6,6 +6,7 @@ import logging from aiohttp import ClientConnectionError from faadelays import Airport +from homeassistant.core import HomeAssistant from homeassistant.helpers import aiohttp_client from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed @@ -14,19 +15,18 @@ from .const import DOMAIN _LOGGER = logging.getLogger(__name__) -class FAADataUpdateCoordinator(DataUpdateCoordinator): +class FAADataUpdateCoordinator(DataUpdateCoordinator[Airport]): """Class to manage fetching FAA API data from a single endpoint.""" - def __init__(self, hass, code): + def __init__(self, hass: HomeAssistant, code: str) -> None: """Initialize the coordinator.""" super().__init__( hass, _LOGGER, name=DOMAIN, update_interval=timedelta(minutes=1) ) self.session = aiohttp_client.async_get_clientsession(hass) self.data = Airport(code, self.session) - self.code = code - async def _async_update_data(self): + async def _async_update_data(self) -> Airport: try: async with asyncio.timeout(10): await self.data.update() diff --git a/mypy.ini b/mypy.ini index 0ed06edaa1d..e01be53db3d 100644 --- a/mypy.ini +++ b/mypy.ini @@ -961,6 +961,16 @@ disallow_untyped_defs = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.faa_delays.*] +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.fan.*] check_untyped_defs = true disallow_incomplete_defs = true