Skip to content

Commit

Permalink
Add strict typing to device_tracker (home-assistant#50930)
Browse files Browse the repository at this point in the history
* Add strict typing to device_tracker

* Update homeassistant/components/device_tracker/legacy.py

Co-authored-by: Martin Hjelmare <[email protected]>

Co-authored-by: Martin Hjelmare <[email protected]>
  • Loading branch information
KapJI and MartinHjelmare authored May 22, 2021
1 parent 2e316f6 commit b704f0e
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 120 deletions.
1 change: 1 addition & 0 deletions .strict-typing
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ homeassistant.components.camera.*
homeassistant.components.canary.*
homeassistant.components.cover.*
homeassistant.components.device_automation.*
homeassistant.components.device_tracker.*
homeassistant.components.elgato.*
homeassistant.components.fitbit.*
homeassistant.components.fritzbox.*
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/device_tracker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@


@bind_hass
def is_on(hass: HomeAssistant, entity_id: str):
def is_on(hass: HomeAssistant, entity_id: str) -> bool:
"""Return the state if any or a specified device is home."""
return hass.states.is_state(entity_id, STATE_HOME)


async def async_setup(hass: HomeAssistant, config: ConfigType):
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the device tracker."""
await async_setup_legacy_integration(hass, config)

Expand Down
40 changes: 22 additions & 18 deletions homeassistant/components/device_tracker/config_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import final

from homeassistant.components import zone
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_BATTERY_LEVEL,
ATTR_GPS_ACCURACY,
Expand All @@ -12,13 +13,15 @@
STATE_HOME,
STATE_NOT_HOME,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import StateType

from .const import ATTR_HOST_NAME, ATTR_IP, ATTR_MAC, ATTR_SOURCE_TYPE, DOMAIN, LOGGER


async def async_setup_entry(hass, entry):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up an entry."""
component: EntityComponent | None = hass.data.get(DOMAIN)

Expand All @@ -28,33 +31,34 @@ async def async_setup_entry(hass, entry):
return await component.async_setup_entry(entry)


async def async_unload_entry(hass, entry):
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload an entry."""
return await hass.data[DOMAIN].async_unload_entry(entry)
component: EntityComponent = hass.data[DOMAIN]
return await component.async_unload_entry(entry)


class BaseTrackerEntity(Entity):
"""Represent a tracked device."""

@property
def battery_level(self):
def battery_level(self) -> int | None:
"""Return the battery level of the device.
Percentage from 0-100.
"""
return None

@property
def source_type(self):
def source_type(self) -> str:
"""Return the source type, eg gps or router, of the device."""
raise NotImplementedError

@property
def state_attributes(self):
def state_attributes(self) -> dict[str, StateType]:
"""Return the device state attributes."""
attr = {ATTR_SOURCE_TYPE: self.source_type}
attr: dict[str, StateType] = {ATTR_SOURCE_TYPE: self.source_type}

if self.battery_level:
if self.battery_level is not None:
attr[ATTR_BATTERY_LEVEL] = self.battery_level

return attr
Expand All @@ -64,17 +68,17 @@ class TrackerEntity(BaseTrackerEntity):
"""Base class for a tracked device."""

@property
def should_poll(self):
def should_poll(self) -> bool:
"""No polling for entities that have location pushed."""
return False

@property
def force_update(self):
def force_update(self) -> bool:
"""All updates need to be written to the state machine if we're not polling."""
return not self.should_poll

@property
def location_accuracy(self):
def location_accuracy(self) -> int:
"""Return the location accuracy of the device.
Value in meters.
Expand All @@ -97,9 +101,9 @@ def longitude(self) -> float | None:
raise NotImplementedError

@property
def state(self):
def state(self) -> str | None:
"""Return the state of the device."""
if self.location_name:
if self.location_name is not None:
return self.location_name

if self.latitude is not None and self.longitude is not None:
Expand All @@ -118,11 +122,11 @@ def state(self):

@final
@property
def state_attributes(self):
def state_attributes(self) -> dict[str, StateType]:
"""Return the device state attributes."""
attr = {}
attr: dict[str, StateType] = {}
attr.update(super().state_attributes)
if self.latitude is not None:
if self.latitude is not None and self.longitude is not None:
attr[ATTR_LATITUDE] = self.latitude
attr[ATTR_LONGITUDE] = self.longitude
attr[ATTR_GPS_ACCURACY] = self.location_accuracy
Expand Down Expand Up @@ -162,9 +166,9 @@ def is_connected(self) -> bool:

@final
@property
def state_attributes(self):
def state_attributes(self) -> dict[str, StateType]:
"""Return the device state attributes."""
attr = {}
attr: dict[str, StateType] = {}
attr.update(super().state_attributes)
if self.ip_address is not None:
attr[ATTR_IP] = self.ip_address
Expand Down
51 changes: 26 additions & 25 deletions homeassistant/components/device_tracker/const.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
"""Device tracker constants."""
from datetime import timedelta
import logging
from typing import Final

LOGGER = logging.getLogger(__package__)
LOGGER: Final = logging.getLogger(__package__)

DOMAIN = "device_tracker"
DOMAIN: Final = "device_tracker"

PLATFORM_TYPE_LEGACY = "legacy"
PLATFORM_TYPE_ENTITY = "entity_platform"
PLATFORM_TYPE_LEGACY: Final = "legacy"
PLATFORM_TYPE_ENTITY: Final = "entity_platform"

SOURCE_TYPE_GPS = "gps"
SOURCE_TYPE_ROUTER = "router"
SOURCE_TYPE_BLUETOOTH = "bluetooth"
SOURCE_TYPE_BLUETOOTH_LE = "bluetooth_le"
SOURCE_TYPE_GPS: Final = "gps"
SOURCE_TYPE_ROUTER: Final = "router"
SOURCE_TYPE_BLUETOOTH: Final = "bluetooth"
SOURCE_TYPE_BLUETOOTH_LE: Final = "bluetooth_le"

CONF_SCAN_INTERVAL = "interval_seconds"
SCAN_INTERVAL = timedelta(seconds=12)
CONF_SCAN_INTERVAL: Final = "interval_seconds"
SCAN_INTERVAL: Final = timedelta(seconds=12)

CONF_TRACK_NEW = "track_new_devices"
DEFAULT_TRACK_NEW = True
CONF_TRACK_NEW: Final = "track_new_devices"
DEFAULT_TRACK_NEW: Final = True

CONF_CONSIDER_HOME = "consider_home"
DEFAULT_CONSIDER_HOME = timedelta(seconds=180)
CONF_CONSIDER_HOME: Final = "consider_home"
DEFAULT_CONSIDER_HOME: Final = timedelta(seconds=180)

CONF_NEW_DEVICE_DEFAULTS = "new_device_defaults"
CONF_NEW_DEVICE_DEFAULTS: Final = "new_device_defaults"

ATTR_ATTRIBUTES = "attributes"
ATTR_BATTERY = "battery"
ATTR_DEV_ID = "dev_id"
ATTR_GPS = "gps"
ATTR_HOST_NAME = "host_name"
ATTR_LOCATION_NAME = "location_name"
ATTR_MAC = "mac"
ATTR_SOURCE_TYPE = "source_type"
ATTR_CONSIDER_HOME = "consider_home"
ATTR_IP = "ip"
ATTR_ATTRIBUTES: Final = "attributes"
ATTR_BATTERY: Final = "battery"
ATTR_DEV_ID: Final = "dev_id"
ATTR_GPS: Final = "gps"
ATTR_HOST_NAME: Final = "host_name"
ATTR_LOCATION_NAME: Final = "location_name"
ATTR_MAC: Final = "mac"
ATTR_SOURCE_TYPE: Final = "source_type"
ATTR_CONSIDER_HOME: Final = "consider_home"
ATTR_IP: Final = "ip"
10 changes: 7 additions & 3 deletions homeassistant/components/device_tracker/device_trigger.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Provides device automations for Device Tracker."""
from __future__ import annotations

from typing import Final

import voluptuous as vol

from homeassistant.components.automation import AutomationActionType
Expand All @@ -21,9 +23,9 @@

from . import DOMAIN

TRIGGER_TYPES = {"enters", "leaves"}
TRIGGER_TYPES: Final[set[str]] = {"enters", "leaves"}

TRIGGER_SCHEMA = TRIGGER_BASE_SCHEMA.extend(
TRIGGER_SCHEMA: Final = TRIGGER_BASE_SCHEMA.extend(
{
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Required(CONF_TYPE): vol.In(TRIGGER_TYPES),
Expand Down Expand Up @@ -88,7 +90,9 @@ async def async_attach_trigger(
)


async def async_get_trigger_capabilities(hass: HomeAssistant, config: ConfigType):
async def async_get_trigger_capabilities(
hass: HomeAssistant, config: ConfigType
) -> dict[str, vol.Schema]:
"""List trigger capabilities."""
zones = {
ent.entity_id: ent.name
Expand Down
Loading

0 comments on commit b704f0e

Please sign in to comment.