From 00093faae223cb0c79f327ccd4323274660ddda7 Mon Sep 17 00:00:00 2001 From: Robert Van Gorkom Date: Wed, 16 Sep 2020 14:23:50 -0700 Subject: [PATCH] Clean up vera typings (#40143) Co-authored-by: J. Nick Koston --- homeassistant/components/vera/__init__.py | 21 ++++++----- .../components/vera/binary_sensor.py | 14 +++++--- homeassistant/components/vera/climate.py | 36 ++++++++++--------- homeassistant/components/vera/config_flow.py | 7 ++-- homeassistant/components/vera/cover.py | 22 +++++++----- homeassistant/components/vera/light.py | 24 +++++++------ homeassistant/components/vera/lock.py | 20 ++++++----- homeassistant/components/vera/scene.py | 12 ++++--- homeassistant/components/vera/sensor.py | 19 +++++----- homeassistant/components/vera/switch.py | 20 ++++++----- 10 files changed, 113 insertions(+), 82 deletions(-) diff --git a/homeassistant/components/vera/__init__.py b/homeassistant/components/vera/__init__.py index 0d34a521276..fdc8503ed70 100644 --- a/homeassistant/components/vera/__init__.py +++ b/homeassistant/components/vera/__init__.py @@ -2,7 +2,7 @@ import asyncio from collections import defaultdict import logging -from typing import Type +from typing import Any, Dict, Generic, List, Optional, Type, TypeVar import pyvera as veraApi from requests.exceptions import RequestException @@ -168,7 +168,7 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> return True -def map_vera_device(vera_device, remap): +def map_vera_device(vera_device: veraApi.VeraDevice, remap: List[int]) -> str: """Map vera classes to Home Assistant types.""" type_map = { @@ -198,10 +198,13 @@ def map_vera_device(vera_device, remap): ) -class VeraDevice(Entity): +DeviceType = TypeVar("DeviceType", bound=veraApi.VeraDevice) + + +class VeraDevice(Generic[DeviceType], Entity): """Representation of a Vera device entity.""" - def __init__(self, vera_device, controller_data: ControllerData): + def __init__(self, vera_device: DeviceType, controller_data: ControllerData): """Initialize the device.""" self.vera_device = vera_device self.controller = controller_data.controller @@ -217,26 +220,26 @@ class VeraDevice(Entity): else: self._unique_id = f"vera_{controller_data.config_entry.unique_id}_{self.vera_device.vera_device_id}" - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Subscribe to updates.""" self.controller.register(self.vera_device, self._update_callback) - def _update_callback(self, _device): + def _update_callback(self, _device: DeviceType) -> None: """Update the state.""" self.schedule_update_ha_state(True) @property - def name(self): + def name(self) -> str: """Return the name of the device.""" return self._name @property - def should_poll(self): + def should_poll(self) -> bool: """Get polling requirement from vera device.""" return self.vera_device.should_poll @property - def device_state_attributes(self): + def device_state_attributes(self) -> Optional[Dict[str, Any]]: """Return the state attributes of the device.""" attr = {} diff --git a/homeassistant/components/vera/binary_sensor.py b/homeassistant/components/vera/binary_sensor.py index 7ab24e9544f..2e66d38e249 100644 --- a/homeassistant/components/vera/binary_sensor.py +++ b/homeassistant/components/vera/binary_sensor.py @@ -1,6 +1,8 @@ """Support for Vera binary sensors.""" import logging -from typing import Callable, List +from typing import Callable, List, Optional + +import pyvera as veraApi from homeassistant.components.binary_sensor import ( DOMAIN as PLATFORM_DOMAIN, @@ -32,20 +34,22 @@ async def async_setup_entry( ) -class VeraBinarySensor(VeraDevice, BinarySensorEntity): +class VeraBinarySensor(VeraDevice[veraApi.VeraBinarySensor], BinarySensorEntity): """Representation of a Vera Binary Sensor.""" - def __init__(self, vera_device, controller_data: ControllerData): + def __init__( + self, vera_device: veraApi.VeraBinarySensor, controller_data: ControllerData + ): """Initialize the binary_sensor.""" self._state = False VeraDevice.__init__(self, vera_device, controller_data) self.entity_id = ENTITY_ID_FORMAT.format(self.vera_id) @property - def is_on(self): + def is_on(self) -> Optional[bool]: """Return true if sensor is on.""" return self._state - def update(self): + def update(self) -> None: """Get the latest data and update the state.""" self._state = self.vera_device.is_tripped diff --git a/homeassistant/components/vera/climate.py b/homeassistant/components/vera/climate.py index a8ba647c1d6..0946de4a379 100644 --- a/homeassistant/components/vera/climate.py +++ b/homeassistant/components/vera/climate.py @@ -1,6 +1,8 @@ """Support for Vera thermostats.""" import logging -from typing import Callable, List +from typing import Any, Callable, List, Optional + +import pyvera as veraApi from homeassistant.components.climate import ( DOMAIN as PLATFORM_DOMAIN, @@ -49,21 +51,23 @@ async def async_setup_entry( ) -class VeraThermostat(VeraDevice, ClimateEntity): +class VeraThermostat(VeraDevice[veraApi.VeraThermostat], ClimateEntity): """Representation of a Vera Thermostat.""" - def __init__(self, vera_device, controller_data: ControllerData): + def __init__( + self, vera_device: veraApi.VeraThermostat, controller_data: ControllerData + ): """Initialize the Vera device.""" VeraDevice.__init__(self, vera_device, controller_data) self.entity_id = ENTITY_ID_FORMAT.format(self.vera_id) @property - def supported_features(self): + def supported_features(self) -> Optional[int]: """Return the list of supported features.""" return SUPPORT_FLAGS @property - def hvac_mode(self): + def hvac_mode(self) -> str: """Return hvac operation ie. heat, cool mode. Need to be one of HVAC_MODE_*. @@ -78,7 +82,7 @@ class VeraThermostat(VeraDevice, ClimateEntity): return HVAC_MODE_OFF @property - def hvac_modes(self): + def hvac_modes(self) -> List[str]: """Return the list of available hvac operation modes. Need to be a subset of HVAC_MODES. @@ -86,7 +90,7 @@ class VeraThermostat(VeraDevice, ClimateEntity): return SUPPORT_HVAC @property - def fan_mode(self): + def fan_mode(self) -> Optional[str]: """Return the fan setting.""" mode = self.vera_device.get_fan_mode() if mode == "ContinuousOn": @@ -94,11 +98,11 @@ class VeraThermostat(VeraDevice, ClimateEntity): return FAN_AUTO @property - def fan_modes(self): + def fan_modes(self) -> Optional[List[str]]: """Return a list of available fan modes.""" return FAN_OPERATION_LIST - def set_fan_mode(self, fan_mode): + def set_fan_mode(self, fan_mode) -> None: """Set new target temperature.""" if fan_mode == FAN_ON: self.vera_device.fan_on() @@ -108,14 +112,14 @@ class VeraThermostat(VeraDevice, ClimateEntity): self.schedule_update_ha_state() @property - def current_power_w(self): + def current_power_w(self) -> Optional[float]: """Return the current power usage in W.""" power = self.vera_device.power if power: return convert(power, float, 0.0) @property - def temperature_unit(self): + def temperature_unit(self) -> str: """Return the unit of measurement.""" vera_temp_units = self.vera_device.vera_controller.temperature_units @@ -125,28 +129,28 @@ class VeraThermostat(VeraDevice, ClimateEntity): return TEMP_CELSIUS @property - def current_temperature(self): + def current_temperature(self) -> Optional[float]: """Return the current temperature.""" return self.vera_device.get_current_temperature() @property - def operation(self): + def operation(self) -> str: """Return current operation ie. heat, cool, idle.""" return self.vera_device.get_hvac_mode() @property - def target_temperature(self): + def target_temperature(self) -> Optional[float]: """Return the temperature we try to reach.""" return self.vera_device.get_current_goal_temperature() - def set_temperature(self, **kwargs): + def set_temperature(self, **kwargs: Any) -> None: """Set new target temperatures.""" if kwargs.get(ATTR_TEMPERATURE) is not None: self.vera_device.set_temperature(kwargs.get(ATTR_TEMPERATURE)) self.schedule_update_ha_state() - def set_hvac_mode(self, hvac_mode): + def set_hvac_mode(self, hvac_mode) -> None: """Set new target hvac mode.""" if hvac_mode == HVAC_MODE_OFF: self.vera_device.turn_off() diff --git a/homeassistant/components/vera/config_flow.py b/homeassistant/components/vera/config_flow.py index 26ae509337b..754d2eca542 100644 --- a/homeassistant/components/vera/config_flow.py +++ b/homeassistant/components/vera/config_flow.py @@ -8,6 +8,7 @@ from requests.exceptions import RequestException import voluptuous as vol from homeassistant import config_entries +from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_EXCLUDE, CONF_LIGHTS, CONF_SOURCE from homeassistant.core import callback from homeassistant.helpers.entity_registry import EntityRegistry @@ -68,11 +69,11 @@ def options_data(user_input: dict) -> dict: class OptionsFlowHandler(config_entries.OptionsFlow): """Options for the component.""" - def __init__(self, config_entry: config_entries.ConfigEntry): + def __init__(self, config_entry: ConfigEntry): """Init object.""" self.config_entry = config_entry - async def async_step_init(self, user_input=None): + async def async_step_init(self, user_input: dict = None): """Manage the options.""" if user_input is not None: return self.async_create_entry( @@ -91,7 +92,7 @@ class VeraFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): @staticmethod @callback - def async_get_options_flow(config_entry) -> OptionsFlowHandler: + def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlowHandler: """Get the options flow.""" return OptionsFlowHandler(config_entry) diff --git a/homeassistant/components/vera/cover.py b/homeassistant/components/vera/cover.py index bad36727c15..49b15e91eb2 100644 --- a/homeassistant/components/vera/cover.py +++ b/homeassistant/components/vera/cover.py @@ -1,6 +1,8 @@ """Support for Vera cover - curtains, rollershutters etc.""" import logging -from typing import Callable, List +from typing import Any, Callable, List + +import pyvera as veraApi from homeassistant.components.cover import ( ATTR_POSITION, @@ -33,16 +35,18 @@ async def async_setup_entry( ) -class VeraCover(VeraDevice, CoverEntity): +class VeraCover(VeraDevice[veraApi.VeraCurtain], CoverEntity): """Representation a Vera Cover.""" - def __init__(self, vera_device, controller_data: ControllerData): + def __init__( + self, vera_device: veraApi.VeraCurtain, controller_data: ControllerData + ): """Initialize the Vera device.""" VeraDevice.__init__(self, vera_device, controller_data) self.entity_id = ENTITY_ID_FORMAT.format(self.vera_id) @property - def current_cover_position(self): + def current_cover_position(self) -> int: """ Return current position of cover. @@ -55,28 +59,28 @@ class VeraCover(VeraDevice, CoverEntity): return 100 return position - def set_cover_position(self, **kwargs): + def set_cover_position(self, **kwargs) -> None: """Move the cover to a specific position.""" self.vera_device.set_level(kwargs.get(ATTR_POSITION)) self.schedule_update_ha_state() @property - def is_closed(self): + def is_closed(self) -> bool: """Return if the cover is closed.""" if self.current_cover_position is not None: return self.current_cover_position == 0 - def open_cover(self, **kwargs): + def open_cover(self, **kwargs: Any) -> None: """Open the cover.""" self.vera_device.open() self.schedule_update_ha_state() - def close_cover(self, **kwargs): + def close_cover(self, **kwargs: Any) -> None: """Close the cover.""" self.vera_device.close() self.schedule_update_ha_state() - def stop_cover(self, **kwargs): + def stop_cover(self, **kwargs: Any) -> None: """Stop the cover.""" self.vera_device.stop() self.schedule_update_ha_state() diff --git a/homeassistant/components/vera/light.py b/homeassistant/components/vera/light.py index 84f36fe3877..47d2d039d2a 100644 --- a/homeassistant/components/vera/light.py +++ b/homeassistant/components/vera/light.py @@ -1,6 +1,8 @@ """Support for Vera lights.""" import logging -from typing import Callable, List +from typing import Any, Callable, List, Optional, Tuple + +import pyvera as veraApi from homeassistant.components.light import ( ATTR_BRIGHTNESS, @@ -37,10 +39,12 @@ async def async_setup_entry( ) -class VeraLight(VeraDevice, LightEntity): +class VeraLight(VeraDevice[veraApi.VeraDimmer], LightEntity): """Representation of a Vera Light, including dimmable.""" - def __init__(self, vera_device, controller_data: ControllerData): + def __init__( + self, vera_device: veraApi.VeraDimmer, controller_data: ControllerData + ): """Initialize the light.""" self._state = False self._color = None @@ -49,23 +53,23 @@ class VeraLight(VeraDevice, LightEntity): self.entity_id = ENTITY_ID_FORMAT.format(self.vera_id) @property - def brightness(self): + def brightness(self) -> Optional[int]: """Return the brightness of the light.""" return self._brightness @property - def hs_color(self): + def hs_color(self) -> Optional[Tuple[float, float]]: """Return the color of the light.""" return self._color @property - def supported_features(self): + def supported_features(self) -> int: """Flag supported features.""" if self._color: return SUPPORT_BRIGHTNESS | SUPPORT_COLOR return SUPPORT_BRIGHTNESS - def turn_on(self, **kwargs): + def turn_on(self, **kwargs: Any) -> None: """Turn the light on.""" if ATTR_HS_COLOR in kwargs and self._color: rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) @@ -78,18 +82,18 @@ class VeraLight(VeraDevice, LightEntity): self._state = True self.schedule_update_ha_state(True) - def turn_off(self, **kwargs): + def turn_off(self, **kwargs: Any): """Turn the light off.""" self.vera_device.switch_off() self._state = False self.schedule_update_ha_state() @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" return self._state - def update(self): + def update(self) -> None: """Call to update state.""" self._state = self.vera_device.is_switched_on() if self.vera_device.is_dimmable: diff --git a/homeassistant/components/vera/lock.py b/homeassistant/components/vera/lock.py index 6a1158d18c4..46f8c6f189e 100644 --- a/homeassistant/components/vera/lock.py +++ b/homeassistant/components/vera/lock.py @@ -1,6 +1,8 @@ """Support for Vera locks.""" import logging -from typing import Callable, List +from typing import Any, Callable, Dict, List, Optional + +import pyvera as veraApi from homeassistant.components.lock import ( DOMAIN as PLATFORM_DOMAIN, @@ -36,32 +38,32 @@ async def async_setup_entry( ) -class VeraLock(VeraDevice, LockEntity): +class VeraLock(VeraDevice[veraApi.VeraLock], LockEntity): """Representation of a Vera lock.""" - def __init__(self, vera_device, controller_data: ControllerData): + def __init__(self, vera_device: veraApi.VeraLock, controller_data: ControllerData): """Initialize the Vera device.""" self._state = None VeraDevice.__init__(self, vera_device, controller_data) self.entity_id = ENTITY_ID_FORMAT.format(self.vera_id) - def lock(self, **kwargs): + def lock(self, **kwargs: Any) -> None: """Lock the device.""" self.vera_device.lock() self._state = STATE_LOCKED - def unlock(self, **kwargs): + def unlock(self, **kwargs: Any) -> None: """Unlock the device.""" self.vera_device.unlock() self._state = STATE_UNLOCKED @property - def is_locked(self): + def is_locked(self) -> Optional[bool]: """Return true if device is on.""" return self._state == STATE_LOCKED @property - def device_state_attributes(self): + def device_state_attributes(self) -> Optional[Dict[str, Any]]: """Who unlocked the lock and did a low battery alert fire. Reports on the previous poll cycle. @@ -78,7 +80,7 @@ class VeraLock(VeraDevice, LockEntity): return data @property - def changed_by(self): + def changed_by(self) -> Optional[str]: """Who unlocked the lock. Reports on the previous poll cycle. @@ -89,7 +91,7 @@ class VeraLock(VeraDevice, LockEntity): return last_user[0] return None - def update(self): + def update(self) -> None: """Update state by the Vera device callback.""" self._state = ( STATE_LOCKED if self.vera_device.is_locked(True) else STATE_UNLOCKED diff --git a/homeassistant/components/vera/scene.py b/homeassistant/components/vera/scene.py index c12f07c15af..8bd4473e1c8 100644 --- a/homeassistant/components/vera/scene.py +++ b/homeassistant/components/vera/scene.py @@ -1,6 +1,8 @@ """Support for Vera scenes.""" import logging -from typing import Any, Callable, List +from typing import Any, Callable, Dict, List, Optional + +import pyvera as veraApi from homeassistant.components.scene import Scene from homeassistant.config_entries import ConfigEntry @@ -29,7 +31,7 @@ async def async_setup_entry( class VeraScene(Scene): """Representation of a Vera scene entity.""" - def __init__(self, vera_scene, controller_data: ControllerData): + def __init__(self, vera_scene: veraApi.VeraScene, controller_data: ControllerData): """Initialize the scene.""" self.vera_scene = vera_scene self.controller = controller_data.controller @@ -40,7 +42,7 @@ class VeraScene(Scene): slugify(vera_scene.name), vera_scene.scene_id ) - def update(self): + def update(self) -> None: """Update the scene status.""" self.vera_scene.refresh() @@ -49,11 +51,11 @@ class VeraScene(Scene): self.vera_scene.activate() @property - def name(self): + def name(self) -> str: """Return the name of the scene.""" return self._name @property - def device_state_attributes(self): + def device_state_attributes(self) -> Optional[Dict[str, Any]]: """Return the state attributes of the scene.""" return {"vera_scene_id": self.vera_scene.vera_scene_id} diff --git a/homeassistant/components/vera/sensor.py b/homeassistant/components/vera/sensor.py index 697af6f4562..0c51094fbc0 100644 --- a/homeassistant/components/vera/sensor.py +++ b/homeassistant/components/vera/sensor.py @@ -1,7 +1,7 @@ """Support for Vera sensors.""" from datetime import timedelta import logging -from typing import Callable, List +from typing import Callable, List, Optional, cast import pyvera as veraApi @@ -35,10 +35,12 @@ async def async_setup_entry( ) -class VeraSensor(VeraDevice, Entity): +class VeraSensor(VeraDevice[veraApi.VeraSensor], Entity): """Representation of a Vera Sensor.""" - def __init__(self, vera_device, controller_data: ControllerData): + def __init__( + self, vera_device: veraApi.VeraSensor, controller_data: ControllerData + ): """Initialize the sensor.""" self.current_value = None self._temperature_units = None @@ -47,12 +49,12 @@ class VeraSensor(VeraDevice, Entity): self.entity_id = ENTITY_ID_FORMAT.format(self.vera_id) @property - def state(self): + def state(self) -> str: """Return the name of the sensor.""" return self.current_value @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> Optional[str]: """Return the unit of measurement of this entity, if any.""" if self.vera_device.category == veraApi.CATEGORY_TEMPERATURE_SENSOR: @@ -66,7 +68,7 @@ class VeraSensor(VeraDevice, Entity): if self.vera_device.category == veraApi.CATEGORY_POWER_METER: return "watts" - def update(self): + def update(self) -> None: """Update the state.""" if self.vera_device.category == veraApi.CATEGORY_TEMPERATURE_SENSOR: @@ -86,8 +88,9 @@ class VeraSensor(VeraDevice, Entity): elif self.vera_device.category == veraApi.CATEGORY_HUMIDITY_SENSOR: self.current_value = self.vera_device.humidity elif self.vera_device.category == veraApi.CATEGORY_SCENE_CONTROLLER: - value = self.vera_device.get_last_scene_id(True) - time = self.vera_device.get_last_scene_time(True) + controller = cast(veraApi.VeraSceneController, self.vera_device) + value = controller.get_last_scene_id(True) + time = controller.get_last_scene_time(True) if time == self.last_changed_time: self.current_value = None else: diff --git a/homeassistant/components/vera/switch.py b/homeassistant/components/vera/switch.py index 9e5af432ce8..9e8360bf673 100644 --- a/homeassistant/components/vera/switch.py +++ b/homeassistant/components/vera/switch.py @@ -1,6 +1,8 @@ """Support for Vera switches.""" import logging -from typing import Callable, List +from typing import Any, Callable, List, Optional + +import pyvera as veraApi from homeassistant.components.switch import ( DOMAIN as PLATFORM_DOMAIN, @@ -33,39 +35,41 @@ async def async_setup_entry( ) -class VeraSwitch(VeraDevice, SwitchEntity): +class VeraSwitch(VeraDevice[veraApi.VeraSwitch], SwitchEntity): """Representation of a Vera Switch.""" - def __init__(self, vera_device, controller_data: ControllerData): + def __init__( + self, vera_device: veraApi.VeraSwitch, controller_data: ControllerData + ): """Initialize the Vera device.""" self._state = False VeraDevice.__init__(self, vera_device, controller_data) self.entity_id = ENTITY_ID_FORMAT.format(self.vera_id) - def turn_on(self, **kwargs): + def turn_on(self, **kwargs: Any) -> None: """Turn device on.""" self.vera_device.switch_on() self._state = True self.schedule_update_ha_state() - def turn_off(self, **kwargs): + def turn_off(self, **kwargs: Any) -> None: """Turn device off.""" self.vera_device.switch_off() self._state = False self.schedule_update_ha_state() @property - def current_power_w(self): + def current_power_w(self) -> Optional[float]: """Return the current power usage in W.""" power = self.vera_device.power if power: return convert(power, float, 0.0) @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" return self._state - def update(self): + def update(self) -> None: """Update device state.""" self._state = self.vera_device.is_switched_on()