From 5483ab0cda14e18a33546a3dffe4cf77b0327435 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Tue, 27 Jul 2021 02:42:51 -0600 Subject: [PATCH] Enforce strict typing for Flu Near You (#53407) --- .strict-typing | 1 + .../components/flunearyou/__init__.py | 22 ++++++++---- .../components/flunearyou/config_flow.py | 13 +++++-- .../components/flunearyou/manifest.json | 2 +- homeassistant/components/flunearyou/sensor.py | 35 ++++++++++++++----- mypy.ini | 11 ++++++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 8 files changed, 67 insertions(+), 21 deletions(-) diff --git a/.strict-typing b/.strict-typing index 90d2d135de3..82069f1548a 100644 --- a/.strict-typing +++ b/.strict-typing @@ -37,6 +37,7 @@ homeassistant.components.esphome.* homeassistant.components.energy.* homeassistant.components.fastdotcom.* homeassistant.components.fitbit.* +homeassistant.components.flunearyou.* homeassistant.components.forecast_solar.* homeassistant.components.fritzbox.* homeassistant.components.frontend.* diff --git a/homeassistant/components/flunearyou/__init__.py b/homeassistant/components/flunearyou/__init__.py index d80591c067c..22de54180a6 100644 --- a/homeassistant/components/flunearyou/__init__.py +++ b/homeassistant/components/flunearyou/__init__.py @@ -1,12 +1,17 @@ """The flunearyou component.""" +from __future__ import annotations + import asyncio from datetime import timedelta from functools import partial +from typing import Any from pyflunearyou import Client from pyflunearyou.errors import FluNearYouError +from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE +from homeassistant.core import HomeAssistant from homeassistant.helpers import aiohttp_client, config_validation as cv from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed @@ -25,28 +30,33 @@ CONFIG_SCHEMA = cv.deprecated(DOMAIN) PLATFORMS = ["sensor"] -async def async_setup_entry(hass, entry): +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Flu Near You as config entry.""" hass.data.setdefault(DOMAIN, {DATA_COORDINATOR: {}}) hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id] = {} websession = aiohttp_client.async_get_clientsession(hass) - client = Client(websession) + client = Client(session=websession) latitude = entry.data.get(CONF_LATITUDE, hass.config.latitude) longitude = entry.data.get(CONF_LONGITUDE, hass.config.longitude) - async def async_update(api_category): + async def async_update(api_category: str) -> dict[str, Any]: """Get updated date from the API based on category.""" try: if api_category == CATEGORY_CDC_REPORT: - return await client.cdc_reports.status_by_coordinates( + data = await client.cdc_reports.status_by_coordinates( + latitude, longitude + ) + else: + data = await client.user_reports.status_by_coordinates( latitude, longitude ) - return await client.user_reports.status_by_coordinates(latitude, longitude) except FluNearYouError as err: raise UpdateFailed(err) from err + return data + data_init_tasks = [] for api_category in (CATEGORY_CDC_REPORT, CATEGORY_USER_REPORT): coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][ @@ -67,7 +77,7 @@ async def async_setup_entry(hass, entry): return True -async def async_unload_entry(hass, entry): +async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload an Flu Near You config entry.""" unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) if unload_ok: diff --git a/homeassistant/components/flunearyou/config_flow.py b/homeassistant/components/flunearyou/config_flow.py index a63b6484a61..0005e0c257a 100644 --- a/homeassistant/components/flunearyou/config_flow.py +++ b/homeassistant/components/flunearyou/config_flow.py @@ -1,10 +1,15 @@ """Define a config flow manager for flunearyou.""" +from __future__ import annotations + +from typing import Any + from pyflunearyou import Client from pyflunearyou.errors import FluNearYouError import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE +from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import aiohttp_client, config_validation as cv from .const import DOMAIN, LOGGER @@ -16,7 +21,7 @@ class FluNearYouFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 @property - def data_schema(self): + def data_schema(self) -> vol.Schema: """Return the data schema for integration.""" return vol.Schema( { @@ -29,7 +34,9 @@ class FluNearYouFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): } ) - 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 start of the config flow.""" if not user_input: return self.async_show_form(step_id="user", data_schema=self.data_schema) @@ -40,7 +47,7 @@ class FluNearYouFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): self._abort_if_unique_id_configured() websession = aiohttp_client.async_get_clientsession(self.hass) - client = Client(websession) + client = Client(session=websession) try: await client.cdc_reports.status_by_coordinates( diff --git a/homeassistant/components/flunearyou/manifest.json b/homeassistant/components/flunearyou/manifest.json index 71f0b49771e..5fd3eb6638f 100644 --- a/homeassistant/components/flunearyou/manifest.json +++ b/homeassistant/components/flunearyou/manifest.json @@ -3,7 +3,7 @@ "name": "Flu Near You", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/flunearyou", - "requirements": ["pyflunearyou==1.0.7"], + "requirements": ["pyflunearyou==2.0.2"], "codeowners": ["@bachya"], "iot_class": "cloud_polling" } diff --git a/homeassistant/components/flunearyou/sensor.py b/homeassistant/components/flunearyou/sensor.py index 244d9120d7d..88fb0147296 100644 --- a/homeassistant/components/flunearyou/sensor.py +++ b/homeassistant/components/flunearyou/sensor.py @@ -1,13 +1,20 @@ """Support for user- and CDC-based flu info sensors from Flu Near You.""" +from __future__ import annotations + from homeassistant.components.sensor import SensorEntity +from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_ATTRIBUTION, ATTR_STATE, CONF_LATITUDE, CONF_LONGITUDE, ) -from homeassistant.core import callback -from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) from .const import CATEGORY_CDC_REPORT, CATEGORY_USER_REPORT, DATA_COORDINATOR, DOMAIN @@ -53,11 +60,13 @@ EXTENDED_SENSOR_TYPE_MAPPING = { } -async def async_setup_entry(hass, entry, async_add_entities): +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: """Set up Flu Near You sensors based on a config entry.""" coordinators = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id] - sensors = [] + sensors: list[CdcSensor | UserSensor] = [] for (sensor_type, name, icon, unit) in CDC_SENSORS: sensors.append( @@ -89,7 +98,15 @@ async def async_setup_entry(hass, entry, async_add_entities): class FluNearYouSensor(CoordinatorEntity, SensorEntity): """Define a base Flu Near You sensor.""" - def __init__(self, coordinator, entry, sensor_type, name, icon, unit): + def __init__( + self, + coordinator: DataUpdateCoordinator, + entry: ConfigEntry, + sensor_type: str, + name: str, + icon: str, + unit: str | None, + ) -> None: """Initialize the sensor.""" super().__init__(coordinator) self._attr_extra_state_attributes = {ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION} @@ -109,13 +126,13 @@ class FluNearYouSensor(CoordinatorEntity, SensorEntity): self.update_from_latest_data() self.async_write_ha_state() - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Register callbacks.""" await super().async_added_to_hass() self.update_from_latest_data() @callback - def update_from_latest_data(self): + def update_from_latest_data(self) -> None: """Update the sensor.""" raise NotImplementedError @@ -124,7 +141,7 @@ class CdcSensor(FluNearYouSensor): """Define a sensor for CDC reports.""" @callback - def update_from_latest_data(self): + def update_from_latest_data(self) -> None: """Update the sensor.""" self._attr_extra_state_attributes.update( { @@ -139,7 +156,7 @@ class UserSensor(FluNearYouSensor): """Define a sensor for user reports.""" @callback - def update_from_latest_data(self): + def update_from_latest_data(self) -> None: """Update the sensor.""" self._attr_extra_state_attributes.update( { diff --git a/mypy.ini b/mypy.ini index beab8cd8d17..072242f44e7 100644 --- a/mypy.ini +++ b/mypy.ini @@ -418,6 +418,17 @@ no_implicit_optional = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.flunearyou.*] +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.forecast_solar.*] check_untyped_defs = true disallow_incomplete_defs = true diff --git a/requirements_all.txt b/requirements_all.txt index 83e8ef37bee..d9c8162d26d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1446,7 +1446,7 @@ pyflic==2.0.3 pyflume==0.5.5 # homeassistant.components.flunearyou -pyflunearyou==1.0.7 +pyflunearyou==2.0.2 # homeassistant.components.futurenow pyfnip==0.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 7815d596c20..6704cb73b5c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -811,7 +811,7 @@ pyfireservicerota==0.0.43 pyflume==0.5.5 # homeassistant.components.flunearyou -pyflunearyou==1.0.7 +pyflunearyou==2.0.2 # homeassistant.components.forked_daapd pyforked-daapd==0.1.11