Add strict typing to abode (#57673)

This commit is contained in:
Robert Hillis 2022-01-10 09:54:09 -05:00 committed by GitHub
parent bc2f4e82e3
commit 7c51d2f159
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 304 additions and 221 deletions

View File

@ -4,6 +4,7 @@
homeassistant.core homeassistant.core
homeassistant.components homeassistant.components
homeassistant.components.abode.*
homeassistant.components.acer_projector.* homeassistant.components.acer_projector.*
homeassistant.components.accuweather.* homeassistant.components.accuweather.*
homeassistant.components.actiontec.* homeassistant.components.actiontec.*

View File

@ -1,7 +1,10 @@
"""Support for the Abode Security System.""" """Support for the Abode Security System."""
from __future__ import annotations
from functools import partial 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 from abodepy.exceptions import AbodeAuthenticationException, AbodeException
import abodepy.helpers.timeline as TIMELINE import abodepy.helpers.timeline as TIMELINE
from requests.exceptions import ConnectTimeout, HTTPError from requests.exceptions import ConnectTimeout, HTTPError
@ -18,15 +21,12 @@ from homeassistant.const import (
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
Platform, Platform,
) )
from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.core import Event, HomeAssistant, ServiceCall
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady 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.dispatcher import dispatcher_send
from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import ATTRIBUTION, DEFAULT_CACHEDB, DOMAIN, LOGGER from .const import ATTRIBUTION, CONF_POLLING, DEFAULT_CACHEDB, DOMAIN, LOGGER
CONF_POLLING = "polling"
SERVICE_SETTINGS = "change_setting" SERVICE_SETTINGS = "change_setting"
SERVICE_CAPTURE_IMAGE = "capture_image" SERVICE_CAPTURE_IMAGE = "capture_image"
@ -69,25 +69,25 @@ PLATFORMS = [
class AbodeSystem: class AbodeSystem:
"""Abode System class.""" """Abode System class."""
def __init__(self, abode, polling): def __init__(self, abode: Abode, polling: bool) -> None:
"""Initialize the system.""" """Initialize the system."""
self.abode = abode self.abode = abode
self.polling = polling self.polling = polling
self.entity_ids = set() self.entity_ids: set[str | None] = set()
self.logout_listener = None 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.""" """Set up Abode integration from a config entry."""
username = config_entry.data.get(CONF_USERNAME) username = entry.data[CONF_USERNAME]
password = config_entry.data.get(CONF_PASSWORD) password = entry.data[CONF_PASSWORD]
polling = config_entry.data.get(CONF_POLLING) polling = entry.data[CONF_POLLING]
cache = hass.config.path(DEFAULT_CACHEDB) cache = hass.config.path(DEFAULT_CACHEDB)
# For previous config entries where unique_id is None # 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( hass.config_entries.async_update_entry(
config_entry, unique_id=config_entry.data[CONF_USERNAME] entry, unique_id=entry.data[CONF_USERNAME]
) )
try: try:
@ -103,7 +103,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
hass.data[DOMAIN] = AbodeSystem(abode, polling) 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 setup_hass_events(hass)
await hass.async_add_executor_job(setup_hass_services, 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 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.""" """Unload a config entry."""
hass.services.async_remove(DOMAIN, SERVICE_SETTINGS) hass.services.async_remove(DOMAIN, SERVICE_SETTINGS)
hass.services.async_remove(DOMAIN, SERVICE_CAPTURE_IMAGE) hass.services.async_remove(DOMAIN, SERVICE_CAPTURE_IMAGE)
hass.services.async_remove(DOMAIN, SERVICE_TRIGGER_AUTOMATION) hass.services.async_remove(DOMAIN, SERVICE_TRIGGER_AUTOMATION)
unload_ok = await hass.config_entries.async_unload_platforms( unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
config_entry, PLATFORMS
)
await hass.async_add_executor_job(hass.data[DOMAIN].abode.events.stop) await hass.async_add_executor_job(hass.data[DOMAIN].abode.events.stop)
await hass.async_add_executor_job(hass.data[DOMAIN].abode.logout) 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: async def setup_hass_events(hass: HomeAssistant) -> None:
"""Home Assistant start and stop callbacks.""" """Home Assistant start and stop callbacks."""
def logout(event): def logout(event: Event) -> None:
"""Logout of Abode.""" """Logout of Abode."""
if not hass.data[DOMAIN].polling: if not hass.data[DOMAIN].polling:
hass.data[DOMAIN].abode.events.stop() 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: def setup_abode_events(hass: HomeAssistant) -> None:
"""Event callbacks.""" """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.""" """Handle an event callback from Abode."""
data = { data = {
ATTR_DEVICE_ID: event_json.get(ATTR_DEVICE_ID, ""), 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.""" """Representation of an Abode entity."""
_attr_attribution = ATTRIBUTION _attr_attribution = ATTRIBUTION
def __init__(self, data): def __init__(self, data: AbodeSystem) -> None:
"""Initialize Abode entity.""" """Initialize Abode entity."""
self._data = data self._data = data
self._attr_should_poll = data.polling 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.""" """Subscribe to Abode connection status updates."""
await self.hass.async_add_executor_job( await self.hass.async_add_executor_job(
self._data.abode.events.add_connection_status_callback, 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) 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.""" """Unsubscribe from Abode connection status updates."""
await self.hass.async_add_executor_job( await self.hass.async_add_executor_job(
self._data.abode.events.remove_connection_status_callback, self.unique_id 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.""" """Update the entity available property."""
self._attr_available = self._data.abode.events.connected self._attr_available = self._data.abode.events.connected
self.schedule_update_ha_state() self.schedule_update_ha_state()
@ -281,14 +279,14 @@ class AbodeEntity(Entity):
class AbodeDevice(AbodeEntity): class AbodeDevice(AbodeEntity):
"""Representation of an Abode device.""" """Representation of an Abode device."""
def __init__(self, data, device): def __init__(self, data: AbodeSystem, device: AbodeDev) -> None:
"""Initialize Abode device.""" """Initialize Abode device."""
super().__init__(data) super().__init__(data)
self._device = device self._device = device
self._attr_name = device.name self._attr_name = device.name
self._attr_unique_id = device.device_uuid 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.""" """Subscribe to device events."""
await super().async_added_to_hass() await super().async_added_to_hass()
await self.hass.async_add_executor_job( await self.hass.async_add_executor_job(
@ -297,19 +295,19 @@ class AbodeDevice(AbodeEntity):
self._update_callback, self._update_callback,
) )
async def async_will_remove_from_hass(self): async def async_will_remove_from_hass(self) -> None:
"""Unsubscribe from device events.""" """Unsubscribe from device events."""
await super().async_will_remove_from_hass() await super().async_will_remove_from_hass()
await self.hass.async_add_executor_job( await self.hass.async_add_executor_job(
self._data.abode.events.remove_all_device_callbacks, self._device.device_id self._data.abode.events.remove_all_device_callbacks, self._device.device_id
) )
def update(self): def update(self) -> None:
"""Update device state.""" """Update device state."""
self._device.refresh() self._device.refresh()
@property @property
def extra_state_attributes(self): def extra_state_attributes(self) -> dict[str, str]:
"""Return the state attributes.""" """Return the state attributes."""
return { return {
"device_id": self._device.device_id, "device_id": self._device.device_id,
@ -319,16 +317,16 @@ class AbodeDevice(AbodeEntity):
} }
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> entity.DeviceInfo:
"""Return device registry information for this entity.""" """Return device registry information for this entity."""
return DeviceInfo( return entity.DeviceInfo(
identifiers={(DOMAIN, self._device.device_id)}, identifiers={(DOMAIN, self._device.device_id)},
manufacturer="Abode", manufacturer="Abode",
model=self._device.type, model=self._device.type,
name=self._device.name, name=self._device.name,
) )
def _update_callback(self, device): def _update_callback(self, device: AbodeDev) -> None:
"""Update the device state.""" """Update the device state."""
self.schedule_update_ha_state() self.schedule_update_ha_state()
@ -336,7 +334,7 @@ class AbodeDevice(AbodeEntity):
class AbodeAutomation(AbodeEntity): class AbodeAutomation(AbodeEntity):
"""Representation of an Abode automation.""" """Representation of an Abode automation."""
def __init__(self, data, automation): def __init__(self, data: AbodeSystem, automation: AbodeAuto) -> None:
"""Initialize for Abode automation.""" """Initialize for Abode automation."""
super().__init__(data) super().__init__(data)
self._automation = automation self._automation = automation
@ -346,6 +344,6 @@ class AbodeAutomation(AbodeEntity):
"type": "CUE automation", "type": "CUE automation",
} }
def update(self): def update(self) -> None:
"""Update automation state.""" """Update automation state."""
self._automation.refresh() self._automation.refresh()

View File

@ -1,4 +1,8 @@
"""Support for Abode Security System alarm control panels.""" """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 import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -13,19 +17,17 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AbodeDevice from . import AbodeDevice, AbodeSystem
from .const import DOMAIN from .const import DOMAIN
ICON = "mdi:security" ICON = "mdi:security"
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up Abode alarm control panel device.""" """Set up Abode alarm control panel device."""
data = hass.data[DOMAIN] data: AbodeSystem = hass.data[DOMAIN]
async_add_entities( async_add_entities(
[AbodeAlarm(data, await hass.async_add_executor_job(data.abode.get_alarm))] [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_icon = ICON
_attr_code_arm_required = False _attr_code_arm_required = False
_attr_supported_features = SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY _attr_supported_features = SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY
_device: AbodeAl
@property @property
def state(self): def state(self) -> str | None:
"""Return the state of the device.""" """Return the state of the device."""
if self._device.is_standby: if self._device.is_standby:
state = STATE_ALARM_DISARMED return STATE_ALARM_DISARMED
elif self._device.is_away: if self._device.is_away:
state = STATE_ALARM_ARMED_AWAY return STATE_ALARM_ARMED_AWAY
elif self._device.is_home: if self._device.is_home:
state = STATE_ALARM_ARMED_HOME return STATE_ALARM_ARMED_HOME
else: return None
state = None
return state
def alarm_disarm(self, code=None): def alarm_disarm(self, code: str | None = None) -> None:
"""Send disarm command.""" """Send disarm command."""
self._device.set_standby() 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.""" """Send arm home command."""
self._device.set_home() 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.""" """Send arm away command."""
self._device.set_away() self._device.set_away()
@property @property
def extra_state_attributes(self): def extra_state_attributes(self) -> dict[str, str]:
"""Return the state attributes.""" """Return the state attributes."""
return { return {
"device_id": self._device.device_id, "device_id": self._device.device_id,

View File

@ -1,4 +1,7 @@
"""Support for Abode Security System binary sensors.""" """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 import abodepy.helpers.constants as CONST
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
@ -9,17 +12,15 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AbodeDevice from . import AbodeDevice, AbodeSystem
from .const import DOMAIN from .const import DOMAIN
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up Abode binary sensor devices.""" """Set up Abode binary sensor devices."""
data = hass.data[DOMAIN] data: AbodeSystem = hass.data[DOMAIN]
device_types = [ device_types = [
CONST.TYPE_CONNECTIVITY, CONST.TYPE_CONNECTIVITY,
@ -40,14 +41,16 @@ async def async_setup_entry(
class AbodeBinarySensor(AbodeDevice, BinarySensorEntity): class AbodeBinarySensor(AbodeDevice, BinarySensorEntity):
"""A binary sensor implementation for Abode device.""" """A binary sensor implementation for Abode device."""
@property _device: ABBinarySensor
def is_on(self):
"""Return True if the binary sensor is on."""
return self._device.is_on
@property @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.""" """Return the class of the binary sensor."""
if self._device.get_value("is_window") == "1": if self._device.get_value("is_window") == "1":
return BinarySensorDeviceClass.WINDOW return BinarySensorDeviceClass.WINDOW
return self._device.generic_type return cast(str, self._device.generic_type)

View File

@ -2,32 +2,32 @@
from __future__ import annotations from __future__ import annotations
from datetime import timedelta 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 abodepy.helpers.timeline as TIMELINE
import requests import requests
from requests.models import Response
from homeassistant.components.camera import Camera from homeassistant.components.camera import Camera
from homeassistant.config_entries import ConfigEntry 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.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import Throttle from homeassistant.util import Throttle
from . import AbodeDevice from . import AbodeDevice, AbodeSystem
from .const import DOMAIN, LOGGER from .const import DOMAIN, LOGGER
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=90) MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=90)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up Abode camera devices.""" """Set up Abode camera devices."""
data = hass.data[DOMAIN] data: AbodeSystem = hass.data[DOMAIN]
entities = [] entities = []
for device in data.abode.get_devices(generic_type=CONST.TYPE_CAMERA): 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): class AbodeCamera(AbodeDevice, Camera):
"""Representation of an Abode 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.""" """Initialize the Abode device."""
AbodeDevice.__init__(self, data, device) AbodeDevice.__init__(self, data, device)
Camera.__init__(self) Camera.__init__(self)
self._event = event 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.""" """Subscribe Abode events."""
await super().async_added_to_hass() await super().async_added_to_hass()
@ -59,17 +61,17 @@ class AbodeCamera(AbodeDevice, Camera):
signal = f"abode_camera_capture_{self.entity_id}" signal = f"abode_camera_capture_{self.entity_id}"
self.async_on_remove(async_dispatcher_connect(self.hass, signal, self.capture)) self.async_on_remove(async_dispatcher_connect(self.hass, signal, self.capture))
def capture(self): def capture(self) -> bool:
"""Request a new image capture.""" """Request a new image capture."""
return self._device.capture() return cast(bool, self._device.capture())
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
def refresh_image(self): def refresh_image(self) -> None:
"""Find a new image on the timeline.""" """Find a new image on the timeline."""
if self._device.refresh_image(): if self._device.refresh_image():
self.get_image() self.get_image()
def get_image(self): def get_image(self) -> None:
"""Attempt to download the most recent capture.""" """Attempt to download the most recent capture."""
if self._device.image_url: if self._device.image_url:
try: try:
@ -93,21 +95,21 @@ class AbodeCamera(AbodeDevice, Camera):
return None return None
def turn_on(self): def turn_on(self) -> None:
"""Turn on camera.""" """Turn on camera."""
self._device.privacy_mode(False) self._device.privacy_mode(False)
def turn_off(self): def turn_off(self) -> None:
"""Turn off camera.""" """Turn off camera."""
self._device.privacy_mode(True) 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.""" """Update the image with the device then refresh device."""
self._device.update_image_location(capture) self._device.update_image_location(capture)
self.get_image() self.get_image()
self.schedule_update_ha_state() self.schedule_update_ha_state()
@property @property
def is_on(self): def is_on(self) -> bool:
"""Return true if on.""" """Return true if on."""
return self._device.is_on return cast(bool, self._device.is_on)

View File

@ -1,5 +1,8 @@
"""Config flow for the Abode Security System component.""" """Config flow for the Abode Security System component."""
from __future__ import annotations
from http import HTTPStatus from http import HTTPStatus
from typing import Any, cast
from abodepy import Abode from abodepy import Abode
from abodepy.exceptions import AbodeAuthenticationException, AbodeException from abodepy.exceptions import AbodeAuthenticationException, AbodeException
@ -9,11 +12,11 @@ import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME 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_MFA = "mfa_code"
CONF_POLLING = "polling"
class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
@ -21,7 +24,7 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
VERSION = 1 VERSION = 1
def __init__(self): def __init__(self) -> None:
"""Initialize.""" """Initialize."""
self.data_schema = { self.data_schema = {
vol.Required(CONF_USERNAME): str, vol.Required(CONF_USERNAME): str,
@ -31,13 +34,13 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
vol.Required(CONF_MFA): str, vol.Required(CONF_MFA): str,
} }
self._cache = None self._cache: str | None = None
self._mfa_code = None self._mfa_code: str | None = None
self._password = None self._password: str | None = None
self._polling = False self._polling: bool = False
self._username = None 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.""" """Handle login with Abode."""
self._cache = self.hass.config.path(DEFAULT_CACHEDB) self._cache = self.hass.config.path(DEFAULT_CACHEDB)
errors = {} errors = {}
@ -47,7 +50,7 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
Abode, self._username, self._password, True, False, False, self._cache 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]: if ex.errcode == MFA_CODE_REQUIRED[0]:
return await self.async_step_mfa() return await self.async_step_mfa()
@ -59,6 +62,9 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
else: else:
errors = {"base": "cannot_connect"} errors = {"base": "cannot_connect"}
except (ConnectTimeout, HTTPError):
errors = {"base": "cannot_connect"}
if errors: if errors:
return self.async_show_form( return self.async_show_form(
step_id=step_id, data_schema=vol.Schema(self.data_schema), errors=errors 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() 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.""" """Handle multi-factor authentication (MFA) login with Abode."""
try: try:
# Create instance to access login method for passing MFA code # 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() return await self._async_create_entry()
async def _async_create_entry(self): async def _async_create_entry(self) -> FlowResult:
"""Create the config entry.""" """Create the config entry."""
config_data = { config_data = {
CONF_USERNAME: self._username, 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_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.""" """Handle a flow initialized by the user."""
if self._async_current_entries(): if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed") 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") 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.""" """Handle a multi-factor authentication (MFA) flow."""
if user_input is None: if user_input is None:
return self.async_show_form( return self.async_show_form(
@ -137,13 +149,15 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
return await self._async_abode_mfa_login() 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.""" """Handle reauthorization request from Abode."""
self._username = config[CONF_USERNAME] self._username = config[CONF_USERNAME]
return await self.async_step_reauth_confirm() 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.""" """Handle reauthorization flow."""
if user_input is None: if user_input is None:
return self.async_show_form( return self.async_show_form(

View File

@ -7,3 +7,4 @@ DOMAIN = "abode"
ATTRIBUTION = "Data provided by goabode.com" ATTRIBUTION = "Data provided by goabode.com"
DEFAULT_CACHEDB = "abodepy_cache.pickle" DEFAULT_CACHEDB = "abodepy_cache.pickle"
CONF_POLLING = "polling"

View File

@ -1,4 +1,7 @@
"""Support for Abode Security System covers.""" """Support for Abode Security System covers."""
from typing import Any
from abodepy.devices.cover import AbodeCover as AbodeCV
import abodepy.helpers.constants as CONST import abodepy.helpers.constants as CONST
from homeassistant.components.cover import CoverEntity from homeassistant.components.cover import CoverEntity
@ -6,17 +9,15 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AbodeDevice from . import AbodeDevice, AbodeSystem
from .const import DOMAIN from .const import DOMAIN
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up Abode cover devices.""" """Set up Abode cover devices."""
data = hass.data[DOMAIN] data: AbodeSystem = hass.data[DOMAIN]
entities = [] entities = []
@ -29,15 +30,17 @@ async def async_setup_entry(
class AbodeCover(AbodeDevice, CoverEntity): class AbodeCover(AbodeDevice, CoverEntity):
"""Representation of an Abode cover.""" """Representation of an Abode cover."""
_device: AbodeCV
@property @property
def is_closed(self): def is_closed(self) -> bool:
"""Return true if cover is closed, else False.""" """Return true if cover is closed, else False."""
return not self._device.is_open return not self._device.is_open
def close_cover(self, **kwargs): def close_cover(self, **kwargs: Any) -> None:
"""Issue close command to cover.""" """Issue close command to cover."""
self._device.close_cover() self._device.close_cover()
def open_cover(self, **kwargs): def open_cover(self, **kwargs: Any) -> None:
"""Issue open command to cover.""" """Issue open command to cover."""
self._device.open_cover() self._device.open_cover()

View File

@ -1,6 +1,10 @@
"""Support for Abode Security System lights.""" """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 import abodepy.helpers.constants as CONST
from homeassistant.components.light import ( from homeassistant.components.light import (
@ -20,17 +24,15 @@ from homeassistant.util.color import (
color_temperature_mired_to_kelvin, color_temperature_mired_to_kelvin,
) )
from . import AbodeDevice from . import AbodeDevice, AbodeSystem
from .const import DOMAIN from .const import DOMAIN
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up Abode light devices.""" """Set up Abode light devices."""
data = hass.data[DOMAIN] data: AbodeSystem = hass.data[DOMAIN]
entities = [] entities = []
@ -43,7 +45,9 @@ async def async_setup_entry(
class AbodeLight(AbodeDevice, LightEntity): class AbodeLight(AbodeDevice, LightEntity):
"""Representation of an Abode light.""" """Representation of an Abode light."""
def turn_on(self, **kwargs): _device: AbodeLT
def turn_on(self, **kwargs: Any) -> None:
"""Turn on the light.""" """Turn on the light."""
if ATTR_COLOR_TEMP in kwargs and self._device.is_color_capable: if ATTR_COLOR_TEMP in kwargs and self._device.is_color_capable:
self._device.set_color_temp( self._device.set_color_temp(
@ -63,40 +67,42 @@ class AbodeLight(AbodeDevice, LightEntity):
self._device.switch_on() self._device.switch_on()
def turn_off(self, **kwargs): def turn_off(self, **kwargs: Any) -> None:
"""Turn off the light.""" """Turn off the light."""
self._device.switch_off() self._device.switch_off()
@property @property
def is_on(self): def is_on(self) -> bool:
"""Return true if device is on.""" """Return true if device is on."""
return self._device.is_on return bool(self._device.is_on)
@property @property
def brightness(self): def brightness(self) -> int | None:
"""Return the brightness of the light.""" """Return the brightness of the light."""
if self._device.is_dimmable and self._device.has_brightness: if self._device.is_dimmable and self._device.has_brightness:
brightness = int(self._device.brightness) brightness = int(self._device.brightness)
# Abode returns 100 during device initialization and device refresh # 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) # 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 @property
def color_temp(self): def color_temp(self) -> int | None:
"""Return the color temp of the light.""" """Return the color temp of the light."""
if self._device.has_color: if self._device.has_color:
return color_temperature_kelvin_to_mired(self._device.color_temp) return color_temperature_kelvin_to_mired(self._device.color_temp)
return None
@property @property
def hs_color(self): def hs_color(self) -> tuple[float, float] | None:
"""Return the color of the light.""" """Return the color of the light."""
_hs = None
if self._device.has_color: if self._device.has_color:
return self._device.color _hs = self._device.color
return _hs
@property @property
def supported_features(self): def supported_features(self) -> int:
"""Flag supported features.""" """Flag supported features."""
if self._device.is_dimmable and self._device.is_color_capable: if self._device.is_dimmable and self._device.is_color_capable:
return SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_COLOR_TEMP return SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_COLOR_TEMP

View File

@ -1,4 +1,7 @@
"""Support for the Abode Security System locks.""" """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 import abodepy.helpers.constants as CONST
from homeassistant.components.lock import LockEntity from homeassistant.components.lock import LockEntity
@ -6,17 +9,15 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AbodeDevice from . import AbodeDevice, AbodeSystem
from .const import DOMAIN from .const import DOMAIN
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up Abode lock devices.""" """Set up Abode lock devices."""
data = hass.data[DOMAIN] data: AbodeSystem = hass.data[DOMAIN]
entities = [] entities = []
@ -29,15 +30,17 @@ async def async_setup_entry(
class AbodeLock(AbodeDevice, LockEntity): class AbodeLock(AbodeDevice, LockEntity):
"""Representation of an Abode lock.""" """Representation of an Abode lock."""
def lock(self, **kwargs): _device: AbodeLK
def lock(self, **kwargs: Any) -> None:
"""Lock the device.""" """Lock the device."""
self._device.lock() self._device.lock()
def unlock(self, **kwargs): def unlock(self, **kwargs: Any) -> None:
"""Unlock the device.""" """Unlock the device."""
self._device.unlock() self._device.unlock()
@property @property
def is_locked(self): def is_locked(self) -> bool:
"""Return true if device is on.""" """Return true if device is on."""
return self._device.is_locked return bool(self._device.is_locked)

View File

@ -1,7 +1,9 @@
"""Support for Abode Security System sensors.""" """Support for Abode Security System sensors."""
from __future__ import annotations 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 ( from homeassistant.components.sensor import (
SensorDeviceClass, SensorDeviceClass,
@ -12,7 +14,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AbodeDevice from . import AbodeDevice, AbodeSystem
from .const import DOMAIN from .const import DOMAIN
SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
@ -35,12 +37,10 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up Abode sensor devices.""" """Set up Abode sensor devices."""
data = hass.data[DOMAIN] data: AbodeSystem = hass.data[DOMAIN]
entities = [] entities = []
@ -60,7 +60,14 @@ async def async_setup_entry(
class AbodeSensor(AbodeDevice, SensorEntity): class AbodeSensor(AbodeDevice, SensorEntity):
"""A sensor implementation for Abode devices.""" """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.""" """Initialize a sensor for an Abode device."""
super().__init__(data, device) super().__init__(data, device)
self.entity_description = description self.entity_description = description
@ -74,11 +81,12 @@ class AbodeSensor(AbodeDevice, SensorEntity):
self._attr_native_unit_of_measurement = device.lux_unit self._attr_native_unit_of_measurement = device.lux_unit
@property @property
def native_value(self): def native_value(self) -> float | None:
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self.entity_description.key == CONST.TEMP_STATUS_KEY: 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: 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: if self.entity_description.key == CONST.LUX_STATUS_KEY:
return self._device.lux return cast(float, self._device.lux)
return None

View File

@ -1,7 +1,9 @@
"""Support for Abode Security System switches.""" """Support for Abode Security System switches."""
from __future__ import annotations 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.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry 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.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AbodeAutomation, AbodeDevice from . import AbodeAutomation, AbodeDevice, AbodeSystem
from .const import DOMAIN from .const import DOMAIN
DEVICE_TYPES = [CONST.TYPE_SWITCH, CONST.TYPE_VALVE] DEVICE_TYPES = [CONST.TYPE_SWITCH, CONST.TYPE_VALVE]
@ -18,12 +20,10 @@ ICON = "mdi:robot"
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up Abode switch devices.""" """Set up Abode switch devices."""
data = hass.data[DOMAIN] data: AbodeSystem = hass.data[DOMAIN]
entities: list[SwitchEntity] = [] entities: list[SwitchEntity] = []
@ -40,18 +40,20 @@ async def async_setup_entry(
class AbodeSwitch(AbodeDevice, SwitchEntity): class AbodeSwitch(AbodeDevice, SwitchEntity):
"""Representation of an Abode switch.""" """Representation of an Abode switch."""
def turn_on(self, **kwargs): _device: AbodeSW
def turn_on(self, **kwargs: Any) -> None:
"""Turn on the device.""" """Turn on the device."""
self._device.switch_on() self._device.switch_on()
def turn_off(self, **kwargs): def turn_off(self, **kwargs: Any) -> None:
"""Turn off the device.""" """Turn off the device."""
self._device.switch_off() self._device.switch_off()
@property @property
def is_on(self): def is_on(self) -> bool:
"""Return true if device is on.""" """Return true if device is on."""
return self._device.is_on return cast(bool, self._device.is_on)
class AbodeAutomationSwitch(AbodeAutomation, SwitchEntity): class AbodeAutomationSwitch(AbodeAutomation, SwitchEntity):
@ -59,28 +61,28 @@ class AbodeAutomationSwitch(AbodeAutomation, SwitchEntity):
_attr_icon = ICON _attr_icon = ICON
async def async_added_to_hass(self): async def async_added_to_hass(self) -> None:
"""Set up trigger automation service.""" """Set up trigger automation service."""
await super().async_added_to_hass() await super().async_added_to_hass()
signal = f"abode_trigger_automation_{self.entity_id}" signal = f"abode_trigger_automation_{self.entity_id}"
self.async_on_remove(async_dispatcher_connect(self.hass, signal, self.trigger)) 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.""" """Enable the automation."""
if self._automation.enable(True): if self._automation.enable(True):
self.schedule_update_ha_state() self.schedule_update_ha_state()
def turn_off(self, **kwargs): def turn_off(self, **kwargs: Any) -> None:
"""Disable the automation.""" """Disable the automation."""
if self._automation.enable(False): if self._automation.enable(False):
self.schedule_update_ha_state() self.schedule_update_ha_state()
def trigger(self): def trigger(self) -> None:
"""Trigger the automation.""" """Trigger the automation."""
self._automation.trigger() self._automation.trigger()
@property @property
def is_on(self): def is_on(self) -> bool:
"""Return True if the automation is enabled.""" """Return True if the automation is enabled."""
return self._automation.is_enabled return bool(self._automation.is_enabled)

View File

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

View File

@ -2,17 +2,23 @@
from unittest.mock import patch from unittest.mock import patch
from homeassistant.components.abode import DOMAIN as ABODE_DOMAIN 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.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry 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.""" """Set up the Abode platform."""
mock_entry = MockConfigEntry( mock_entry = MockConfigEntry(
domain=ABODE_DOMAIN, 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) mock_entry.add_to_hass(hass)

View File

@ -7,7 +7,7 @@ from tests.components.light.conftest import mock_light_profiles # noqa: F401
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def requests_mock_fixture(requests_mock): def requests_mock_fixture(requests_mock) -> None:
"""Fixture to provide a requests mocker.""" """Fixture to provide a requests mocker."""
# Mocks the login response for abodepy. # Mocks the login response for abodepy.
requests_mock.post(CONST.LOGIN_URL, text=load_fixture("login.json", "abode")) requests_mock.post(CONST.LOGIN_URL, text=load_fixture("login.json", "abode"))

View File

@ -16,6 +16,7 @@ from homeassistant.const import (
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_ALARM_DISARMED,
) )
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from .common import setup_platform from .common import setup_platform
@ -23,7 +24,7 @@ from .common import setup_platform
DEVICE_ID = "alarm_control_panel.abode_alarm" 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.""" """Tests that the devices are registered in the entity registry."""
await setup_platform(hass, ALARM_DOMAIN) await setup_platform(hass, ALARM_DOMAIN)
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -33,7 +34,7 @@ async def test_entity_registry(hass):
assert entry.unique_id == "001122334455" 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.""" """Test the alarm control panel attributes are correct."""
await setup_platform(hass, ALARM_DOMAIN) await setup_platform(hass, ALARM_DOMAIN)
@ -46,7 +47,7 @@ async def test_attributes(hass):
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 3 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.""" """Test the alarm control panel can be set to away."""
with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback: with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback:
with patch("abodepy.ALARM.AbodeAlarm.set_away") as mock_set_away: 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 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.""" """Test the alarm control panel can be set to home."""
with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback: with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback:
with patch("abodepy.ALARM.AbodeAlarm.set_home") as mock_set_home: 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 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.""" """Test the alarm control panel can be set to standby."""
with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback: with patch("abodepy.AbodeEventController.add_device_callback") as mock_callback:
with patch("abodepy.ALARM.AbodeAlarm.set_standby") as mock_set_standby: 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 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.""" """Test an unknown alarm control panel state."""
with patch("abodepy.ALARM.AbodeAlarm.mode", new_callable=PropertyMock) as mock_mode: with patch("abodepy.ALARM.AbodeAlarm.mode", new_callable=PropertyMock) as mock_mode:
await setup_platform(hass, ALARM_DOMAIN) await setup_platform(hass, ALARM_DOMAIN)

View File

@ -11,12 +11,13 @@ from homeassistant.const import (
ATTR_FRIENDLY_NAME, ATTR_FRIENDLY_NAME,
STATE_OFF, STATE_OFF,
) )
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from .common import setup_platform 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.""" """Tests that the devices are registered in the entity registry."""
await setup_platform(hass, BINARY_SENSOR_DOMAIN) await setup_platform(hass, BINARY_SENSOR_DOMAIN)
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -25,7 +26,7 @@ async def test_entity_registry(hass):
assert entry.unique_id == "2834013428b6035fba7d4054aa7b25a3" assert entry.unique_id == "2834013428b6035fba7d4054aa7b25a3"
async def test_attributes(hass): async def test_attributes(hass: HomeAssistant) -> None:
"""Test the binary sensor attributes are correct.""" """Test the binary sensor attributes are correct."""
await setup_platform(hass, BINARY_SENSOR_DOMAIN) await setup_platform(hass, BINARY_SENSOR_DOMAIN)

View File

@ -4,12 +4,13 @@ from unittest.mock import patch
from homeassistant.components.abode.const import DOMAIN as ABODE_DOMAIN from homeassistant.components.abode.const import DOMAIN as ABODE_DOMAIN
from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN
from homeassistant.const import ATTR_ENTITY_ID, STATE_IDLE from homeassistant.const import ATTR_ENTITY_ID, STATE_IDLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from .common import setup_platform 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.""" """Tests that the devices are registered in the entity registry."""
await setup_platform(hass, CAMERA_DOMAIN) await setup_platform(hass, CAMERA_DOMAIN)
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -18,7 +19,7 @@ async def test_entity_registry(hass):
assert entry.unique_id == "d0a3a1c316891ceb00c20118aae2a133" assert entry.unique_id == "d0a3a1c316891ceb00c20118aae2a133"
async def test_attributes(hass): async def test_attributes(hass: HomeAssistant) -> None:
"""Test the camera attributes are correct.""" """Test the camera attributes are correct."""
await setup_platform(hass, CAMERA_DOMAIN) await setup_platform(hass, CAMERA_DOMAIN)
@ -26,7 +27,7 @@ async def test_attributes(hass):
assert state.state == STATE_IDLE 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.""" """Test the camera capture image service."""
await setup_platform(hass, CAMERA_DOMAIN) await setup_platform(hass, CAMERA_DOMAIN)
@ -41,7 +42,7 @@ async def test_capture_image(hass):
mock_capture.assert_called_once() 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.""" """Test the camera turn on service."""
await setup_platform(hass, CAMERA_DOMAIN) await setup_platform(hass, CAMERA_DOMAIN)
@ -56,7 +57,7 @@ async def test_camera_on(hass):
mock_capture.assert_called_once_with(False) 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.""" """Test the camera turn off service."""
await setup_platform(hass, CAMERA_DOMAIN) await setup_platform(hass, CAMERA_DOMAIN)

View File

@ -4,19 +4,19 @@ from unittest.mock import patch
from abodepy.exceptions import AbodeAuthenticationException from abodepy.exceptions import AbodeAuthenticationException
from abodepy.helpers.errors import MFA_CODE_REQUIRED from abodepy.helpers.errors import MFA_CODE_REQUIRED
from requests.exceptions import ConnectTimeout
from homeassistant import data_entry_flow from homeassistant import data_entry_flow
from homeassistant.components.abode import config_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.config_entries import SOURCE_REAUTH, SOURCE_USER
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
CONF_POLLING = "polling"
async def test_show_form(hass: HomeAssistant) -> None:
async def test_show_form(hass):
"""Test that the form is served with no input.""" """Test that the form is served with no input."""
flow = config_flow.AbodeFlowHandler() flow = config_flow.AbodeFlowHandler()
flow.hass = hass flow.hass = hass
@ -27,7 +27,7 @@ async def test_show_form(hass):
assert result["step_id"] == "user" 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.""" """Test that only one Abode configuration is allowed."""
flow = config_flow.AbodeFlowHandler() flow = config_flow.AbodeFlowHandler()
flow.hass = hass flow.hass = hass
@ -43,7 +43,7 @@ async def test_one_config_allowed(hass):
assert step_user_result["reason"] == "single_instance_allowed" 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.""" """Test that invalid credentials throws an error."""
conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} 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"} 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.""" """Test other than invalid credentials throws an error."""
conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} 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"} 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.""" """Test that the user step works."""
conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} 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.""" """Test that the MFA step works."""
conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} 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.""" """Test the reauth flow."""
conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"}

View File

@ -10,6 +10,7 @@ from homeassistant.const import (
SERVICE_OPEN_COVER, SERVICE_OPEN_COVER,
STATE_CLOSED, STATE_CLOSED,
) )
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from .common import setup_platform from .common import setup_platform
@ -17,7 +18,7 @@ from .common import setup_platform
DEVICE_ID = "cover.garage_door" 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.""" """Tests that the devices are registered in the entity registry."""
await setup_platform(hass, COVER_DOMAIN) await setup_platform(hass, COVER_DOMAIN)
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -26,7 +27,7 @@ async def test_entity_registry(hass):
assert entry.unique_id == "61cbz3b542d2o33ed2fz02721bda3324" assert entry.unique_id == "61cbz3b542d2o33ed2fz02721bda3324"
async def test_attributes(hass): async def test_attributes(hass: HomeAssistant) -> None:
"""Test the cover attributes are correct.""" """Test the cover attributes are correct."""
await setup_platform(hass, COVER_DOMAIN) await setup_platform(hass, COVER_DOMAIN)
@ -39,7 +40,7 @@ async def test_attributes(hass):
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Garage Door" 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.""" """Test the cover can be opened."""
await setup_platform(hass, COVER_DOMAIN) await setup_platform(hass, COVER_DOMAIN)
@ -51,7 +52,7 @@ async def test_open(hass):
mock_open.assert_called_once() mock_open.assert_called_once()
async def test_close(hass): async def test_close(hass: HomeAssistant) -> None:
"""Test the cover can be closed.""" """Test the cover can be closed."""
await setup_platform(hass, COVER_DOMAIN) await setup_platform(hass, COVER_DOMAIN)

View File

@ -14,11 +14,12 @@ from homeassistant.components.abode import (
from homeassistant.components.alarm_control_panel import DOMAIN as ALARM_DOMAIN from homeassistant.components.alarm_control_panel import DOMAIN as ALARM_DOMAIN
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_USERNAME from homeassistant.const import CONF_USERNAME
from homeassistant.core import HomeAssistant
from .common import setup_platform from .common import setup_platform
async def test_change_settings(hass): async def test_change_settings(hass: HomeAssistant) -> None:
"""Test change_setting service.""" """Test change_setting service."""
await setup_platform(hass, ALARM_DOMAIN) await setup_platform(hass, ALARM_DOMAIN)
@ -33,7 +34,7 @@ async def test_change_settings(hass):
mock_set_setting.assert_called_once() 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.""" """Test unique_id is set to Abode username."""
mock_entry = await setup_platform(hass, ALARM_DOMAIN) mock_entry = await setup_platform(hass, ALARM_DOMAIN)
# Set unique_id to None to match previous config entries # 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] 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.""" """Test unloading the Abode entry."""
mock_entry = await setup_platform(hass, ALARM_DOMAIN) 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) 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.""" """Test Abode credentials changing."""
with patch( with patch(
"homeassistant.components.abode.Abode", "homeassistant.components.abode.Abode",
@ -81,7 +82,7 @@ async def test_invalid_credentials(hass):
mock_async_step_reauth.assert_called_once() 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.""" """Config entry state is SETUP_RETRY when abode is offline."""
with patch( with patch(
"homeassistant.components.abode.Abode", "homeassistant.components.abode.Abode",

View File

@ -16,6 +16,7 @@ from homeassistant.const import (
SERVICE_TURN_ON, SERVICE_TURN_ON,
STATE_ON, STATE_ON,
) )
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from .common import setup_platform from .common import setup_platform
@ -23,7 +24,7 @@ from .common import setup_platform
DEVICE_ID = "light.living_room_lamp" 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.""" """Tests that the devices are registered in the entity registry."""
await setup_platform(hass, LIGHT_DOMAIN) await setup_platform(hass, LIGHT_DOMAIN)
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -32,7 +33,7 @@ async def test_entity_registry(hass):
assert entry.unique_id == "741385f4388b2637df4c6b398fe50581" assert entry.unique_id == "741385f4388b2637df4c6b398fe50581"
async def test_attributes(hass): async def test_attributes(hass: HomeAssistant) -> None:
"""Test the light attributes are correct.""" """Test the light attributes are correct."""
await setup_platform(hass, LIGHT_DOMAIN) await setup_platform(hass, LIGHT_DOMAIN)
@ -49,7 +50,7 @@ async def test_attributes(hass):
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 19 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.""" """Test the light can be turned off."""
await setup_platform(hass, LIGHT_DOMAIN) await setup_platform(hass, LIGHT_DOMAIN)
@ -61,7 +62,7 @@ async def test_switch_off(hass):
mock_switch_off.assert_called_once() 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.""" """Test the light can be turned on."""
await setup_platform(hass, LIGHT_DOMAIN) await setup_platform(hass, LIGHT_DOMAIN)
@ -73,7 +74,7 @@ async def test_switch_on(hass):
mock_switch_on.assert_called_once() 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.""" """Test the brightness can be set."""
await setup_platform(hass, LIGHT_DOMAIN) await setup_platform(hass, LIGHT_DOMAIN)
@ -89,7 +90,7 @@ async def test_set_brightness(hass):
mock_set_level.assert_called_once_with(39) 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.""" """Test the color can be set."""
await setup_platform(hass, LIGHT_DOMAIN) 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)) 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.""" """Test the color temp can be set."""
await setup_platform(hass, LIGHT_DOMAIN) await setup_platform(hass, LIGHT_DOMAIN)

View File

@ -10,6 +10,7 @@ from homeassistant.const import (
SERVICE_UNLOCK, SERVICE_UNLOCK,
STATE_LOCKED, STATE_LOCKED,
) )
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from .common import setup_platform from .common import setup_platform
@ -17,7 +18,7 @@ from .common import setup_platform
DEVICE_ID = "lock.test_lock" 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.""" """Tests that the devices are registered in the entity registry."""
await setup_platform(hass, LOCK_DOMAIN) await setup_platform(hass, LOCK_DOMAIN)
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -26,7 +27,7 @@ async def test_entity_registry(hass):
assert entry.unique_id == "51cab3b545d2o34ed7fz02731bda5324" assert entry.unique_id == "51cab3b545d2o34ed7fz02731bda5324"
async def test_attributes(hass): async def test_attributes(hass: HomeAssistant) -> None:
"""Test the lock attributes are correct.""" """Test the lock attributes are correct."""
await setup_platform(hass, LOCK_DOMAIN) await setup_platform(hass, LOCK_DOMAIN)
@ -39,7 +40,7 @@ async def test_attributes(hass):
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Test Lock" 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.""" """Test the lock can be locked."""
await setup_platform(hass, LOCK_DOMAIN) await setup_platform(hass, LOCK_DOMAIN)
@ -51,7 +52,7 @@ async def test_lock(hass):
mock_lock.assert_called_once() mock_lock.assert_called_once()
async def test_unlock(hass): async def test_unlock(hass: HomeAssistant) -> None:
"""Test the lock can be unlocked.""" """Test the lock can be unlocked."""
await setup_platform(hass, LOCK_DOMAIN) await setup_platform(hass, LOCK_DOMAIN)

View File

@ -8,12 +8,13 @@ from homeassistant.const import (
PERCENTAGE, PERCENTAGE,
TEMP_CELSIUS, TEMP_CELSIUS,
) )
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from .common import setup_platform 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.""" """Tests that the devices are registered in the entity registry."""
await setup_platform(hass, SENSOR_DOMAIN) await setup_platform(hass, SENSOR_DOMAIN)
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -22,7 +23,7 @@ async def test_entity_registry(hass):
assert entry.unique_id == "13545b21f4bdcd33d9abd461f8443e65-humidity" assert entry.unique_id == "13545b21f4bdcd33d9abd461f8443e65-humidity"
async def test_attributes(hass): async def test_attributes(hass: HomeAssistant) -> None:
"""Test the sensor attributes are correct.""" """Test the sensor attributes are correct."""
await setup_platform(hass, SENSOR_DOMAIN) await setup_platform(hass, SENSOR_DOMAIN)

View File

@ -13,6 +13,7 @@ from homeassistant.const import (
STATE_OFF, STATE_OFF,
STATE_ON, STATE_ON,
) )
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from .common import setup_platform from .common import setup_platform
@ -23,7 +24,7 @@ DEVICE_ID = "switch.test_switch"
DEVICE_UID = "0012a4d3614cb7e2b8c9abea31d2fb2a" 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.""" """Tests that the devices are registered in the entity registry."""
await setup_platform(hass, SWITCH_DOMAIN) await setup_platform(hass, SWITCH_DOMAIN)
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -35,7 +36,7 @@ async def test_entity_registry(hass):
assert entry.unique_id == DEVICE_UID assert entry.unique_id == DEVICE_UID
async def test_attributes(hass): async def test_attributes(hass: HomeAssistant) -> None:
"""Test the switch attributes are correct.""" """Test the switch attributes are correct."""
await setup_platform(hass, SWITCH_DOMAIN) await setup_platform(hass, SWITCH_DOMAIN)
@ -43,7 +44,7 @@ async def test_attributes(hass):
assert state.state == STATE_OFF 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.""" """Test the switch can be turned on."""
await setup_platform(hass, SWITCH_DOMAIN) await setup_platform(hass, SWITCH_DOMAIN)
@ -56,7 +57,7 @@ async def test_switch_on(hass):
mock_switch_on.assert_called_once() 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.""" """Test the switch can be turned off."""
await setup_platform(hass, SWITCH_DOMAIN) await setup_platform(hass, SWITCH_DOMAIN)
@ -69,7 +70,7 @@ async def test_switch_off(hass):
mock_switch_off.assert_called_once() 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.""" """Test the automation attributes are correct."""
await setup_platform(hass, SWITCH_DOMAIN) await setup_platform(hass, SWITCH_DOMAIN)
@ -78,7 +79,7 @@ async def test_automation_attributes(hass):
assert state.state == STATE_ON 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.""" """Test the automation can be turned off."""
with patch("abodepy.AbodeAutomation.enable") as mock_trigger: with patch("abodepy.AbodeAutomation.enable") as mock_trigger:
await setup_platform(hass, SWITCH_DOMAIN) await setup_platform(hass, SWITCH_DOMAIN)
@ -94,7 +95,7 @@ async def test_turn_automation_off(hass):
mock_trigger.assert_called_once_with(False) 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.""" """Test the automation can be turned on."""
with patch("abodepy.AbodeAutomation.enable") as mock_trigger: with patch("abodepy.AbodeAutomation.enable") as mock_trigger:
await setup_platform(hass, SWITCH_DOMAIN) await setup_platform(hass, SWITCH_DOMAIN)
@ -110,7 +111,7 @@ async def test_turn_automation_on(hass):
mock_trigger.assert_called_once_with(True) 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.""" """Test the trigger automation service."""
await setup_platform(hass, SWITCH_DOMAIN) await setup_platform(hass, SWITCH_DOMAIN)