Add and fix type hints (#36501)

* Fix exceptions.Unauthorized.permission type

* Use auth.permission consts more

* Auth typing improvements

* Helpers typing improvements

* Calculate self.state only once
This commit is contained in:
Ville Skyttä 2020-06-06 21:34:56 +03:00 committed by GitHub
parent 49747684a0
commit 0c5ca3084e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 53 additions and 43 deletions

View file

@ -5,7 +5,7 @@ from datetime import datetime, timedelta
import functools as ft
import logging
from timeit import default_timer as timer
from typing import Any, Dict, Iterable, List, Optional, Union
from typing import Any, Awaitable, Dict, Iterable, List, Optional, Union
from homeassistant.config import DATA_CUSTOMIZE
from homeassistant.const import (
@ -32,11 +32,10 @@ from homeassistant.helpers.entity_registry import (
EVENT_ENTITY_REGISTRY_UPDATED,
RegistryEntry,
)
from homeassistant.helpers.event import Event
from homeassistant.util import dt as dt_util, ensure_unique_string, slugify
from homeassistant.util.async_ import run_callback_threadsafe
# mypy: allow-untyped-defs, no-check-untyped-defs
_LOGGER = logging.getLogger(__name__)
SLOW_UPDATE_WARNING = 10
@ -258,7 +257,7 @@ class Entity(ABC):
self._context = context
self._context_set = dt_util.utcnow()
async def async_update_ha_state(self, force_refresh=False):
async def async_update_ha_state(self, force_refresh: bool = False) -> None:
"""Update Home Assistant with current state of entity.
If force_refresh == True will update entity before setting state.
@ -294,14 +293,15 @@ class Entity(ABC):
f"No entity id specified for entity {self.name}"
)
self._async_write_ha_state() # type: ignore
self._async_write_ha_state()
@callback
def _async_write_ha_state(self):
def _async_write_ha_state(self) -> None:
"""Write the state to the state machine."""
if self.registry_entry and self.registry_entry.disabled_by:
if not self._disabled_reported:
self._disabled_reported = True
assert self.platform is not None
_LOGGER.warning(
"Entity %s is incorrectly being triggered for updates while it is disabled. This is a bug in the %s integration.",
self.entity_id,
@ -317,9 +317,8 @@ class Entity(ABC):
if not self.available:
state = STATE_UNAVAILABLE
else:
state = self.state
state = STATE_UNKNOWN if state is None else str(state)
sstate = self.state
state = STATE_UNKNOWN if sstate is None else str(sstate)
attr.update(self.state_attributes or {})
attr.update(self.device_state_attributes or {})
@ -383,6 +382,7 @@ class Entity(ABC):
)
# Overwrite properties that have been set in the config file.
assert self.hass is not None
if DATA_CUSTOMIZE in self.hass.data:
attr.update(self.hass.data[DATA_CUSTOMIZE].get(self.entity_id))
@ -403,7 +403,7 @@ class Entity(ABC):
pass
if (
self._context is not None
self._context_set is not None
and dt_util.utcnow() - self._context_set > self.context_recent_time
):
self._context = None
@ -413,7 +413,7 @@ class Entity(ABC):
self.entity_id, state, attr, self.force_update, self._context
)
def schedule_update_ha_state(self, force_refresh=False):
def schedule_update_ha_state(self, force_refresh: bool = False) -> None:
"""Schedule an update ha state change task.
Scheduling the update avoids executor deadlocks.
@ -423,10 +423,11 @@ class Entity(ABC):
If state is changed more than once before the ha state change task has
been executed, the intermediate state transitions will be missed.
"""
self.hass.add_job(self.async_update_ha_state(force_refresh))
assert self.hass is not None
self.hass.add_job(self.async_update_ha_state(force_refresh)) # type: ignore
@callback
def async_schedule_update_ha_state(self, force_refresh=False):
def async_schedule_update_ha_state(self, force_refresh: bool = False) -> None:
"""Schedule an update ha state change task.
This method must be run in the event loop.
@ -438,11 +439,12 @@ class Entity(ABC):
been executed, the intermediate state transitions will be missed.
"""
if force_refresh:
assert self.hass is not None
self.hass.async_create_task(self.async_update_ha_state(force_refresh))
else:
self.async_write_ha_state()
async def async_device_update(self, warning=True):
async def async_device_update(self, warning: bool = True) -> None:
"""Process 'update' or 'async_update' from entity.
This method is a coroutine.
@ -455,6 +457,7 @@ class Entity(ABC):
if self.parallel_updates:
await self.parallel_updates.acquire()
assert self.hass is not None
if warning:
update_warn = self.hass.loop.call_later(
SLOW_UPDATE_WARNING,
@ -467,9 +470,11 @@ class Entity(ABC):
try:
# pylint: disable=no-member
if hasattr(self, "async_update"):
await self.async_update()
await self.async_update() # type: ignore
elif hasattr(self, "update"):
await self.hass.async_add_executor_job(self.update)
await self.hass.async_add_executor_job(
self.update # type: ignore
)
finally:
self._update_staged = False
if warning:
@ -534,7 +539,7 @@ class Entity(ABC):
Not to be extended by integrations.
"""
async def _async_registry_updated(self, event):
async def _async_registry_updated(self, event: Event) -> None:
"""Handle entity registry update."""
data = event.data
if data["action"] == "remove" and data["entity_id"] == self.entity_id:
@ -547,24 +552,28 @@ class Entity(ABC):
):
return
assert self.hass is not None
ent_reg = await self.hass.helpers.entity_registry.async_get_registry()
old = self.registry_entry
self.registry_entry = ent_reg.async_get(data["entity_id"])
assert self.registry_entry is not None
if self.registry_entry.disabled_by is not None:
await self.async_remove()
return
assert old is not None
if self.registry_entry.entity_id == old.entity_id:
self.async_write_ha_state()
return
await self.async_remove()
assert self.platform is not None
self.entity_id = self.registry_entry.entity_id
await self.platform.async_add_entities([self])
def __eq__(self, other):
def __eq__(self, other: Any) -> bool:
"""Return the comparison."""
if not isinstance(other, self.__class__):
return False
@ -587,8 +596,7 @@ class Entity(ABC):
"""Return the representation."""
return f"<Entity {self.name}: {self.state}>"
# call an requests
async def async_request_call(self, coro):
async def async_request_call(self, coro: Awaitable) -> None:
"""Process request batched."""
if self.parallel_updates:
await self.parallel_updates.acquire()
@ -617,16 +625,18 @@ class ToggleEntity(Entity):
"""Turn the entity on."""
raise NotImplementedError()
async def async_turn_on(self, **kwargs):
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
assert self.hass is not None
await self.hass.async_add_executor_job(ft.partial(self.turn_on, **kwargs))
def turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
raise NotImplementedError()
async def async_turn_off(self, **kwargs):
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
assert self.hass is not None
await self.hass.async_add_executor_job(ft.partial(self.turn_off, **kwargs))
def toggle(self, **kwargs: Any) -> None:
@ -636,7 +646,7 @@ class ToggleEntity(Entity):
else:
self.turn_on(**kwargs)
async def async_toggle(self, **kwargs):
async def async_toggle(self, **kwargs: Any) -> None:
"""Toggle the entity."""
if self.is_on:
await self.async_turn_off(**kwargs)