Make use of generic EntityComponent (#78492)

This commit is contained in:
epenet 2022-09-15 11:53:00 +02:00 committed by GitHub
parent 19ea95a6e4
commit b4afb1cb6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 32 additions and 45 deletions

View File

@ -221,7 +221,7 @@ def automations_with_blueprint(hass: HomeAssistant, blueprint_path: str) -> list
if DOMAIN not in hass.data: if DOMAIN not in hass.data:
return [] return []
component = hass.data[DOMAIN] component: EntityComponent[AutomationEntity] = hass.data[DOMAIN]
return [ return [
automation_entity.entity_id automation_entity.entity_id
@ -661,7 +661,7 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
async def _async_process_config( async def _async_process_config(
hass: HomeAssistant, hass: HomeAssistant,
config: dict[str, Any], config: dict[str, Any],
component: EntityComponent, component: EntityComponent[AutomationEntity],
) -> bool: ) -> bool:
"""Process config and add automations. """Process config and add automations.

View File

@ -322,12 +322,9 @@ def async_register_rtsp_to_web_rtc_provider(
async def _async_refresh_providers(hass: HomeAssistant) -> None: async def _async_refresh_providers(hass: HomeAssistant) -> None:
"""Check all cameras for any state changes for registered providers.""" """Check all cameras for any state changes for registered providers."""
component: EntityComponent = hass.data[DOMAIN] component: EntityComponent[Camera] = hass.data[DOMAIN]
await asyncio.gather( await asyncio.gather(
*( *(camera.async_refresh_providers() for camera in component.entities)
cast(Camera, camera).async_refresh_providers()
for camera in component.entities
)
) )
@ -343,7 +340,7 @@ def _async_get_rtsp_to_web_rtc_providers(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the camera component.""" """Set up the camera component."""
component = hass.data[DOMAIN] = EntityComponent( component = hass.data[DOMAIN] = EntityComponent[Camera](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
@ -363,7 +360,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def preload_stream(_event: Event) -> None: async def preload_stream(_event: Event) -> None:
for camera in component.entities: for camera in component.entities:
camera = cast(Camera, camera)
camera_prefs = prefs.get(camera.entity_id) camera_prefs = prefs.get(camera.entity_id)
if not camera_prefs.preload_stream: if not camera_prefs.preload_stream:
continue continue
@ -380,7 +376,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
def update_tokens(time: datetime) -> None: def update_tokens(time: datetime) -> None:
"""Update tokens of the entities.""" """Update tokens of the entities."""
for entity in component.entities: for entity in component.entities:
entity = cast(Camera, entity)
entity.async_update_token() entity.async_update_token()
entity.async_write_ha_state() entity.async_write_ha_state()
@ -411,13 +406,13 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up a config entry.""" """Set up a config entry."""
component: EntityComponent = hass.data[DOMAIN] component: EntityComponent[Camera] = hass.data[DOMAIN]
return await component.async_setup_entry(entry) return await component.async_setup_entry(entry)
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry.""" """Unload a config entry."""
component: EntityComponent = hass.data[DOMAIN] component: EntityComponent[Camera] = hass.data[DOMAIN]
return await component.async_unload_entry(entry) return await component.async_unload_entry(entry)
@ -698,7 +693,7 @@ class CameraView(HomeAssistantView):
requires_auth = False requires_auth = False
def __init__(self, component: EntityComponent) -> None: def __init__(self, component: EntityComponent[Camera]) -> None:
"""Initialize a basic camera view.""" """Initialize a basic camera view."""
self.component = component self.component = component
@ -707,8 +702,6 @@ class CameraView(HomeAssistantView):
if (camera := self.component.get_entity(entity_id)) is None: if (camera := self.component.get_entity(entity_id)) is None:
raise web.HTTPNotFound() raise web.HTTPNotFound()
camera = cast(Camera, camera)
authenticated = ( authenticated = (
request[KEY_AUTHENTICATED] request[KEY_AUTHENTICATED]
or request.query.get("token") in camera.access_tokens or request.query.get("token") in camera.access_tokens

View File

@ -1,8 +1,6 @@
"""Expose cameras as media sources.""" """Expose cameras as media sources."""
from __future__ import annotations from __future__ import annotations
from typing import Optional, cast
from homeassistant.components.media_player import BrowseError, MediaClass from homeassistant.components.media_player import BrowseError, MediaClass
from homeassistant.components.media_source.error import Unresolvable from homeassistant.components.media_source.error import Unresolvable
from homeassistant.components.media_source.models import ( from homeassistant.components.media_source.models import (
@ -37,8 +35,8 @@ class CameraMediaSource(MediaSource):
async def async_resolve_media(self, item: MediaSourceItem) -> PlayMedia: async def async_resolve_media(self, item: MediaSourceItem) -> PlayMedia:
"""Resolve media to a url.""" """Resolve media to a url."""
component: EntityComponent = self.hass.data[DOMAIN] component: EntityComponent[Camera] = self.hass.data[DOMAIN]
camera = cast(Optional[Camera], component.get_entity(item.identifier)) camera = component.get_entity(item.identifier)
if not camera: if not camera:
raise Unresolvable(f"Could not resolve media item: {item.identifier}") raise Unresolvable(f"Could not resolve media item: {item.identifier}")
@ -72,11 +70,10 @@ class CameraMediaSource(MediaSource):
can_stream_hls = "stream" in self.hass.config.components can_stream_hls = "stream" in self.hass.config.components
# Root. List cameras. # Root. List cameras.
component: EntityComponent = self.hass.data[DOMAIN] component: EntityComponent[Camera] = self.hass.data[DOMAIN]
children = [] children = []
not_shown = 0 not_shown = 0
for camera in component.entities: for camera in component.entities:
camera = cast(Camera, camera)
stream_type = camera.frontend_stream_type stream_type = camera.frontend_stream_type
if stream_type is None: if stream_type is None:

View File

@ -6,7 +6,7 @@ import asyncio
from collections.abc import Collection, Iterable from collections.abc import Collection, Iterable
from contextvars import ContextVar from contextvars import ContextVar
import logging import logging
from typing import Any, Protocol, Union, cast from typing import Any, Protocol, cast
import voluptuous as vol import voluptuous as vol
@ -119,9 +119,9 @@ CONFIG_SCHEMA = vol.Schema(
) )
def _async_get_component(hass: HomeAssistant) -> EntityComponent: def _async_get_component(hass: HomeAssistant) -> EntityComponent[Group]:
if (component := hass.data.get(DOMAIN)) is None: if (component := hass.data.get(DOMAIN)) is None:
component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass) component = hass.data[DOMAIN] = EntityComponent[Group](_LOGGER, DOMAIN, hass)
return component return component
@ -288,11 +288,11 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up all groups found defined in the configuration.""" """Set up all groups found defined in the configuration."""
if DOMAIN not in hass.data: if DOMAIN not in hass.data:
hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass) hass.data[DOMAIN] = EntityComponent[Group](_LOGGER, DOMAIN, hass)
await async_process_integration_platform_for_component(hass, DOMAIN) await async_process_integration_platform_for_component(hass, DOMAIN)
component: EntityComponent = hass.data[DOMAIN] component: EntityComponent[Group] = hass.data[DOMAIN]
hass.data[REG_KEY] = GroupIntegrationRegistry() hass.data[REG_KEY] = GroupIntegrationRegistry()
@ -302,11 +302,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def reload_service_handler(service: ServiceCall) -> None: async def reload_service_handler(service: ServiceCall) -> None:
"""Remove all user-defined groups and load new ones from config.""" """Remove all user-defined groups and load new ones from config."""
auto = [ auto = [e for e in component.entities if not e.user_defined]
cast(Group, e)
for e in component.entities
if not cast(Group, e).user_defined
]
if (conf := await component.async_prepare_reload()) is None: if (conf := await component.async_prepare_reload()) is None:
return return
@ -331,7 +327,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Handle dynamic group service functions.""" """Handle dynamic group service functions."""
object_id = service.data[ATTR_OBJECT_ID] object_id = service.data[ATTR_OBJECT_ID]
entity_id = f"{DOMAIN}.{object_id}" entity_id = f"{DOMAIN}.{object_id}"
group: Group | None = cast(Union[Group, None], component.get_entity(entity_id)) group = component.get_entity(entity_id)
# new group # new group
if service.service == SERVICE_SET and group is None: if service.service == SERVICE_SET and group is None:

View File

@ -2,7 +2,6 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
from typing import cast
import voluptuous as vol import voluptuous as vol
@ -107,7 +106,7 @@ async def async_add_user_device_tracker(
hass: HomeAssistant, user_id: str, device_tracker_entity_id: str hass: HomeAssistant, user_id: str, device_tracker_entity_id: str
): ):
"""Add a device tracker to a person linked to a user.""" """Add a device tracker to a person linked to a user."""
coll = cast(PersonStorageCollection, hass.data[DOMAIN][1]) coll: PersonStorageCollection = hass.data[DOMAIN][1]
for person in coll.async_items(): for person in coll.async_items():
if person.get(ATTR_USER_ID) != user_id: if person.get(ATTR_USER_ID) != user_id:
@ -134,12 +133,12 @@ def persons_with_entity(hass: HomeAssistant, entity_id: str) -> list[str]:
): ):
return [] return []
component: EntityComponent = hass.data[DOMAIN][2] component: EntityComponent[Person] = hass.data[DOMAIN][2]
return [ return [
person_entity.entity_id person_entity.entity_id
for person_entity in component.entities for person_entity in component.entities
if entity_id in cast(Person, person_entity).device_trackers if entity_id in person_entity.device_trackers
] ]
@ -149,12 +148,12 @@ def entities_in_person(hass: HomeAssistant, entity_id: str) -> list[str]:
if DOMAIN not in hass.data: if DOMAIN not in hass.data:
return [] return []
component: EntityComponent = hass.data[DOMAIN][2] component: EntityComponent[Person] = hass.data[DOMAIN][2]
if (person_entity := component.get_entity(entity_id)) is None: if (person_entity := component.get_entity(entity_id)) is None:
return [] return []
return cast(Person, person_entity).device_trackers return person_entity.device_trackers
CREATE_FIELDS = { CREATE_FIELDS = {

View File

@ -7,7 +7,7 @@ from datetime import timedelta
from enum import IntEnum from enum import IntEnum
import functools as ft import functools as ft
import logging import logging
from typing import Any, cast, final from typing import Any, final
import voluptuous as vol import voluptuous as vol
@ -88,7 +88,7 @@ def is_on(hass: HomeAssistant, entity_id: str) -> bool:
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Track states and offer events for remotes.""" """Track states and offer events for remotes."""
component = hass.data[DOMAIN] = EntityComponent( component = hass.data[DOMAIN] = EntityComponent[RemoteEntity](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
await component.async_setup(config) await component.async_setup(config)
@ -145,12 +145,14 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up a config entry.""" """Set up a config entry."""
return await cast(EntityComponent, hass.data[DOMAIN]).async_setup_entry(entry) component: EntityComponent[RemoteEntity] = hass.data[DOMAIN]
return await component.async_setup_entry(entry)
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry.""" """Unload a config entry."""
return await cast(EntityComponent, hass.data[DOMAIN]).async_unload_entry(entry) component: EntityComponent[RemoteEntity] = hass.data[DOMAIN]
return await component.async_unload_entry(entry)
@dataclass @dataclass

View File

@ -86,7 +86,7 @@ def _scripts_with_x(
if DOMAIN not in hass.data: if DOMAIN not in hass.data:
return [] return []
component = hass.data[DOMAIN] component: EntityComponent[ScriptEntity] = hass.data[DOMAIN]
return [ return [
script_entity.entity_id script_entity.entity_id
@ -100,7 +100,7 @@ def _x_in_script(hass: HomeAssistant, entity_id: str, property_name: str) -> lis
if DOMAIN not in hass.data: if DOMAIN not in hass.data:
return [] return []
component = hass.data[DOMAIN] component: EntityComponent[ScriptEntity] = hass.data[DOMAIN]
if (script_entity := component.get_entity(entity_id)) is None: if (script_entity := component.get_entity(entity_id)) is None:
return [] return []
@ -150,7 +150,7 @@ def scripts_with_blueprint(hass: HomeAssistant, blueprint_path: str) -> list[str
if DOMAIN not in hass.data: if DOMAIN not in hass.data:
return [] return []
component = hass.data[DOMAIN] component: EntityComponent[ScriptEntity] = hass.data[DOMAIN]
return [ return [
script_entity.entity_id script_entity.entity_id