From 0e7cd02d178b3972d0520a9e41eb241ae575a94b Mon Sep 17 00:00:00 2001 From: Yuval Aboulafia Date: Mon, 5 Jul 2021 11:19:37 +0300 Subject: [PATCH] Add type checking and entity attributes for Fast.com (#52524) * Cleanup fast.com (typing, attrs) * Adress review * fixes --- .strict-typing | 1 + .../components/fastdotcom/__init__.py | 15 +++-- homeassistant/components/fastdotcom/sensor.py | 64 ++++++++----------- mypy.ini | 11 ++++ 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/.strict-typing b/.strict-typing index dbf25ac927e..f267925ad19 100644 --- a/.strict-typing +++ b/.strict-typing @@ -31,6 +31,7 @@ homeassistant.components.dnsip.* homeassistant.components.dsmr.* homeassistant.components.dunehd.* homeassistant.components.elgato.* +homeassistant.components.fastdotcom.* homeassistant.components.fitbit.* homeassistant.components.forecast_solar.* homeassistant.components.fritzbox.* diff --git a/homeassistant/components/fastdotcom/__init__.py b/homeassistant/components/fastdotcom/__init__.py index e0a4782493e..f2424332a01 100644 --- a/homeassistant/components/fastdotcom/__init__.py +++ b/homeassistant/components/fastdotcom/__init__.py @@ -1,15 +1,20 @@ """Support for testing internet speed via Fast.com.""" +from __future__ import annotations + from datetime import timedelta import logging +from typing import Any from fastdotcom import fast_com import voluptuous as vol from homeassistant.const import CONF_SCAN_INTERVAL +from homeassistant.core import HomeAssistant, ServiceCall import homeassistant.helpers.config_validation as cv from homeassistant.helpers.discovery import async_load_platform from homeassistant.helpers.dispatcher import dispatcher_send from homeassistant.helpers.event import async_track_time_interval +from homeassistant.helpers.typing import ConfigType DOMAIN = "fastdotcom" DATA_UPDATED = f"{DOMAIN}_data_updated" @@ -35,7 +40,7 @@ CONFIG_SCHEMA = vol.Schema( ) -async def async_setup(hass, config): +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the Fast.com component.""" conf = config[DOMAIN] data = hass.data[DOMAIN] = SpeedtestData(hass) @@ -43,7 +48,7 @@ async def async_setup(hass, config): if not conf[CONF_MANUAL]: async_track_time_interval(hass, data.update, conf[CONF_SCAN_INTERVAL]) - def update(call=None): + def update(service_call: ServiceCall | None = None) -> None: """Service call to manually update the data.""" data.update() @@ -57,12 +62,12 @@ async def async_setup(hass, config): class SpeedtestData: """Get the latest data from fast.com.""" - def __init__(self, hass): + def __init__(self, hass: HomeAssistant) -> None: """Initialize the data object.""" - self.data = None + self.data: dict[str, Any] | None = None self._hass = hass - def update(self, now=None): + def update(self) -> None: """Get the latest data from fast.com.""" _LOGGER.debug("Executing fast.com speedtest") diff --git a/homeassistant/components/fastdotcom/sensor.py b/homeassistant/components/fastdotcom/sensor.py index b4406a4de95..14f63a99e5d 100644 --- a/homeassistant/components/fastdotcom/sensor.py +++ b/homeassistant/components/fastdotcom/sensor.py @@ -1,16 +1,27 @@ """Support for Fast.com internet speed testing sensor.""" +from __future__ import annotations + +from typing import Any + from homeassistant.components.sensor import SensorEntity from homeassistant.const import DATA_RATE_MEGABITS_PER_SECOND -from homeassistant.core import callback +from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.restore_state import RestoreEntity +from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from . import DATA_UPDATED, DOMAIN as FASTDOTCOM_DOMAIN ICON = "mdi:speedometer" -async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): +async def async_setup_platform( + hass: HomeAssistant, + config: ConfigType, + async_add_entities: AddEntitiesCallback, + discovery_info: DiscoveryInfoType | None = None, +) -> None: """Set up the Fast.com sensor.""" async_add_entities([SpeedtestSensor(hass.data[FASTDOTCOM_DOMAIN])]) @@ -18,38 +29,17 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= class SpeedtestSensor(RestoreEntity, SensorEntity): """Implementation of a FAst.com sensor.""" - def __init__(self, speedtest_data): + _attr_name = "Fast.com Download" + _attr_unit_of_measurement = DATA_RATE_MEGABITS_PER_SECOND + _attr_icon = ICON + _attr_should_poll = False + _attr_state = None + + def __init__(self, speedtest_data: dict[str, Any]) -> None: """Initialize the sensor.""" - self._name = "Fast.com Download" - self.speedtest_client = speedtest_data - self._state = None + self._speedtest_data = speedtest_data - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def state(self): - """Return the state of the device.""" - return self._state - - @property - def unit_of_measurement(self): - """Return the unit of measurement of this entity, if any.""" - return DATA_RATE_MEGABITS_PER_SECOND - - @property - def icon(self): - """Return icon.""" - return ICON - - @property - def should_poll(self): - """Return the polling requirement for this sensor.""" - return False - - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Handle entity which will be added.""" await super().async_added_to_hass() @@ -62,15 +52,15 @@ class SpeedtestSensor(RestoreEntity, SensorEntity): state = await self.async_get_last_state() if not state: return - self._state = state.state + self._attr_state = state.state - def update(self): + def update(self) -> None: """Get the latest data and update the states.""" - data = self.speedtest_client.data + data = self._speedtest_data.data # type: ignore[attr-defined] if data is None: return - self._state = data["download"] + self._attr_state = data["download"] @callback - def _schedule_immediate_update(self): + def _schedule_immediate_update(self) -> None: self.async_schedule_update_ha_state(True) diff --git a/mypy.ini b/mypy.ini index 78a42cdaaf4..7e2b6f24632 100644 --- a/mypy.ini +++ b/mypy.ini @@ -352,6 +352,17 @@ no_implicit_optional = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.fastdotcom.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +no_implicit_optional = true +warn_return_any = true +warn_unreachable = true + [mypy-homeassistant.components.fitbit.*] check_untyped_defs = true disallow_incomplete_defs = true