From 0e1927830951900d9184fe9d3f327448cc1fa8b6 Mon Sep 17 00:00:00 2001 From: carstenschroeder Date: Mon, 1 Nov 2021 14:28:30 +0100 Subject: [PATCH] Add type annotations to OpenWeatherMap (#58802) --- .../components/openweathermap/__init__.py | 15 +++--- .../components/openweathermap/sensor.py | 40 +++++++++------ .../components/openweathermap/weather.py | 49 +++++++++++-------- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/openweathermap/__init__.py b/homeassistant/components/openweathermap/__init__.py index 58219ee70b3..8fd7aaae7ad 100644 --- a/homeassistant/components/openweathermap/__init__.py +++ b/homeassistant/components/openweathermap/__init__.py @@ -1,5 +1,8 @@ """The openweathermap component.""" +from __future__ import annotations + import logging +from typing import Any from pyowm import OWM from pyowm.utils.config import get_default_config @@ -62,7 +65,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: return True -async def async_migrate_entry(hass, entry): +async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Migrate old entry.""" config_entries = hass.config_entries data = entry.data @@ -83,7 +86,7 @@ async def async_migrate_entry(hass, entry): return True -async def async_update_options(hass: HomeAssistant, entry: ConfigEntry): +async def async_update_options(hass: HomeAssistant, entry: ConfigEntry) -> None: """Update options.""" await hass.config_entries.async_reload(entry.entry_id) @@ -99,17 +102,13 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: return unload_ok -def _filter_domain_configs(elements, domain): - return list(filter(lambda elem: elem["platform"] == domain, elements)) - - -def _get_config_value(config_entry, key): +def _get_config_value(config_entry: ConfigEntry, key: str) -> Any: if config_entry.options: return config_entry.options[key] return config_entry.data[key] -def _get_owm_config(language): +def _get_owm_config(language: str) -> dict[str, Any]: """Get OpenWeatherMap configuration and add language to it.""" config_dict = get_default_config() config_dict["language"] = language diff --git a/homeassistant/components/openweathermap/sensor.py b/homeassistant/components/openweathermap/sensor.py index 13b282b5ef6..dcdb1c0c8fb 100644 --- a/homeassistant/components/openweathermap/sensor.py +++ b/homeassistant/components/openweathermap/sensor.py @@ -2,8 +2,12 @@ from __future__ import annotations from homeassistant.components.sensor import SensorEntity, SensorEntityDescription +from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_ATTRIBUTION +from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.typing import StateType from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import ( @@ -20,7 +24,11 @@ from .const import ( from .weather_update_coordinator import WeatherUpdateCoordinator -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: """Set up OpenWeatherMap sensor entities based on a config entry.""" domain_data = hass.data[DOMAIN][config_entry.entry_id] name = domain_data[ENTRY_NAME] @@ -59,11 +67,11 @@ class AbstractOpenWeatherMapSensor(SensorEntity): def __init__( self, - name, - unique_id, + name: str, + unique_id: str, description: SensorEntityDescription, coordinator: DataUpdateCoordinator, - ): + ) -> None: """Initialize the sensor.""" self.entity_description = description self._coordinator = coordinator @@ -79,22 +87,22 @@ class AbstractOpenWeatherMapSensor(SensorEntity): ) @property - def attribution(self): + def attribution(self) -> str: """Return the attribution.""" return ATTRIBUTION @property - def available(self): + def available(self) -> bool: """Return True if entity is available.""" return self._coordinator.last_update_success - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Connect to dispatcher listening for entity data notifications.""" self.async_on_remove( self._coordinator.async_add_listener(self.async_write_ha_state) ) - async def async_update(self): + async def async_update(self) -> None: """Get the latest data from OWM and updates the states.""" await self._coordinator.async_request_refresh() @@ -104,17 +112,17 @@ class OpenWeatherMapSensor(AbstractOpenWeatherMapSensor): def __init__( self, - name, - unique_id, + name: str, + unique_id: str, description: SensorEntityDescription, weather_coordinator: WeatherUpdateCoordinator, - ): + ) -> None: """Initialize the sensor.""" super().__init__(name, unique_id, description, weather_coordinator) self._weather_coordinator = weather_coordinator @property - def native_value(self): + def native_value(self) -> StateType: """Return the state of the device.""" return self._weather_coordinator.data.get(self.entity_description.key, None) @@ -124,17 +132,17 @@ class OpenWeatherMapForecastSensor(AbstractOpenWeatherMapSensor): def __init__( self, - name, - unique_id, + name: str, + unique_id: str, description: SensorEntityDescription, weather_coordinator: WeatherUpdateCoordinator, - ): + ) -> None: """Initialize the sensor.""" super().__init__(name, unique_id, description, weather_coordinator) self._weather_coordinator = weather_coordinator @property - def native_value(self): + def native_value(self) -> StateType: """Return the state of the device.""" forecasts = self._weather_coordinator.data.get(ATTR_API_FORECAST) if forecasts is not None and len(forecasts) > 0: diff --git a/homeassistant/components/openweathermap/weather.py b/homeassistant/components/openweathermap/weather.py index f80566be329..d3b5c488c56 100644 --- a/homeassistant/components/openweathermap/weather.py +++ b/homeassistant/components/openweathermap/weather.py @@ -1,7 +1,12 @@ """Support for the OpenWeatherMap (OWM) service.""" -from homeassistant.components.weather import WeatherEntity +from __future__ import annotations + +from homeassistant.components.weather import Forecast, WeatherEntity +from homeassistant.config_entries import ConfigEntry from homeassistant.const import PRESSURE_HPA, PRESSURE_INHG, TEMP_CELSIUS +from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.util.pressure import convert as pressure_convert from .const import ( @@ -22,7 +27,11 @@ from .const import ( from .weather_update_coordinator import WeatherUpdateCoordinator -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: """Set up OpenWeatherMap weather entity based on a config entry.""" domain_data = hass.data[DOMAIN][config_entry.entry_id] name = domain_data[ENTRY_NAME] @@ -39,22 +48,22 @@ class OpenWeatherMapWeather(WeatherEntity): def __init__( self, - name, - unique_id, + name: str, + unique_id: str, weather_coordinator: WeatherUpdateCoordinator, - ): + ) -> None: """Initialize the sensor.""" self._name = name self._unique_id = unique_id self._weather_coordinator = weather_coordinator @property - def name(self): + def name(self) -> str: """Return the name of the sensor.""" return self._name @property - def unique_id(self): + def unique_id(self) -> str: """Return a unique_id for this entity.""" return self._unique_id @@ -69,32 +78,32 @@ class OpenWeatherMapWeather(WeatherEntity): ) @property - def should_poll(self): + def should_poll(self) -> bool: """Return the polling requirement of the entity.""" return False @property - def attribution(self): + def attribution(self) -> str: """Return the attribution.""" return ATTRIBUTION @property - def condition(self): + def condition(self) -> str | None: """Return the current condition.""" return self._weather_coordinator.data[ATTR_API_CONDITION] @property - def temperature(self): + def temperature(self) -> float | None: """Return the temperature.""" return self._weather_coordinator.data[ATTR_API_TEMPERATURE] @property - def temperature_unit(self): + def temperature_unit(self) -> str: """Return the unit of measurement.""" return TEMP_CELSIUS @property - def pressure(self): + def pressure(self) -> float | None: """Return the pressure.""" pressure = self._weather_coordinator.data[ATTR_API_PRESSURE] # OpenWeatherMap returns pressure in hPA, so convert to @@ -104,12 +113,12 @@ class OpenWeatherMapWeather(WeatherEntity): return pressure @property - def humidity(self): + def humidity(self) -> float | None: """Return the humidity.""" return self._weather_coordinator.data[ATTR_API_HUMIDITY] @property - def wind_speed(self): + def wind_speed(self) -> float | None: """Return the wind speed.""" wind_speed = self._weather_coordinator.data[ATTR_API_WIND_SPEED] if self.hass.config.units.name == "imperial": @@ -117,26 +126,26 @@ class OpenWeatherMapWeather(WeatherEntity): return round(wind_speed * 3.6, 2) @property - def wind_bearing(self): + def wind_bearing(self) -> float | str | None: """Return the wind bearing.""" return self._weather_coordinator.data[ATTR_API_WIND_BEARING] @property - def forecast(self): + def forecast(self) -> list[Forecast] | None: """Return the forecast array.""" return self._weather_coordinator.data[ATTR_API_FORECAST] @property - def available(self): + def available(self) -> bool: """Return True if entity is available.""" return self._weather_coordinator.last_update_success - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Connect to dispatcher listening for entity data notifications.""" self.async_on_remove( self._weather_coordinator.async_add_listener(self.async_write_ha_state) ) - async def async_update(self): + async def async_update(self) -> None: """Get the latest data from OWM and updates the states.""" await self._weather_coordinator.async_request_refresh()