Enforce strict typing for Flu Near You (#53407)

This commit is contained in:
Aaron Bach 2021-07-27 02:42:51 -06:00 committed by GitHub
parent d7d859fc86
commit 5483ab0cda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 67 additions and 21 deletions

View File

@ -37,6 +37,7 @@ homeassistant.components.esphome.*
homeassistant.components.energy.* homeassistant.components.energy.*
homeassistant.components.fastdotcom.* homeassistant.components.fastdotcom.*
homeassistant.components.fitbit.* homeassistant.components.fitbit.*
homeassistant.components.flunearyou.*
homeassistant.components.forecast_solar.* homeassistant.components.forecast_solar.*
homeassistant.components.fritzbox.* homeassistant.components.fritzbox.*
homeassistant.components.frontend.* homeassistant.components.frontend.*

View File

@ -1,12 +1,17 @@
"""The flunearyou component.""" """The flunearyou component."""
from __future__ import annotations
import asyncio import asyncio
from datetime import timedelta from datetime import timedelta
from functools import partial from functools import partial
from typing import Any
from pyflunearyou import Client from pyflunearyou import Client
from pyflunearyou.errors import FluNearYouError from pyflunearyou.errors import FluNearYouError
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE 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 import aiohttp_client, config_validation as cv
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
@ -25,28 +30,33 @@ CONFIG_SCHEMA = cv.deprecated(DOMAIN)
PLATFORMS = ["sensor"] 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.""" """Set up Flu Near You as config entry."""
hass.data.setdefault(DOMAIN, {DATA_COORDINATOR: {}}) hass.data.setdefault(DOMAIN, {DATA_COORDINATOR: {}})
hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id] = {} hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id] = {}
websession = aiohttp_client.async_get_clientsession(hass) websession = aiohttp_client.async_get_clientsession(hass)
client = Client(websession) client = Client(session=websession)
latitude = entry.data.get(CONF_LATITUDE, hass.config.latitude) latitude = entry.data.get(CONF_LATITUDE, hass.config.latitude)
longitude = entry.data.get(CONF_LONGITUDE, hass.config.longitude) 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.""" """Get updated date from the API based on category."""
try: try:
if api_category == CATEGORY_CDC_REPORT: 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 latitude, longitude
) )
return await client.user_reports.status_by_coordinates(latitude, longitude)
except FluNearYouError as err: except FluNearYouError as err:
raise UpdateFailed(err) from err raise UpdateFailed(err) from err
return data
data_init_tasks = [] data_init_tasks = []
for api_category in (CATEGORY_CDC_REPORT, CATEGORY_USER_REPORT): for api_category in (CATEGORY_CDC_REPORT, CATEGORY_USER_REPORT):
coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][ coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][
@ -67,7 +77,7 @@ async def async_setup_entry(hass, entry):
return True 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 an Flu Near You config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok: if unload_ok:

View File

@ -1,10 +1,15 @@
"""Define a config flow manager for flunearyou.""" """Define a config flow manager for flunearyou."""
from __future__ import annotations
from typing import Any
from pyflunearyou import Client from pyflunearyou import Client
from pyflunearyou.errors import FluNearYouError from pyflunearyou.errors import FluNearYouError
import voluptuous as vol import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE 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 homeassistant.helpers import aiohttp_client, config_validation as cv
from .const import DOMAIN, LOGGER from .const import DOMAIN, LOGGER
@ -16,7 +21,7 @@ class FluNearYouFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
VERSION = 1 VERSION = 1
@property @property
def data_schema(self): def data_schema(self) -> vol.Schema:
"""Return the data schema for integration.""" """Return the data schema for integration."""
return vol.Schema( 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.""" """Handle the start of the config flow."""
if not user_input: if not user_input:
return self.async_show_form(step_id="user", data_schema=self.data_schema) 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() self._abort_if_unique_id_configured()
websession = aiohttp_client.async_get_clientsession(self.hass) websession = aiohttp_client.async_get_clientsession(self.hass)
client = Client(websession) client = Client(session=websession)
try: try:
await client.cdc_reports.status_by_coordinates( await client.cdc_reports.status_by_coordinates(

View File

@ -3,7 +3,7 @@
"name": "Flu Near You", "name": "Flu Near You",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/flunearyou", "documentation": "https://www.home-assistant.io/integrations/flunearyou",
"requirements": ["pyflunearyou==1.0.7"], "requirements": ["pyflunearyou==2.0.2"],
"codeowners": ["@bachya"], "codeowners": ["@bachya"],
"iot_class": "cloud_polling" "iot_class": "cloud_polling"
} }

View File

@ -1,13 +1,20 @@
"""Support for user- and CDC-based flu info sensors from Flu Near You.""" """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.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
ATTR_ATTRIBUTION, ATTR_ATTRIBUTION,
ATTR_STATE, ATTR_STATE,
CONF_LATITUDE, CONF_LATITUDE,
CONF_LONGITUDE, CONF_LONGITUDE,
) )
from homeassistant.core import callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.update_coordinator import CoordinatorEntity 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 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.""" """Set up Flu Near You sensors based on a config entry."""
coordinators = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id] coordinators = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id]
sensors = [] sensors: list[CdcSensor | UserSensor] = []
for (sensor_type, name, icon, unit) in CDC_SENSORS: for (sensor_type, name, icon, unit) in CDC_SENSORS:
sensors.append( sensors.append(
@ -89,7 +98,15 @@ async def async_setup_entry(hass, entry, async_add_entities):
class FluNearYouSensor(CoordinatorEntity, SensorEntity): class FluNearYouSensor(CoordinatorEntity, SensorEntity):
"""Define a base Flu Near You sensor.""" """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.""" """Initialize the sensor."""
super().__init__(coordinator) super().__init__(coordinator)
self._attr_extra_state_attributes = {ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION} self._attr_extra_state_attributes = {ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION}
@ -109,13 +126,13 @@ class FluNearYouSensor(CoordinatorEntity, SensorEntity):
self.update_from_latest_data() self.update_from_latest_data()
self.async_write_ha_state() self.async_write_ha_state()
async def async_added_to_hass(self): async def async_added_to_hass(self) -> None:
"""Register callbacks.""" """Register callbacks."""
await super().async_added_to_hass() await super().async_added_to_hass()
self.update_from_latest_data() self.update_from_latest_data()
@callback @callback
def update_from_latest_data(self): def update_from_latest_data(self) -> None:
"""Update the sensor.""" """Update the sensor."""
raise NotImplementedError raise NotImplementedError
@ -124,7 +141,7 @@ class CdcSensor(FluNearYouSensor):
"""Define a sensor for CDC reports.""" """Define a sensor for CDC reports."""
@callback @callback
def update_from_latest_data(self): def update_from_latest_data(self) -> None:
"""Update the sensor.""" """Update the sensor."""
self._attr_extra_state_attributes.update( self._attr_extra_state_attributes.update(
{ {
@ -139,7 +156,7 @@ class UserSensor(FluNearYouSensor):
"""Define a sensor for user reports.""" """Define a sensor for user reports."""
@callback @callback
def update_from_latest_data(self): def update_from_latest_data(self) -> None:
"""Update the sensor.""" """Update the sensor."""
self._attr_extra_state_attributes.update( self._attr_extra_state_attributes.update(
{ {

View File

@ -418,6 +418,17 @@ no_implicit_optional = true
warn_return_any = true warn_return_any = true
warn_unreachable = 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.*] [mypy-homeassistant.components.forecast_solar.*]
check_untyped_defs = true check_untyped_defs = true
disallow_incomplete_defs = true disallow_incomplete_defs = true

View File

@ -1446,7 +1446,7 @@ pyflic==2.0.3
pyflume==0.5.5 pyflume==0.5.5
# homeassistant.components.flunearyou # homeassistant.components.flunearyou
pyflunearyou==1.0.7 pyflunearyou==2.0.2
# homeassistant.components.futurenow # homeassistant.components.futurenow
pyfnip==0.2 pyfnip==0.2

View File

@ -811,7 +811,7 @@ pyfireservicerota==0.0.43
pyflume==0.5.5 pyflume==0.5.5
# homeassistant.components.flunearyou # homeassistant.components.flunearyou
pyflunearyou==1.0.7 pyflunearyou==2.0.2
# homeassistant.components.forked_daapd # homeassistant.components.forked_daapd
pyforked-daapd==0.1.11 pyforked-daapd==0.1.11