diff --git a/.strict-typing b/.strict-typing index f6a1b48bcca..9629f55c3ad 100644 --- a/.strict-typing +++ b/.strict-typing @@ -4,6 +4,7 @@ homeassistant.core homeassistant.components +homeassistant.components.abode.* homeassistant.components.acer_projector.* homeassistant.components.accuweather.* homeassistant.components.actiontec.* diff --git a/homeassistant/components/abode/__init__.py b/homeassistant/components/abode/__init__.py index 4a05b39641e..edd799d31f7 100644 --- a/homeassistant/components/abode/__init__.py +++ b/homeassistant/components/abode/__init__.py @@ -1,7 +1,10 @@ """Support for the Abode Security System.""" +from __future__ import annotations + from functools import partial -from abodepy import Abode +from abodepy import Abode, AbodeAutomation as AbodeAuto +from abodepy.devices import AbodeDevice as AbodeDev from abodepy.exceptions import AbodeAuthenticationException, AbodeException import abodepy.helpers.timeline as TIMELINE from requests.exceptions import ConnectTimeout, HTTPError @@ -18,15 +21,12 @@ from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP, Platform, ) -from homeassistant.core import HomeAssistant, ServiceCall +from homeassistant.core import Event, HomeAssistant, ServiceCall from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady -from homeassistant.helpers import config_validation as cv +from homeassistant.helpers import config_validation as cv, entity from homeassistant.helpers.dispatcher import dispatcher_send -from homeassistant.helpers.entity import DeviceInfo, Entity -from .const import ATTRIBUTION, DEFAULT_CACHEDB, DOMAIN, LOGGER - -CONF_POLLING = "polling" +from .const import ATTRIBUTION, CONF_POLLING, DEFAULT_CACHEDB, DOMAIN, LOGGER SERVICE_SETTINGS = "change_setting" SERVICE_CAPTURE_IMAGE = "capture_image" @@ -69,25 +69,25 @@ PLATFORMS = [ class AbodeSystem: """Abode System class.""" - def __init__(self, abode, polling): + def __init__(self, abode: Abode, polling: bool) -> None: """Initialize the system.""" self.abode = abode self.polling = polling - self.entity_ids = set() + self.entity_ids: set[str | None] = set() self.logout_listener = None -async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Abode integration from a config entry.""" - username = config_entry.data.get(CONF_USERNAME) - password = config_entry.data.get(CONF_PASSWORD) - polling = config_entry.data.get(CONF_POLLING) + username = entry.data[CONF_USERNAME] + password = entry.data[CONF_PASSWORD] + polling = entry.data[CONF_POLLING] cache = hass.config.path(DEFAULT_CACHEDB) # For previous config entries where unique_id is None - if config_entry.unique_id is None: + if entry.unique_id is None: hass.config_entries.async_update_entry( - config_entry, unique_id=config_entry.data[CONF_USERNAME] + entry, unique_id=entry.data[CONF_USERNAME] ) try: @@ -103,7 +103,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b hass.data[DOMAIN] = AbodeSystem(abode, polling) - hass.config_entries.async_setup_platforms(config_entry, PLATFORMS) + hass.config_entries.async_setup_platforms(entry, PLATFORMS) await setup_hass_events(hass) await hass.async_add_executor_job(setup_hass_services, hass) @@ -112,15 +112,13 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b return True -async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: +async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" hass.services.async_remove(DOMAIN, SERVICE_SETTINGS) hass.services.async_remove(DOMAIN, SERVICE_CAPTURE_IMAGE) hass.services.async_remove(DOMAIN, SERVICE_TRIGGER_AUTOMATION) - unload_ok = await hass.config_entries.async_unload_platforms( - config_entry, PLATFORMS - ) + unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) await hass.async_add_executor_job(hass.data[DOMAIN].abode.events.stop) await hass.async_add_executor_job(hass.data[DOMAIN].abode.logout) @@ -188,7 +186,7 @@ def setup_hass_services(hass: HomeAssistant) -> None: async def setup_hass_events(hass: HomeAssistant) -> None: """Home Assistant start and stop callbacks.""" - def logout(event): + def logout(event: Event) -> None: """Logout of Abode.""" if not hass.data[DOMAIN].polling: hass.data[DOMAIN].abode.events.stop() @@ -207,7 +205,7 @@ async def setup_hass_events(hass: HomeAssistant) -> None: def setup_abode_events(hass: HomeAssistant) -> None: """Event callbacks.""" - def event_callback(event, event_json): + def event_callback(event: str, event_json: dict[str, str]) -> None: """Handle an event callback from Abode.""" data = { ATTR_DEVICE_ID: event_json.get(ATTR_DEVICE_ID, ""), @@ -246,17 +244,17 @@ def setup_abode_events(hass: HomeAssistant) -> None: ) -class AbodeEntity(Entity): +class AbodeEntity(entity.Entity): """Representation of an Abode entity.""" _attr_attribution = ATTRIBUTION - def __init__(self, data): + def __init__(self, data: AbodeSystem) -> None: """Initialize Abode entity.""" self._data = data self._attr_should_poll = data.polling - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Subscribe to Abode connection status updates.""" await self.hass.async_add_executor_job( self._data.abode.events.add_connection_status_callback, @@ -266,13 +264,13 @@ class AbodeEntity(Entity): self.hass.data[DOMAIN].entity_ids.add(self.entity_id) - async def async_will_remove_from_hass(self): + async def async_will_remove_from_hass(self) -> None: """Unsubscribe from Abode connection status updates.""" await self.hass.async_add_executor_job( self._data.abode.events.remove_connection_status_callback, self.unique_id ) - def _update_connection_status(self): + def _update_connection_status(self) -> None: """Update the entity available property.""" self._attr_available = self._data.abode.events.connected self.schedule_update_ha_state() @@ -281,14 +279,14 @@ class AbodeEntity(Entity): class AbodeDevice(AbodeEntity): """Representation of an Abode device.""" - def __init__(self, data, device): + def __init__(self, data: AbodeSystem, device: AbodeDev) -> None: """Initialize Abode device.""" super().__init__(data) self._device = device self._attr_name = device.name self._attr_unique_id = device.device_uuid - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Subscribe to device events.""" await super().async_added_to_hass() await self.hass.async_add_executor_job( @@ -297,19 +295,19 @@ class AbodeDevice(AbodeEntity): self._update_callback, ) - async def async_will_remove_from_hass(self): + async def async_will_remove_from_hass(self) -> None: """Unsubscribe from device events.""" await super().async_will_remove_from_hass() await self.hass.async_add_executor_job( self._data.abode.events.remove_all_device_callbacks, self._device.device_id ) - def update(self): + def update(self) -> None: """Update device state.""" self._device.refresh() @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> dict[str, str]: """Return the state attributes.""" return { "device_id": self._device.device_id, @@ -319,16 +317,16 @@ class AbodeDevice(AbodeEntity): } @property - def device_info(self) -> DeviceInfo: + def device_info(self) -> entity.DeviceInfo: """Return device registry information for this entity.""" - return DeviceInfo( + return entity.DeviceInfo( identifiers={(DOMAIN, self._device.device_id)}, manufacturer="Abode", model=self._device.type, name=self._device.name, ) - def _update_callback(self, device): + def _update_callback(self, device: AbodeDev) -> None: """Update the device state.""" self.schedule_update_ha_state() @@ -336,7 +334,7 @@ class AbodeDevice(AbodeEntity): class AbodeAutomation(AbodeEntity): """Representation of an Abode automation.""" - def __init__(self, data, automation): + def __init__(self, data: AbodeSystem, automation: AbodeAuto) -> None: """Initialize for Abode automation.""" super().__init__(data) self._automation = automation @@ -346,6 +344,6 @@ class AbodeAutomation(AbodeEntity): "type": "CUE automation", } - def update(self): + def update(self) -> None: """Update automation state.""" self._automation.refresh() diff --git a/homeassistant/components/abode/alarm_control_panel.py b/homeassistant/components/abode/alarm_control_panel.py index 791c6ab393d..ca7f64ce28d 100644 --- a/homeassistant/components/abode/alarm_control_panel.py +++ b/homeassistant/components/abode/alarm_control_panel.py @@ -1,4 +1,8 @@ """Support for Abode Security System alarm control panels.""" +from __future__ import annotations + +from abodepy.devices.alarm import AbodeAlarm as AbodeAl + import homeassistant.components.alarm_control_panel as alarm from homeassistant.components.alarm_control_panel.const import ( SUPPORT_ALARM_ARM_AWAY, @@ -13,19 +17,17 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AbodeDevice +from . import AbodeDevice, AbodeSystem from .const import DOMAIN ICON = "mdi:security" async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Abode alarm control panel device.""" - data = hass.data[DOMAIN] + data: AbodeSystem = hass.data[DOMAIN] async_add_entities( [AbodeAlarm(data, await hass.async_add_executor_job(data.abode.get_alarm))] ) @@ -37,34 +39,33 @@ class AbodeAlarm(AbodeDevice, alarm.AlarmControlPanelEntity): _attr_icon = ICON _attr_code_arm_required = False _attr_supported_features = SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY + _device: AbodeAl @property - def state(self): + def state(self) -> str | None: """Return the state of the device.""" if self._device.is_standby: - state = STATE_ALARM_DISARMED - elif self._device.is_away: - state = STATE_ALARM_ARMED_AWAY - elif self._device.is_home: - state = STATE_ALARM_ARMED_HOME - else: - state = None - return state + return STATE_ALARM_DISARMED + if self._device.is_away: + return STATE_ALARM_ARMED_AWAY + if self._device.is_home: + return STATE_ALARM_ARMED_HOME + return None - def alarm_disarm(self, code=None): + def alarm_disarm(self, code: str | None = None) -> None: """Send disarm command.""" self._device.set_standby() - def alarm_arm_home(self, code=None): + def alarm_arm_home(self, code: str | None = None) -> None: """Send arm home command.""" self._device.set_home() - def alarm_arm_away(self, code=None): + def alarm_arm_away(self, code: str | None = None) -> None: """Send arm away command.""" self._device.set_away() @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> dict[str, str]: """Return the state attributes.""" return { "device_id": self._device.device_id, diff --git a/homeassistant/components/abode/binary_sensor.py b/homeassistant/components/abode/binary_sensor.py index 0f59f02842f..58bb101cb5d 100644 --- a/homeassistant/components/abode/binary_sensor.py +++ b/homeassistant/components/abode/binary_sensor.py @@ -1,4 +1,7 @@ """Support for Abode Security System binary sensors.""" +from typing import cast + +from abodepy.devices.binary_sensor import AbodeBinarySensor as ABBinarySensor import abodepy.helpers.constants as CONST from homeassistant.components.binary_sensor import ( @@ -9,17 +12,15 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AbodeDevice +from . import AbodeDevice, AbodeSystem from .const import DOMAIN async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Abode binary sensor devices.""" - data = hass.data[DOMAIN] + data: AbodeSystem = hass.data[DOMAIN] device_types = [ CONST.TYPE_CONNECTIVITY, @@ -40,14 +41,16 @@ async def async_setup_entry( class AbodeBinarySensor(AbodeDevice, BinarySensorEntity): """A binary sensor implementation for Abode device.""" - @property - def is_on(self): - """Return True if the binary sensor is on.""" - return self._device.is_on + _device: ABBinarySensor @property - def device_class(self): + def is_on(self) -> bool: + """Return True if the binary sensor is on.""" + return cast(bool, self._device.is_on) + + @property + def device_class(self) -> str: """Return the class of the binary sensor.""" if self._device.get_value("is_window") == "1": return BinarySensorDeviceClass.WINDOW - return self._device.generic_type + return cast(str, self._device.generic_type) diff --git a/homeassistant/components/abode/camera.py b/homeassistant/components/abode/camera.py index 05feaf214c5..9885ccb54ef 100644 --- a/homeassistant/components/abode/camera.py +++ b/homeassistant/components/abode/camera.py @@ -2,32 +2,32 @@ from __future__ import annotations from datetime import timedelta +from typing import Any, cast -import abodepy.helpers.constants as CONST +from abodepy.devices import CONST, AbodeDevice as AbodeDev +from abodepy.devices.camera import AbodeCamera as AbodeCam import abodepy.helpers.timeline as TIMELINE import requests +from requests.models import Response from homeassistant.components.camera import Camera from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant +from homeassistant.core import Event, HomeAssistant from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.util import Throttle -from . import AbodeDevice +from . import AbodeDevice, AbodeSystem from .const import DOMAIN, LOGGER MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=90) async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Abode camera devices.""" - data = hass.data[DOMAIN] - + data: AbodeSystem = hass.data[DOMAIN] entities = [] for device in data.abode.get_devices(generic_type=CONST.TYPE_CAMERA): @@ -39,14 +39,16 @@ async def async_setup_entry( class AbodeCamera(AbodeDevice, Camera): """Representation of an Abode camera.""" - def __init__(self, data, device, event): + _device: AbodeCam + + def __init__(self, data: AbodeSystem, device: AbodeDev, event: Event) -> None: """Initialize the Abode device.""" AbodeDevice.__init__(self, data, device) Camera.__init__(self) self._event = event - self._response = None + self._response: Response | None = None - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Subscribe Abode events.""" await super().async_added_to_hass() @@ -59,17 +61,17 @@ class AbodeCamera(AbodeDevice, Camera): signal = f"abode_camera_capture_{self.entity_id}" self.async_on_remove(async_dispatcher_connect(self.hass, signal, self.capture)) - def capture(self): + def capture(self) -> bool: """Request a new image capture.""" - return self._device.capture() + return cast(bool, self._device.capture()) @Throttle(MIN_TIME_BETWEEN_UPDATES) - def refresh_image(self): + def refresh_image(self) -> None: """Find a new image on the timeline.""" if self._device.refresh_image(): self.get_image() - def get_image(self): + def get_image(self) -> None: """Attempt to download the most recent capture.""" if self._device.image_url: try: @@ -93,21 +95,21 @@ class AbodeCamera(AbodeDevice, Camera): return None - def turn_on(self): + def turn_on(self) -> None: """Turn on camera.""" self._device.privacy_mode(False) - def turn_off(self): + def turn_off(self) -> None: """Turn off camera.""" self._device.privacy_mode(True) - def _capture_callback(self, capture): + def _capture_callback(self, capture: Any) -> None: """Update the image with the device then refresh device.""" self._device.update_image_location(capture) self.get_image() self.schedule_update_ha_state() @property - def is_on(self): + def is_on(self) -> bool: """Return true if on.""" - return self._device.is_on + return cast(bool, self._device.is_on) diff --git a/homeassistant/components/abode/config_flow.py b/homeassistant/components/abode/config_flow.py index 0c22766e373..715bc53e2b2 100644 --- a/homeassistant/components/abode/config_flow.py +++ b/homeassistant/components/abode/config_flow.py @@ -1,5 +1,8 @@ """Config flow for the Abode Security System component.""" +from __future__ import annotations + from http import HTTPStatus +from typing import Any, cast from abodepy import Abode from abodepy.exceptions import AbodeAuthenticationException, AbodeException @@ -9,11 +12,11 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.data_entry_flow import FlowResult -from .const import DEFAULT_CACHEDB, DOMAIN, LOGGER +from .const import CONF_POLLING, DEFAULT_CACHEDB, DOMAIN, LOGGER CONF_MFA = "mfa_code" -CONF_POLLING = "polling" class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): @@ -21,7 +24,7 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 - def __init__(self): + def __init__(self) -> None: """Initialize.""" self.data_schema = { vol.Required(CONF_USERNAME): str, @@ -31,13 +34,13 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): vol.Required(CONF_MFA): str, } - self._cache = None - self._mfa_code = None - self._password = None - self._polling = False - self._username = None + self._cache: str | None = None + self._mfa_code: str | None = None + self._password: str | None = None + self._polling: bool = False + self._username: str | None = None - async def _async_abode_login(self, step_id): + async def _async_abode_login(self, step_id: str) -> FlowResult: """Handle login with Abode.""" self._cache = self.hass.config.path(DEFAULT_CACHEDB) errors = {} @@ -47,7 +50,7 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): Abode, self._username, self._password, True, False, False, self._cache ) - except (AbodeException, ConnectTimeout, HTTPError) as ex: + except AbodeException as ex: if ex.errcode == MFA_CODE_REQUIRED[0]: return await self.async_step_mfa() @@ -59,6 +62,9 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): else: errors = {"base": "cannot_connect"} + except (ConnectTimeout, HTTPError): + errors = {"base": "cannot_connect"} + if errors: return self.async_show_form( step_id=step_id, data_schema=vol.Schema(self.data_schema), errors=errors @@ -66,7 +72,7 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return await self._async_create_entry() - async def _async_abode_mfa_login(self): + async def _async_abode_mfa_login(self) -> FlowResult: """Handle multi-factor authentication (MFA) login with Abode.""" try: # Create instance to access login method for passing MFA code @@ -89,7 +95,7 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return await self._async_create_entry() - async def _async_create_entry(self): + async def _async_create_entry(self) -> FlowResult: """Create the config entry.""" config_data = { CONF_USERNAME: self._username, @@ -109,9 +115,13 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return self.async_abort(reason="reauth_successful") - return self.async_create_entry(title=self._username, data=config_data) + return self.async_create_entry( + title=cast(str, self._username), data=config_data + ) - async def async_step_user(self, user_input=None): + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle a flow initialized by the user.""" if self._async_current_entries(): return self.async_abort(reason="single_instance_allowed") @@ -126,7 +136,9 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return await self._async_abode_login(step_id="user") - async def async_step_mfa(self, user_input=None): + async def async_step_mfa( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle a multi-factor authentication (MFA) flow.""" if user_input is None: return self.async_show_form( @@ -137,13 +149,15 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return await self._async_abode_mfa_login() - async def async_step_reauth(self, config): + async def async_step_reauth(self, config: dict[str, Any]) -> FlowResult: """Handle reauthorization request from Abode.""" self._username = config[CONF_USERNAME] return await self.async_step_reauth_confirm() - async def async_step_reauth_confirm(self, user_input=None): + async def async_step_reauth_confirm( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle reauthorization flow.""" if user_input is None: return self.async_show_form( diff --git a/homeassistant/components/abode/const.py b/homeassistant/components/abode/const.py index b509984876b..e6b048059a1 100644 --- a/homeassistant/components/abode/const.py +++ b/homeassistant/components/abode/const.py @@ -7,3 +7,4 @@ DOMAIN = "abode" ATTRIBUTION = "Data provided by goabode.com" DEFAULT_CACHEDB = "abodepy_cache.pickle" +CONF_POLLING = "polling" diff --git a/homeassistant/components/abode/cover.py b/homeassistant/components/abode/cover.py index 6eb65296c2d..7943056f8ac 100644 --- a/homeassistant/components/abode/cover.py +++ b/homeassistant/components/abode/cover.py @@ -1,4 +1,7 @@ """Support for Abode Security System covers.""" +from typing import Any + +from abodepy.devices.cover import AbodeCover as AbodeCV import abodepy.helpers.constants as CONST from homeassistant.components.cover import CoverEntity @@ -6,17 +9,15 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AbodeDevice +from . import AbodeDevice, AbodeSystem from .const import DOMAIN async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Abode cover devices.""" - data = hass.data[DOMAIN] + data: AbodeSystem = hass.data[DOMAIN] entities = [] @@ -29,15 +30,17 @@ async def async_setup_entry( class AbodeCover(AbodeDevice, CoverEntity): """Representation of an Abode cover.""" + _device: AbodeCV + @property - def is_closed(self): + def is_closed(self) -> bool: """Return true if cover is closed, else False.""" return not self._device.is_open - def close_cover(self, **kwargs): + def close_cover(self, **kwargs: Any) -> None: """Issue close command to cover.""" self._device.close_cover() - def open_cover(self, **kwargs): + def open_cover(self, **kwargs: Any) -> None: """Issue open command to cover.""" self._device.open_cover() diff --git a/homeassistant/components/abode/light.py b/homeassistant/components/abode/light.py index 7f90137d0f7..f998e21510d 100644 --- a/homeassistant/components/abode/light.py +++ b/homeassistant/components/abode/light.py @@ -1,6 +1,10 @@ """Support for Abode Security System lights.""" -from math import ceil +from __future__ import annotations +from math import ceil +from typing import Any + +from abodepy.devices.light import AbodeLight as AbodeLT import abodepy.helpers.constants as CONST from homeassistant.components.light import ( @@ -20,17 +24,15 @@ from homeassistant.util.color import ( color_temperature_mired_to_kelvin, ) -from . import AbodeDevice +from . import AbodeDevice, AbodeSystem from .const import DOMAIN async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Abode light devices.""" - data = hass.data[DOMAIN] + data: AbodeSystem = hass.data[DOMAIN] entities = [] @@ -43,7 +45,9 @@ async def async_setup_entry( class AbodeLight(AbodeDevice, LightEntity): """Representation of an Abode light.""" - def turn_on(self, **kwargs): + _device: AbodeLT + + def turn_on(self, **kwargs: Any) -> None: """Turn on the light.""" if ATTR_COLOR_TEMP in kwargs and self._device.is_color_capable: self._device.set_color_temp( @@ -63,40 +67,42 @@ class AbodeLight(AbodeDevice, LightEntity): self._device.switch_on() - def turn_off(self, **kwargs): + def turn_off(self, **kwargs: Any) -> None: """Turn off the light.""" self._device.switch_off() @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" - return self._device.is_on + return bool(self._device.is_on) @property - def brightness(self): + def brightness(self) -> int | None: """Return the brightness of the light.""" if self._device.is_dimmable and self._device.has_brightness: brightness = int(self._device.brightness) # Abode returns 100 during device initialization and device refresh - if brightness == 100: - return 255 # Convert Abode brightness (0-99) to Home Assistant brightness (0-255) - return ceil(brightness * 255 / 99.0) + return 255 if brightness == 100 else ceil(brightness * 255 / 99.0) + return None @property - def color_temp(self): + def color_temp(self) -> int | None: """Return the color temp of the light.""" if self._device.has_color: return color_temperature_kelvin_to_mired(self._device.color_temp) + return None @property - def hs_color(self): + def hs_color(self) -> tuple[float, float] | None: """Return the color of the light.""" + _hs = None if self._device.has_color: - return self._device.color + _hs = self._device.color + return _hs @property - def supported_features(self): + def supported_features(self) -> int: """Flag supported features.""" if self._device.is_dimmable and self._device.is_color_capable: return SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_COLOR_TEMP diff --git a/homeassistant/components/abode/lock.py b/homeassistant/components/abode/lock.py index f766ef88c2c..368769003b0 100644 --- a/homeassistant/components/abode/lock.py +++ b/homeassistant/components/abode/lock.py @@ -1,4 +1,7 @@ """Support for the Abode Security System locks.""" +from typing import Any + +from abodepy.devices.lock import AbodeLock as AbodeLK import abodepy.helpers.constants as CONST from homeassistant.components.lock import LockEntity @@ -6,17 +9,15 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AbodeDevice +from . import AbodeDevice, AbodeSystem from .const import DOMAIN async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Abode lock devices.""" - data = hass.data[DOMAIN] + data: AbodeSystem = hass.data[DOMAIN] entities = [] @@ -29,15 +30,17 @@ async def async_setup_entry( class AbodeLock(AbodeDevice, LockEntity): """Representation of an Abode lock.""" - def lock(self, **kwargs): + _device: AbodeLK + + def lock(self, **kwargs: Any) -> None: """Lock the device.""" self._device.lock() - def unlock(self, **kwargs): + def unlock(self, **kwargs: Any) -> None: """Unlock the device.""" self._device.unlock() @property - def is_locked(self): + def is_locked(self) -> bool: """Return true if device is on.""" - return self._device.is_locked + return bool(self._device.is_locked) diff --git a/homeassistant/components/abode/sensor.py b/homeassistant/components/abode/sensor.py index f415036aff8..2564b775cf9 100644 --- a/homeassistant/components/abode/sensor.py +++ b/homeassistant/components/abode/sensor.py @@ -1,7 +1,9 @@ """Support for Abode Security System sensors.""" from __future__ import annotations -import abodepy.helpers.constants as CONST +from typing import cast + +from abodepy.devices.sensor import CONST, AbodeSensor as AbodeSense from homeassistant.components.sensor import ( SensorDeviceClass, @@ -12,7 +14,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AbodeDevice +from . import AbodeDevice, AbodeSystem from .const import DOMAIN SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( @@ -35,12 +37,10 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Abode sensor devices.""" - data = hass.data[DOMAIN] + data: AbodeSystem = hass.data[DOMAIN] entities = [] @@ -60,7 +60,14 @@ async def async_setup_entry( class AbodeSensor(AbodeDevice, SensorEntity): """A sensor implementation for Abode devices.""" - def __init__(self, data, device, description: SensorEntityDescription): + _device: AbodeSense + + def __init__( + self, + data: AbodeSystem, + device: AbodeSense, + description: SensorEntityDescription, + ) -> None: """Initialize a sensor for an Abode device.""" super().__init__(data, device) self.entity_description = description @@ -74,11 +81,12 @@ class AbodeSensor(AbodeDevice, SensorEntity): self._attr_native_unit_of_measurement = device.lux_unit @property - def native_value(self): + def native_value(self) -> float | None: """Return the state of the sensor.""" if self.entity_description.key == CONST.TEMP_STATUS_KEY: - return self._device.temp + return cast(float, self._device.temp) if self.entity_description.key == CONST.HUMI_STATUS_KEY: - return self._device.humidity + return cast(float, self._device.humidity) if self.entity_description.key == CONST.LUX_STATUS_KEY: - return self._device.lux + return cast(float, self._device.lux) + return None diff --git a/homeassistant/components/abode/switch.py b/homeassistant/components/abode/switch.py index aacfb46d287..5ed32b4f83c 100644 --- a/homeassistant/components/abode/switch.py +++ b/homeassistant/components/abode/switch.py @@ -1,7 +1,9 @@ """Support for Abode Security System switches.""" from __future__ import annotations -import abodepy.helpers.constants as CONST +from typing import Any, cast + +from abodepy.devices.switch import CONST, AbodeSwitch as AbodeSW from homeassistant.components.switch import SwitchEntity from homeassistant.config_entries import ConfigEntry @@ -9,7 +11,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AbodeAutomation, AbodeDevice +from . import AbodeAutomation, AbodeDevice, AbodeSystem from .const import DOMAIN DEVICE_TYPES = [CONST.TYPE_SWITCH, CONST.TYPE_VALVE] @@ -18,12 +20,10 @@ ICON = "mdi:robot" async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Abode switch devices.""" - data = hass.data[DOMAIN] + data: AbodeSystem = hass.data[DOMAIN] entities: list[SwitchEntity] = [] @@ -40,18 +40,20 @@ async def async_setup_entry( class AbodeSwitch(AbodeDevice, SwitchEntity): """Representation of an Abode switch.""" - def turn_on(self, **kwargs): + _device: AbodeSW + + def turn_on(self, **kwargs: Any) -> None: """Turn on the device.""" self._device.switch_on() - def turn_off(self, **kwargs): + def turn_off(self, **kwargs: Any) -> None: """Turn off the device.""" self._device.switch_off() @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" - return self._device.is_on + return cast(bool, self._device.is_on) class AbodeAutomationSwitch(AbodeAutomation, SwitchEntity): @@ -59,28 +61,28 @@ class AbodeAutomationSwitch(AbodeAutomation, SwitchEntity): _attr_icon = ICON - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Set up trigger automation service.""" await super().async_added_to_hass() signal = f"abode_trigger_automation_{self.entity_id}" self.async_on_remove(async_dispatcher_connect(self.hass, signal, self.trigger)) - def turn_on(self, **kwargs): + def turn_on(self, **kwargs: Any) -> None: """Enable the automation.""" if self._automation.enable(True): self.schedule_update_ha_state() - def turn_off(self, **kwargs): + def turn_off(self, **kwargs: Any) -> None: """Disable the automation.""" if self._automation.enable(False): self.schedule_update_ha_state() - def trigger(self): + def trigger(self) -> None: """Trigger the automation.""" self._automation.trigger() @property - def is_on(self): + def is_on(self) -> bool: """Return True if the automation is enabled.""" - return self._automation.is_enabled + return bool(self._automation.is_enabled) diff --git a/mypy.ini b/mypy.ini index 0fa832130e8..a91bbe59f40 100644 --- a/mypy.ini +++ b/mypy.ini @@ -47,6 +47,17 @@ no_implicit_optional = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.abode.*] +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.acer_projector.*] check_untyped_defs = true disallow_incomplete_defs = true diff --git a/tests/components/abode/common.py b/tests/components/abode/common.py index c134552ccd4..dd9b889fe27 100644 --- a/tests/components/abode/common.py +++ b/tests/components/abode/common.py @@ -2,17 +2,23 @@ from unittest.mock import patch from homeassistant.components.abode import DOMAIN as ABODE_DOMAIN +from homeassistant.components.abode.const import CONF_POLLING from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component from tests.common import MockConfigEntry -async def setup_platform(hass, platform): +async def setup_platform(hass: HomeAssistant, platform: str) -> MockConfigEntry: """Set up the Abode platform.""" mock_entry = MockConfigEntry( domain=ABODE_DOMAIN, - data={CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"}, + data={ + CONF_USERNAME: "user@email.com", + CONF_PASSWORD: "password", + CONF_POLLING: False, + }, ) mock_entry.add_to_hass(hass) diff --git a/tests/components/abode/conftest.py b/tests/components/abode/conftest.py index 472587781ca..e41cf3ec587 100644 --- a/tests/components/abode/conftest.py +++ b/tests/components/abode/conftest.py @@ -7,7 +7,7 @@ from tests.components.light.conftest import mock_light_profiles # noqa: F401 @pytest.fixture(autouse=True) -def requests_mock_fixture(requests_mock): +def requests_mock_fixture(requests_mock) -> None: """Fixture to provide a requests mocker.""" # Mocks the login response for abodepy. requests_mock.post(CONST.LOGIN_URL, text=load_fixture("login.json", "abode")) diff --git a/tests/components/abode/test_alarm_control_panel.py b/tests/components/abode/test_alarm_control_panel.py index 55ff22b9ee3..74d64731128 100644 --- a/tests/components/abode/test_alarm_control_panel.py +++ b/tests/components/abode/test_alarm_control_panel.py @@ -16,6 +16,7 @@ from homeassistant.const import ( STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, ) +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .common import setup_platform @@ -23,7 +24,7 @@ from .common import setup_platform DEVICE_ID = "alarm_control_panel.abode_alarm" -async def test_entity_registry(hass): +async def test_entity_registry(hass: HomeAssistant) -> None: """Tests that the devices are registered in the entity registry.""" await setup_platform(hass, ALARM_DOMAIN) entity_registry = er.async_get(hass) @@ -33,7 +34,7 @@ async def test_entity_registry(hass): assert entry.unique_id == "001122334455" -async def test_attributes(hass): +async def test_attributes(hass: HomeAssistant) -> None: """Test the alarm control panel attributes are correct.""" await setup_platform(hass, ALARM_DOMAIN) @@ -46,7 +47,7 @@ async def test_attributes(hass): assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 3 -async def test_set_alarm_away(hass): +async def test_set_alarm_away(hass: HomeAssistant) -> None: """Test the alarm control panel can be set to away.""" with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback: with patch("abodepy.ALARM.AbodeAlarm.set_away") as mock_set_away: @@ -75,7 +76,7 @@ async def test_set_alarm_away(hass): assert state.state == STATE_ALARM_ARMED_AWAY -async def test_set_alarm_home(hass): +async def test_set_alarm_home(hass: HomeAssistant) -> None: """Test the alarm control panel can be set to home.""" with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback: with patch("abodepy.ALARM.AbodeAlarm.set_home") as mock_set_home: @@ -103,7 +104,7 @@ async def test_set_alarm_home(hass): assert state.state == STATE_ALARM_ARMED_HOME -async def test_set_alarm_standby(hass): +async def test_set_alarm_standby(hass: HomeAssistant) -> None: """Test the alarm control panel can be set to standby.""" with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback: with patch("abodepy.ALARM.AbodeAlarm.set_standby") as mock_set_standby: @@ -130,7 +131,7 @@ async def test_set_alarm_standby(hass): assert state.state == STATE_ALARM_DISARMED -async def test_state_unknown(hass): +async def test_state_unknown(hass: HomeAssistant) -> None: """Test an unknown alarm control panel state.""" with patch("abodepy.ALARM.AbodeAlarm.mode", new_callable=PropertyMock) as mock_mode: await setup_platform(hass, ALARM_DOMAIN) diff --git a/tests/components/abode/test_binary_sensor.py b/tests/components/abode/test_binary_sensor.py index d8f19a19b77..6d7ffec438b 100644 --- a/tests/components/abode/test_binary_sensor.py +++ b/tests/components/abode/test_binary_sensor.py @@ -11,12 +11,13 @@ from homeassistant.const import ( ATTR_FRIENDLY_NAME, STATE_OFF, ) +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .common import setup_platform -async def test_entity_registry(hass): +async def test_entity_registry(hass: HomeAssistant) -> None: """Tests that the devices are registered in the entity registry.""" await setup_platform(hass, BINARY_SENSOR_DOMAIN) entity_registry = er.async_get(hass) @@ -25,7 +26,7 @@ async def test_entity_registry(hass): assert entry.unique_id == "2834013428b6035fba7d4054aa7b25a3" -async def test_attributes(hass): +async def test_attributes(hass: HomeAssistant) -> None: """Test the binary sensor attributes are correct.""" await setup_platform(hass, BINARY_SENSOR_DOMAIN) diff --git a/tests/components/abode/test_camera.py b/tests/components/abode/test_camera.py index 7dc943a0a74..fd490c4a1c2 100644 --- a/tests/components/abode/test_camera.py +++ b/tests/components/abode/test_camera.py @@ -4,12 +4,13 @@ from unittest.mock import patch from homeassistant.components.abode.const import DOMAIN as ABODE_DOMAIN from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN from homeassistant.const import ATTR_ENTITY_ID, STATE_IDLE +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .common import setup_platform -async def test_entity_registry(hass): +async def test_entity_registry(hass: HomeAssistant) -> None: """Tests that the devices are registered in the entity registry.""" await setup_platform(hass, CAMERA_DOMAIN) entity_registry = er.async_get(hass) @@ -18,7 +19,7 @@ async def test_entity_registry(hass): assert entry.unique_id == "d0a3a1c316891ceb00c20118aae2a133" -async def test_attributes(hass): +async def test_attributes(hass: HomeAssistant) -> None: """Test the camera attributes are correct.""" await setup_platform(hass, CAMERA_DOMAIN) @@ -26,7 +27,7 @@ async def test_attributes(hass): assert state.state == STATE_IDLE -async def test_capture_image(hass): +async def test_capture_image(hass: HomeAssistant) -> None: """Test the camera capture image service.""" await setup_platform(hass, CAMERA_DOMAIN) @@ -41,7 +42,7 @@ async def test_capture_image(hass): mock_capture.assert_called_once() -async def test_camera_on(hass): +async def test_camera_on(hass: HomeAssistant) -> None: """Test the camera turn on service.""" await setup_platform(hass, CAMERA_DOMAIN) @@ -56,7 +57,7 @@ async def test_camera_on(hass): mock_capture.assert_called_once_with(False) -async def test_camera_off(hass): +async def test_camera_off(hass: HomeAssistant) -> None: """Test the camera turn off service.""" await setup_platform(hass, CAMERA_DOMAIN) diff --git a/tests/components/abode/test_config_flow.py b/tests/components/abode/test_config_flow.py index 44582692c73..adbea237d34 100644 --- a/tests/components/abode/test_config_flow.py +++ b/tests/components/abode/test_config_flow.py @@ -4,19 +4,19 @@ from unittest.mock import patch from abodepy.exceptions import AbodeAuthenticationException from abodepy.helpers.errors import MFA_CODE_REQUIRED +from requests.exceptions import ConnectTimeout from homeassistant import data_entry_flow from homeassistant.components.abode import config_flow -from homeassistant.components.abode.const import DOMAIN +from homeassistant.components.abode.const import CONF_POLLING, DOMAIN from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry -CONF_POLLING = "polling" - -async def test_show_form(hass): +async def test_show_form(hass: HomeAssistant) -> None: """Test that the form is served with no input.""" flow = config_flow.AbodeFlowHandler() flow.hass = hass @@ -27,7 +27,7 @@ async def test_show_form(hass): assert result["step_id"] == "user" -async def test_one_config_allowed(hass): +async def test_one_config_allowed(hass: HomeAssistant) -> None: """Test that only one Abode configuration is allowed.""" flow = config_flow.AbodeFlowHandler() flow.hass = hass @@ -43,7 +43,7 @@ async def test_one_config_allowed(hass): assert step_user_result["reason"] == "single_instance_allowed" -async def test_invalid_credentials(hass): +async def test_invalid_credentials(hass: HomeAssistant) -> None: """Test that invalid credentials throws an error.""" conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} @@ -60,7 +60,7 @@ async def test_invalid_credentials(hass): assert result["errors"] == {"base": "invalid_auth"} -async def test_connection_error(hass): +async def test_connection_auth_error(hass: HomeAssistant) -> None: """Test other than invalid credentials throws an error.""" conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} @@ -77,7 +77,22 @@ async def test_connection_error(hass): assert result["errors"] == {"base": "cannot_connect"} -async def test_step_user(hass): +async def test_connection_error(hass: HomeAssistant) -> None: + """Test login throws an error if connection times out.""" + conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} + + flow = config_flow.AbodeFlowHandler() + flow.hass = hass + + with patch( + "homeassistant.components.abode.config_flow.Abode", + side_effect=ConnectTimeout, + ): + result = await flow.async_step_user(user_input=conf) + assert result["errors"] == {"base": "cannot_connect"} + + +async def test_step_user(hass: HomeAssistant) -> None: """Test that the user step works.""" conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} @@ -98,7 +113,7 @@ async def test_step_user(hass): } -async def test_step_mfa(hass): +async def test_step_mfa(hass: HomeAssistant) -> None: """Test that the MFA step works.""" conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} @@ -141,7 +156,7 @@ async def test_step_mfa(hass): } -async def test_step_reauth(hass): +async def test_step_reauth(hass: HomeAssistant) -> None: """Test the reauth flow.""" conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} diff --git a/tests/components/abode/test_cover.py b/tests/components/abode/test_cover.py index edd40a86707..bd7104bff3f 100644 --- a/tests/components/abode/test_cover.py +++ b/tests/components/abode/test_cover.py @@ -10,6 +10,7 @@ from homeassistant.const import ( SERVICE_OPEN_COVER, STATE_CLOSED, ) +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .common import setup_platform @@ -17,7 +18,7 @@ from .common import setup_platform DEVICE_ID = "cover.garage_door" -async def test_entity_registry(hass): +async def test_entity_registry(hass: HomeAssistant) -> None: """Tests that the devices are registered in the entity registry.""" await setup_platform(hass, COVER_DOMAIN) entity_registry = er.async_get(hass) @@ -26,7 +27,7 @@ async def test_entity_registry(hass): assert entry.unique_id == "61cbz3b542d2o33ed2fz02721bda3324" -async def test_attributes(hass): +async def test_attributes(hass: HomeAssistant) -> None: """Test the cover attributes are correct.""" await setup_platform(hass, COVER_DOMAIN) @@ -39,7 +40,7 @@ async def test_attributes(hass): assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Garage Door" -async def test_open(hass): +async def test_open(hass: HomeAssistant) -> None: """Test the cover can be opened.""" await setup_platform(hass, COVER_DOMAIN) @@ -51,7 +52,7 @@ async def test_open(hass): mock_open.assert_called_once() -async def test_close(hass): +async def test_close(hass: HomeAssistant) -> None: """Test the cover can be closed.""" await setup_platform(hass, COVER_DOMAIN) diff --git a/tests/components/abode/test_init.py b/tests/components/abode/test_init.py index 130f0c6791e..32bb8bf7c70 100644 --- a/tests/components/abode/test_init.py +++ b/tests/components/abode/test_init.py @@ -14,11 +14,12 @@ from homeassistant.components.abode import ( from homeassistant.components.alarm_control_panel import DOMAIN as ALARM_DOMAIN from homeassistant.config_entries import ConfigEntryState from homeassistant.const import CONF_USERNAME +from homeassistant.core import HomeAssistant from .common import setup_platform -async def test_change_settings(hass): +async def test_change_settings(hass: HomeAssistant) -> None: """Test change_setting service.""" await setup_platform(hass, ALARM_DOMAIN) @@ -33,7 +34,7 @@ async def test_change_settings(hass): mock_set_setting.assert_called_once() -async def test_add_unique_id(hass): +async def test_add_unique_id(hass: HomeAssistant) -> None: """Test unique_id is set to Abode username.""" mock_entry = await setup_platform(hass, ALARM_DOMAIN) # Set unique_id to None to match previous config entries @@ -49,7 +50,7 @@ async def test_add_unique_id(hass): assert mock_entry.unique_id == mock_entry.data[CONF_USERNAME] -async def test_unload_entry(hass): +async def test_unload_entry(hass: HomeAssistant) -> None: """Test unloading the Abode entry.""" mock_entry = await setup_platform(hass, ALARM_DOMAIN) @@ -65,7 +66,7 @@ async def test_unload_entry(hass): assert not hass.services.has_service(ABODE_DOMAIN, SERVICE_TRIGGER_AUTOMATION) -async def test_invalid_credentials(hass): +async def test_invalid_credentials(hass: HomeAssistant) -> None: """Test Abode credentials changing.""" with patch( "homeassistant.components.abode.Abode", @@ -81,7 +82,7 @@ async def test_invalid_credentials(hass): mock_async_step_reauth.assert_called_once() -async def test_raise_config_entry_not_ready_when_offline(hass): +async def test_raise_config_entry_not_ready_when_offline(hass: HomeAssistant) -> None: """Config entry state is SETUP_RETRY when abode is offline.""" with patch( "homeassistant.components.abode.Abode", diff --git a/tests/components/abode/test_light.py b/tests/components/abode/test_light.py index b5160aece2a..d27a07227d0 100644 --- a/tests/components/abode/test_light.py +++ b/tests/components/abode/test_light.py @@ -16,6 +16,7 @@ from homeassistant.const import ( SERVICE_TURN_ON, STATE_ON, ) +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .common import setup_platform @@ -23,7 +24,7 @@ from .common import setup_platform DEVICE_ID = "light.living_room_lamp" -async def test_entity_registry(hass): +async def test_entity_registry(hass: HomeAssistant) -> None: """Tests that the devices are registered in the entity registry.""" await setup_platform(hass, LIGHT_DOMAIN) entity_registry = er.async_get(hass) @@ -32,7 +33,7 @@ async def test_entity_registry(hass): assert entry.unique_id == "741385f4388b2637df4c6b398fe50581" -async def test_attributes(hass): +async def test_attributes(hass: HomeAssistant) -> None: """Test the light attributes are correct.""" await setup_platform(hass, LIGHT_DOMAIN) @@ -49,7 +50,7 @@ async def test_attributes(hass): assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 19 -async def test_switch_off(hass): +async def test_switch_off(hass: HomeAssistant) -> None: """Test the light can be turned off.""" await setup_platform(hass, LIGHT_DOMAIN) @@ -61,7 +62,7 @@ async def test_switch_off(hass): mock_switch_off.assert_called_once() -async def test_switch_on(hass): +async def test_switch_on(hass: HomeAssistant) -> None: """Test the light can be turned on.""" await setup_platform(hass, LIGHT_DOMAIN) @@ -73,7 +74,7 @@ async def test_switch_on(hass): mock_switch_on.assert_called_once() -async def test_set_brightness(hass): +async def test_set_brightness(hass: HomeAssistant) -> None: """Test the brightness can be set.""" await setup_platform(hass, LIGHT_DOMAIN) @@ -89,7 +90,7 @@ async def test_set_brightness(hass): mock_set_level.assert_called_once_with(39) -async def test_set_color(hass): +async def test_set_color(hass: HomeAssistant) -> None: """Test the color can be set.""" await setup_platform(hass, LIGHT_DOMAIN) @@ -104,7 +105,7 @@ async def test_set_color(hass): mock_set_color.assert_called_once_with((240.0, 100.0)) -async def test_set_color_temp(hass): +async def test_set_color_temp(hass: HomeAssistant) -> None: """Test the color temp can be set.""" await setup_platform(hass, LIGHT_DOMAIN) diff --git a/tests/components/abode/test_lock.py b/tests/components/abode/test_lock.py index c688b6f02bc..837b62e06cd 100644 --- a/tests/components/abode/test_lock.py +++ b/tests/components/abode/test_lock.py @@ -10,6 +10,7 @@ from homeassistant.const import ( SERVICE_UNLOCK, STATE_LOCKED, ) +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .common import setup_platform @@ -17,7 +18,7 @@ from .common import setup_platform DEVICE_ID = "lock.test_lock" -async def test_entity_registry(hass): +async def test_entity_registry(hass: HomeAssistant) -> None: """Tests that the devices are registered in the entity registry.""" await setup_platform(hass, LOCK_DOMAIN) entity_registry = er.async_get(hass) @@ -26,7 +27,7 @@ async def test_entity_registry(hass): assert entry.unique_id == "51cab3b545d2o34ed7fz02731bda5324" -async def test_attributes(hass): +async def test_attributes(hass: HomeAssistant) -> None: """Test the lock attributes are correct.""" await setup_platform(hass, LOCK_DOMAIN) @@ -39,7 +40,7 @@ async def test_attributes(hass): assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Test Lock" -async def test_lock(hass): +async def test_lock(hass: HomeAssistant) -> None: """Test the lock can be locked.""" await setup_platform(hass, LOCK_DOMAIN) @@ -51,7 +52,7 @@ async def test_lock(hass): mock_lock.assert_called_once() -async def test_unlock(hass): +async def test_unlock(hass: HomeAssistant) -> None: """Test the lock can be unlocked.""" await setup_platform(hass, LOCK_DOMAIN) diff --git a/tests/components/abode/test_sensor.py b/tests/components/abode/test_sensor.py index 3d68e4d3d8a..ba163ba87d9 100644 --- a/tests/components/abode/test_sensor.py +++ b/tests/components/abode/test_sensor.py @@ -8,12 +8,13 @@ from homeassistant.const import ( PERCENTAGE, TEMP_CELSIUS, ) +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .common import setup_platform -async def test_entity_registry(hass): +async def test_entity_registry(hass: HomeAssistant) -> None: """Tests that the devices are registered in the entity registry.""" await setup_platform(hass, SENSOR_DOMAIN) entity_registry = er.async_get(hass) @@ -22,7 +23,7 @@ async def test_entity_registry(hass): assert entry.unique_id == "13545b21f4bdcd33d9abd461f8443e65-humidity" -async def test_attributes(hass): +async def test_attributes(hass: HomeAssistant) -> None: """Test the sensor attributes are correct.""" await setup_platform(hass, SENSOR_DOMAIN) diff --git a/tests/components/abode/test_switch.py b/tests/components/abode/test_switch.py index 829c5e8ae37..74fa6491f66 100644 --- a/tests/components/abode/test_switch.py +++ b/tests/components/abode/test_switch.py @@ -13,6 +13,7 @@ from homeassistant.const import ( STATE_OFF, STATE_ON, ) +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .common import setup_platform @@ -23,7 +24,7 @@ DEVICE_ID = "switch.test_switch" DEVICE_UID = "0012a4d3614cb7e2b8c9abea31d2fb2a" -async def test_entity_registry(hass): +async def test_entity_registry(hass: HomeAssistant) -> None: """Tests that the devices are registered in the entity registry.""" await setup_platform(hass, SWITCH_DOMAIN) entity_registry = er.async_get(hass) @@ -35,7 +36,7 @@ async def test_entity_registry(hass): assert entry.unique_id == DEVICE_UID -async def test_attributes(hass): +async def test_attributes(hass: HomeAssistant) -> None: """Test the switch attributes are correct.""" await setup_platform(hass, SWITCH_DOMAIN) @@ -43,7 +44,7 @@ async def test_attributes(hass): assert state.state == STATE_OFF -async def test_switch_on(hass): +async def test_switch_on(hass: HomeAssistant) -> None: """Test the switch can be turned on.""" await setup_platform(hass, SWITCH_DOMAIN) @@ -56,7 +57,7 @@ async def test_switch_on(hass): mock_switch_on.assert_called_once() -async def test_switch_off(hass): +async def test_switch_off(hass: HomeAssistant) -> None: """Test the switch can be turned off.""" await setup_platform(hass, SWITCH_DOMAIN) @@ -69,7 +70,7 @@ async def test_switch_off(hass): mock_switch_off.assert_called_once() -async def test_automation_attributes(hass): +async def test_automation_attributes(hass: HomeAssistant) -> None: """Test the automation attributes are correct.""" await setup_platform(hass, SWITCH_DOMAIN) @@ -78,7 +79,7 @@ async def test_automation_attributes(hass): assert state.state == STATE_ON -async def test_turn_automation_off(hass): +async def test_turn_automation_off(hass: HomeAssistant) -> None: """Test the automation can be turned off.""" with patch("abodepy.AbodeAutomation.enable") as mock_trigger: await setup_platform(hass, SWITCH_DOMAIN) @@ -94,7 +95,7 @@ async def test_turn_automation_off(hass): mock_trigger.assert_called_once_with(False) -async def test_turn_automation_on(hass): +async def test_turn_automation_on(hass: HomeAssistant) -> None: """Test the automation can be turned on.""" with patch("abodepy.AbodeAutomation.enable") as mock_trigger: await setup_platform(hass, SWITCH_DOMAIN) @@ -110,7 +111,7 @@ async def test_turn_automation_on(hass): mock_trigger.assert_called_once_with(True) -async def test_trigger_automation(hass, requests_mock): +async def test_trigger_automation(hass: HomeAssistant) -> None: """Test the trigger automation service.""" await setup_platform(hass, SWITCH_DOMAIN)