diff --git a/homeassistant/components/icloud/__init__.py b/homeassistant/components/icloud/__init__.py index 06028ebce6c4..63802804f4dd 100644 --- a/homeassistant/components/icloud/__init__.py +++ b/homeassistant/components/icloud/__init__.py @@ -1,4 +1,8 @@ """The iCloud component.""" +from __future__ import annotations + +from typing import Any + import voluptuous as vol from homeassistant.config_entries import ConfigEntry @@ -82,7 +86,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: if entry.unique_id is None: hass.config_entries.async_update_entry(entry, unique_id=username) - icloud_dir = Store(hass, STORAGE_VERSION, STORAGE_KEY) + icloud_dir = Store[Any](hass, STORAGE_VERSION, STORAGE_KEY) account = IcloudAccount( hass, @@ -103,7 +107,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: def play_sound(service: ServiceCall) -> None: """Play sound on the device.""" account = service.data[ATTR_ACCOUNT] - device_name = service.data.get(ATTR_DEVICE_NAME) + device_name: str = service.data[ATTR_DEVICE_NAME] device_name = slugify(device_name.replace(" ", "", 99)) for device in _get_account(account).get_devices_with_name(device_name): @@ -112,7 +116,7 @@ def play_sound(service: ServiceCall) -> None: def display_message(service: ServiceCall) -> None: """Display a message on the device.""" account = service.data[ATTR_ACCOUNT] - device_name = service.data.get(ATTR_DEVICE_NAME) + device_name: str = service.data[ATTR_DEVICE_NAME] device_name = slugify(device_name.replace(" ", "", 99)) message = service.data.get(ATTR_LOST_DEVICE_MESSAGE) sound = service.data.get(ATTR_LOST_DEVICE_SOUND, False) @@ -123,7 +127,7 @@ def display_message(service: ServiceCall) -> None: def lost_device(service: ServiceCall) -> None: """Make the device in lost state.""" account = service.data[ATTR_ACCOUNT] - device_name = service.data.get(ATTR_DEVICE_NAME) + device_name: str = service.data[ATTR_DEVICE_NAME] device_name = slugify(device_name.replace(" ", "", 99)) number = service.data.get(ATTR_LOST_DEVICE_NUMBER) message = service.data.get(ATTR_LOST_DEVICE_MESSAGE) @@ -139,11 +143,11 @@ def update_account(service: ServiceCall) -> None: else: _get_account(account).keep_alive() - def _get_account(account_identifier: str) -> any: + def _get_account(account_identifier: str) -> IcloudAccount: if account_identifier is None: return None - icloud_account = hass.data[DOMAIN].get(account_identifier) + icloud_account: IcloudAccount | None = hass.data[DOMAIN].get(account_identifier) if icloud_account is None: for account in hass.data[DOMAIN].values(): if account.username == account_identifier: diff --git a/homeassistant/components/icloud/account.py b/homeassistant/components/icloud/account.py index 95b90791165e..4dc3c07aba77 100644 --- a/homeassistant/components/icloud/account.py +++ b/homeassistant/components/icloud/account.py @@ -91,21 +91,19 @@ def __init__( self._username = username self._password = password self._with_family = with_family - self._fetch_interval = max_interval + self._fetch_interval: float = max_interval self._max_interval = max_interval self._gps_accuracy_threshold = gps_accuracy_threshold self._icloud_dir = icloud_dir self.api: PyiCloudService | None = None - self._owner_fullname = None - self._family_members_fullname = {} - self._devices = {} + self._owner_fullname: str | None = None + self._family_members_fullname: dict[str, str] = {} + self._devices: dict[str, IcloudDevice] = {} self._retried_fetch = False self._config_entry = config_entry - self.listeners = [] - def setup(self) -> None: """Set up an iCloud account.""" try: @@ -271,6 +269,8 @@ def _determine_interval(self) -> int: distances = [] for zone_state in zones: + if zone_state is None: + continue zone_state_lat = zone_state.attributes[DEVICE_LOCATION_LATITUDE] zone_state_long = zone_state.attributes[DEVICE_LOCATION_LONGITUDE] zone_distance = distance( @@ -279,7 +279,8 @@ def _determine_interval(self) -> int: zone_state_lat, zone_state_long, ) - distances.append(round(zone_distance / 1000, 1)) + if zone_distance is not None: + distances.append(round(zone_distance / 1000, 1)) # Max interval if no zone if not distances: @@ -288,7 +289,7 @@ def _determine_interval(self) -> int: # Calculate out how long it would take for the device to drive # to the nearest zone at 120 km/h: - interval = round(mindistance / 2, 0) + interval = round(mindistance / 2) # Never poll more than once per minute interval = max(interval, 1) @@ -324,7 +325,7 @@ def keep_alive(self, now=None) -> None: self.api.authenticate() self.update_devices() - def get_devices_with_name(self, name: str) -> [any]: + def get_devices_with_name(self, name: str) -> list[Any]: """Get devices by name.""" result = [] name_slug = slugify(name.replace(" ", "", 99)) @@ -341,7 +342,7 @@ def username(self) -> str: return self._username @property - def owner_fullname(self) -> str: + def owner_fullname(self) -> str | None: """Return the account owner fullname.""" return self._owner_fullname @@ -351,7 +352,7 @@ def family_members_fullname(self) -> dict[str, str]: return self._family_members_fullname @property - def fetch_interval(self) -> int: + def fetch_interval(self) -> float: """Return the account fetch interval.""" return self._fetch_interval @@ -386,14 +387,7 @@ def __init__(self, account: IcloudAccount, device: AppleDevice, status) -> None: self._device_class = self._status[DEVICE_CLASS] self._device_model = self._status[DEVICE_DISPLAY_NAME] - if self._status[DEVICE_PERSON_ID]: - owner_fullname = account.family_members_fullname[ - self._status[DEVICE_PERSON_ID] - ] - else: - owner_fullname = account.owner_fullname - - self._battery_level = None + self._battery_level: int | None = None self._battery_status = None self._location = None @@ -402,8 +396,13 @@ def __init__(self, account: IcloudAccount, device: AppleDevice, status) -> None: ATTR_ACCOUNT_FETCH_INTERVAL: self._account.fetch_interval, ATTR_DEVICE_NAME: self._device_model, ATTR_DEVICE_STATUS: None, - ATTR_OWNER_NAME: owner_fullname, } + if self._status[DEVICE_PERSON_ID]: + self._attrs[ATTR_OWNER_NAME] = account.family_members_fullname[ + self._status[DEVICE_PERSON_ID] + ] + elif account.owner_fullname is not None: + self._attrs[ATTR_OWNER_NAME] = account.owner_fullname def update(self, status) -> None: """Update the iCloud device.""" @@ -487,17 +486,17 @@ def device_model(self) -> str: return self._device_model @property - def battery_level(self) -> int: + def battery_level(self) -> int | None: """Return the Apple device battery level.""" return self._battery_level @property - def battery_status(self) -> str: + def battery_status(self) -> str | None: """Return the Apple device battery status.""" return self._battery_status @property - def location(self) -> dict[str, Any]: + def location(self) -> dict[str, Any] | None: """Return the Apple device location.""" return self._location diff --git a/homeassistant/components/icloud/device_tracker.py b/homeassistant/components/icloud/device_tracker.py index c9d251b06c7d..6886d500a845 100644 --- a/homeassistant/components/icloud/device_tracker.py +++ b/homeassistant/components/icloud/device_tracker.py @@ -36,7 +36,7 @@ async def async_setup_entry( ) -> None: """Set up device tracker for iCloud component.""" account = hass.data[DOMAIN][entry.unique_id] - tracked = set() + tracked = set[str]() @callback def update_account(): @@ -51,7 +51,7 @@ def update_account(): @callback -def add_entities(account, async_add_entities, tracked): +def add_entities(account: IcloudAccount, async_add_entities, tracked): """Add new tracker entities from the account.""" new_tracked = [] @@ -101,7 +101,7 @@ def longitude(self): return self._device.location[DEVICE_LOCATION_LONGITUDE] @property - def battery_level(self) -> int: + def battery_level(self) -> int | None: """Return the battery level of the device.""" return self._device.battery_level diff --git a/homeassistant/components/icloud/sensor.py b/homeassistant/components/icloud/sensor.py index 38ea3af62b6b..6e415aa33501 100644 --- a/homeassistant/components/icloud/sensor.py +++ b/homeassistant/components/icloud/sensor.py @@ -21,7 +21,7 @@ async def async_setup_entry( ) -> None: """Set up device tracker for iCloud component.""" account = hass.data[DOMAIN][entry.unique_id] - tracked = set() + tracked = set[str]() @callback def update_account(): @@ -74,7 +74,7 @@ def name(self) -> str: return f"{self._device.name} battery state" @property - def native_value(self) -> int: + def native_value(self) -> int | None: """Battery state percentage.""" return self._device.battery_level diff --git a/mypy.ini b/mypy.ini index 8335af1ed774..65b51e9d1c99 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2672,18 +2672,6 @@ ignore_errors = true [mypy-homeassistant.components.evohome.climate] ignore_errors = true -[mypy-homeassistant.components.icloud] -ignore_errors = true - -[mypy-homeassistant.components.icloud.account] -ignore_errors = true - -[mypy-homeassistant.components.icloud.device_tracker] -ignore_errors = true - -[mypy-homeassistant.components.icloud.sensor] -ignore_errors = true - [mypy-homeassistant.components.lovelace] ignore_errors = true diff --git a/script/hassfest/mypy_config.py b/script/hassfest/mypy_config.py index b492a70c8a9b..17ef8edc529c 100644 --- a/script/hassfest/mypy_config.py +++ b/script/hassfest/mypy_config.py @@ -25,10 +25,6 @@ "homeassistant.components.conversation.default_agent", "homeassistant.components.evohome", "homeassistant.components.evohome.climate", - "homeassistant.components.icloud", - "homeassistant.components.icloud.account", - "homeassistant.components.icloud.device_tracker", - "homeassistant.components.icloud.sensor", "homeassistant.components.lovelace", "homeassistant.components.lovelace.dashboard", "homeassistant.components.lovelace.resources",