Use HassKey in core components (a-c) (#126258)

* Use HassKey in conversation

* Use HassKey in assist_satellite

* automation

* More

* Unrelated

* Improve
This commit is contained in:
epenet 2024-09-20 12:07:15 +02:00 committed by GitHub
parent ef94fcf873
commit 8b44c16b57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 125 additions and 108 deletions

View file

@ -13,11 +13,13 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType, StateType from homeassistant.helpers.typing import ConfigType, StateType
from homeassistant.util.hass_dict import HassKey
from .const import DOMAIN from .const import DOMAIN
_LOGGER: Final = logging.getLogger(__name__) _LOGGER: Final = logging.getLogger(__name__)
DOMAIN_DATA: HassKey[EntityComponent[AirQualityEntity]] = HassKey(DOMAIN)
ENTITY_ID_FORMAT: Final = DOMAIN + ".{}" ENTITY_ID_FORMAT: Final = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
@ -54,7 +56,7 @@ PROP_TO_ATTR: Final[dict[str, str]] = {
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the air quality component.""" """Set up the air quality component."""
component = hass.data[DOMAIN] = EntityComponent[AirQualityEntity]( component = hass.data[DOMAIN_DATA] = EntityComponent[AirQualityEntity](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
await component.async_setup(config) await component.async_setup(config)
@ -63,14 +65,12 @@ 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[AirQualityEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[AirQualityEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)
class AirQualityEntity(Entity): class AirQualityEntity(Entity):

View file

@ -33,6 +33,7 @@ from homeassistant.helpers.deprecation import (
from homeassistant.helpers.entity import Entity, EntityDescription from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util.hass_dict import HassKey
from .const import ( # noqa: F401 from .const import ( # noqa: F401
_DEPRECATED_FORMAT_NUMBER, _DEPRECATED_FORMAT_NUMBER,
@ -52,6 +53,7 @@ from .const import ( # noqa: F401
_LOGGER: Final = logging.getLogger(__name__) _LOGGER: Final = logging.getLogger(__name__)
DOMAIN_DATA: HassKey[EntityComponent[AlarmControlPanelEntity]] = HassKey(DOMAIN)
ENTITY_ID_FORMAT: Final = DOMAIN + ".{}" ENTITY_ID_FORMAT: Final = DOMAIN + ".{}"
PLATFORM_SCHEMA: Final = cv.PLATFORM_SCHEMA PLATFORM_SCHEMA: Final = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE: Final = cv.PLATFORM_SCHEMA_BASE PLATFORM_SCHEMA_BASE: Final = cv.PLATFORM_SCHEMA_BASE
@ -69,7 +71,7 @@ ALARM_SERVICE_SCHEMA: Final = make_entity_service_schema(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Track states and offer events for sensors.""" """Track states and offer events for sensors."""
component = hass.data[DOMAIN] = EntityComponent[AlarmControlPanelEntity]( component = hass.data[DOMAIN_DATA] = EntityComponent[AlarmControlPanelEntity](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
@ -122,14 +124,12 @@ 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[AlarmControlPanelEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[AlarmControlPanelEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)
class AlarmControlPanelEntityDescription(EntityDescription, frozen_or_thawed=True): class AlarmControlPanelEntityDescription(EntityDescription, frozen_or_thawed=True):

View file

@ -10,7 +10,7 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN, AssistSatelliteEntityFeature from .const import DOMAIN, DOMAIN_DATA, AssistSatelliteEntityFeature
from .entity import ( from .entity import (
AssistSatelliteConfiguration, AssistSatelliteConfiguration,
AssistSatelliteEntity, AssistSatelliteEntity,
@ -36,7 +36,7 @@ PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
component = hass.data[DOMAIN] = EntityComponent[AssistSatelliteEntity]( component = hass.data[DOMAIN_DATA] = EntityComponent[AssistSatelliteEntity](
_LOGGER, DOMAIN, hass _LOGGER, DOMAIN, hass
) )
await component.async_setup(config) await component.async_setup(config)
@ -62,11 +62,9 @@ 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[AssistSatelliteEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[AssistSatelliteEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)

View file

@ -1,9 +1,21 @@
"""Constants for assist satellite.""" """Constants for assist satellite."""
from __future__ import annotations
from enum import IntFlag from enum import IntFlag
from typing import TYPE_CHECKING
from homeassistant.util.hass_dict import HassKey
if TYPE_CHECKING:
from homeassistant.helpers.entity_component import EntityComponent
from .entity import AssistSatelliteEntity
DOMAIN = "assist_satellite" DOMAIN = "assist_satellite"
DOMAIN_DATA: HassKey[EntityComponent[AssistSatelliteEntity]] = HassKey(DOMAIN)
class AssistSatelliteEntityFeature(IntFlag): class AssistSatelliteEntityFeature(IntFlag):
"""Supported features of Assist satellite entity.""" """Supported features of Assist satellite entity."""

View file

@ -9,10 +9,8 @@ from homeassistant.components import websocket_api
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_component import EntityComponent
from .const import DOMAIN from .const import DOMAIN, DOMAIN_DATA
from .entity import AssistSatelliteEntity
@callback @callback
@ -38,8 +36,7 @@ async def websocket_intercept_wake_word(
msg: dict[str, Any], msg: dict[str, Any],
) -> None: ) -> None:
"""Intercept the next wake word from a satellite.""" """Intercept the next wake word from a satellite."""
component: EntityComponent[AssistSatelliteEntity] = hass.data[DOMAIN] satellite = hass.data[DOMAIN_DATA].get_entity(msg["entity_id"])
satellite = component.get_entity(msg["entity_id"])
if satellite is None: if satellite is None:
connection.send_error( connection.send_error(
msg["id"], websocket_api.ERR_NOT_FOUND, "Entity not found" msg["id"], websocket_api.ERR_NOT_FOUND, "Entity not found"
@ -77,8 +74,7 @@ def websocket_get_configuration(
msg: dict[str, Any], msg: dict[str, Any],
) -> None: ) -> None:
"""Get the current satellite configuration.""" """Get the current satellite configuration."""
component: EntityComponent[AssistSatelliteEntity] = hass.data[DOMAIN] satellite = hass.data[DOMAIN_DATA].get_entity(msg["entity_id"])
satellite = component.get_entity(msg["entity_id"])
if satellite is None: if satellite is None:
connection.send_error( connection.send_error(
msg["id"], websocket_api.ERR_NOT_FOUND, "Entity not found" msg["id"], websocket_api.ERR_NOT_FOUND, "Entity not found"
@ -108,8 +104,7 @@ async def websocket_set_wake_words(
msg: dict[str, Any], msg: dict[str, Any],
) -> None: ) -> None:
"""Set the active wake words for the satellite.""" """Set the active wake words for the satellite."""
component: EntityComponent[AssistSatelliteEntity] = hass.data[DOMAIN] satellite = hass.data[DOMAIN_DATA].get_entity(msg["entity_id"])
satellite = component.get_entity(msg["entity_id"])
if satellite is None: if satellite is None:
connection.send_error( connection.send_error(
msg["id"], websocket_api.ERR_NOT_FOUND, "Entity not found" msg["id"], websocket_api.ERR_NOT_FOUND, "Entity not found"

View file

@ -94,6 +94,7 @@ from homeassistant.helpers.trigger import (
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
from homeassistant.util.dt import parse_datetime from homeassistant.util.dt import parse_datetime
from homeassistant.util.hass_dict import HassKey
from .config import AutomationConfig, ValidationStatus from .config import AutomationConfig, ValidationStatus
from .const import ( from .const import (
@ -109,6 +110,7 @@ from .const import (
from .helpers import async_get_blueprints from .helpers import async_get_blueprints
from .trace import trace_automation from .trace import trace_automation
DOMAIN_DATA: HassKey[EntityComponent[BaseAutomationEntity]] = HassKey(DOMAIN)
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
@ -161,14 +163,12 @@ def _automations_with_x(
hass: HomeAssistant, referenced_id: str, property_name: str hass: HomeAssistant, referenced_id: str, property_name: str
) -> list[str]: ) -> list[str]:
"""Return all automations that reference the x.""" """Return all automations that reference the x."""
if DOMAIN not in hass.data: if DOMAIN_DATA not in hass.data:
return [] return []
component: EntityComponent[BaseAutomationEntity] = hass.data[DOMAIN]
return [ return [
automation_entity.entity_id automation_entity.entity_id
for automation_entity in component.entities for automation_entity in hass.data[DOMAIN_DATA].entities
if referenced_id in getattr(automation_entity, property_name) if referenced_id in getattr(automation_entity, property_name)
] ]
@ -177,12 +177,10 @@ def _x_in_automation(
hass: HomeAssistant, entity_id: str, property_name: str hass: HomeAssistant, entity_id: str, property_name: str
) -> list[str]: ) -> list[str]:
"""Return all x in an automation.""" """Return all x in an automation."""
if DOMAIN not in hass.data: if DOMAIN_DATA not in hass.data:
return [] return []
component: EntityComponent[BaseAutomationEntity] = hass.data[DOMAIN] if (automation_entity := hass.data[DOMAIN_DATA].get_entity(entity_id)) is None:
if (automation_entity := component.get_entity(entity_id)) is None:
return [] return []
return list(getattr(automation_entity, property_name)) return list(getattr(automation_entity, property_name))
@ -254,11 +252,9 @@ 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: EntityComponent[BaseAutomationEntity] = hass.data[DOMAIN]
return [ return [
automation_entity.entity_id automation_entity.entity_id
for automation_entity in component.entities for automation_entity in hass.data[DOMAIN_DATA].entities
if automation_entity.referenced_blueprint == blueprint_path if automation_entity.referenced_blueprint == blueprint_path
] ]
@ -266,12 +262,10 @@ def automations_with_blueprint(hass: HomeAssistant, blueprint_path: str) -> list
@callback @callback
def blueprint_in_automation(hass: HomeAssistant, entity_id: str) -> str | None: def blueprint_in_automation(hass: HomeAssistant, entity_id: str) -> str | None:
"""Return the blueprint the automation is based on or None.""" """Return the blueprint the automation is based on or None."""
if DOMAIN not in hass.data: if DOMAIN_DATA not in hass.data:
return None return None
component: EntityComponent[BaseAutomationEntity] = hass.data[DOMAIN] if (automation_entity := hass.data[DOMAIN_DATA].get_entity(entity_id)) is None:
if (automation_entity := component.get_entity(entity_id)) is None:
return None return None
return automation_entity.referenced_blueprint return automation_entity.referenced_blueprint
@ -279,7 +273,7 @@ def blueprint_in_automation(hass: HomeAssistant, entity_id: str) -> str | None:
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up all automations.""" """Set up all automations."""
hass.data[DOMAIN] = component = EntityComponent[BaseAutomationEntity]( hass.data[DOMAIN_DATA] = component = EntityComponent[BaseAutomationEntity](
LOGGER, DOMAIN, hass LOGGER, DOMAIN, hass
) )
@ -1210,9 +1204,7 @@ def websocket_config(
msg: dict[str, Any], msg: dict[str, Any],
) -> None: ) -> None:
"""Get automation config.""" """Get automation config."""
component: EntityComponent[BaseAutomationEntity] = hass.data[DOMAIN] automation = hass.data[DOMAIN_DATA].get_entity(msg["entity_id"])
automation = component.get_entity(msg["entity_id"])
if automation is None: if automation is None:
connection.send_error( connection.send_error(

View file

@ -24,10 +24,12 @@ from homeassistant.helpers.deprecation import (
from homeassistant.helpers.entity import Entity, EntityDescription from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util.hass_dict import HassKey
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = "binary_sensor" DOMAIN = "binary_sensor"
DOMAIN_DATA: HassKey[EntityComponent[BinarySensorEntity]] = HassKey(DOMAIN)
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
@ -217,7 +219,7 @@ _DEPRECATED_DEVICE_CLASS_WINDOW = DeprecatedConstantEnum(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Track states and offer events for binary sensors.""" """Track states and offer events for binary sensors."""
component = hass.data[DOMAIN] = EntityComponent[BinarySensorEntity]( component = hass.data[DOMAIN_DATA] = EntityComponent[BinarySensorEntity](
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL
) )
@ -227,14 +229,12 @@ 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[BinarySensorEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[BinarySensorEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)
class BinarySensorEntityDescription(EntityDescription, frozen_or_thawed=True): class BinarySensorEntityDescription(EntityDescription, frozen_or_thawed=True):

View file

@ -19,11 +19,13 @@ from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from homeassistant.util.hass_dict import HassKey
from .const import DOMAIN, SERVICE_PRESS from .const import DOMAIN, SERVICE_PRESS
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN_DATA: HassKey[EntityComponent[ButtonEntity]] = HassKey(DOMAIN)
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
@ -47,7 +49,7 @@ DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.Coerce(ButtonDeviceClass))
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up Button entities.""" """Set up Button entities."""
component = hass.data[DOMAIN] = EntityComponent[ButtonEntity]( component = hass.data[DOMAIN_DATA] = EntityComponent[ButtonEntity](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
await component.async_setup(config) await component.async_setup(config)
@ -63,14 +65,12 @@ 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[ButtonEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[ButtonEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)
class ButtonEntityDescription(EntityDescription, frozen_or_thawed=True): class ButtonEntityDescription(EntityDescription, frozen_or_thawed=True):

View file

@ -43,6 +43,8 @@ from homeassistant.util.json import JsonValueType
from .const import ( from .const import (
CONF_EVENT, CONF_EVENT,
DOMAIN,
DOMAIN_DATA,
EVENT_DESCRIPTION, EVENT_DESCRIPTION,
EVENT_DURATION, EVENT_DURATION,
EVENT_END, EVENT_END,
@ -70,7 +72,6 @@ from .const import (
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = "calendar"
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
@ -285,7 +286,7 @@ SERVICE_GET_EVENTS_SCHEMA: Final = vol.All(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Track states and offer events for calendars.""" """Track states and offer events for calendars."""
component = hass.data[DOMAIN] = EntityComponent[CalendarEntity]( component = hass.data[DOMAIN_DATA] = EntityComponent[CalendarEntity](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
@ -318,14 +319,12 @@ 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[CalendarEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[CalendarEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)
def get_date(date: dict[str, Any]) -> datetime.datetime: def get_date(date: dict[str, Any]) -> datetime.datetime:
@ -702,8 +701,7 @@ async def handle_calendar_event_create(
hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any] hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]
) -> None: ) -> None:
"""Handle creation of a calendar event.""" """Handle creation of a calendar event."""
component: EntityComponent[CalendarEntity] = hass.data[DOMAIN] if not (entity := hass.data[DOMAIN_DATA].get_entity(msg["entity_id"])):
if not (entity := component.get_entity(msg["entity_id"])):
connection.send_error(msg["id"], ERR_NOT_FOUND, "Entity not found") connection.send_error(msg["id"], ERR_NOT_FOUND, "Entity not found")
return return
@ -743,8 +741,7 @@ async def handle_calendar_event_delete(
) -> None: ) -> None:
"""Handle delete of a calendar event.""" """Handle delete of a calendar event."""
component: EntityComponent[CalendarEntity] = hass.data[DOMAIN] if not (entity := hass.data[DOMAIN_DATA].get_entity(msg["entity_id"])):
if not (entity := component.get_entity(msg["entity_id"])):
connection.send_error(msg["id"], ERR_NOT_FOUND, "Entity not found") connection.send_error(msg["id"], ERR_NOT_FOUND, "Entity not found")
return return
@ -789,8 +786,7 @@ async def handle_calendar_event_update(
hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any] hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]
) -> None: ) -> None:
"""Handle creation of a calendar event.""" """Handle creation of a calendar event."""
component: EntityComponent[CalendarEntity] = hass.data[DOMAIN] if not (entity := hass.data[DOMAIN_DATA].get_entity(msg["entity_id"])):
if not (entity := component.get_entity(msg["entity_id"])):
connection.send_error(msg["id"], ERR_NOT_FOUND, "Entity not found") connection.send_error(msg["id"], ERR_NOT_FOUND, "Entity not found")
return return

View file

@ -1,6 +1,19 @@
"""Constants for calendar components.""" """Constants for calendar components."""
from __future__ import annotations
from enum import IntFlag from enum import IntFlag
from typing import TYPE_CHECKING
from homeassistant.util.hass_dict import HassKey
if TYPE_CHECKING:
from homeassistant.helpers.entity_component import EntityComponent
from . import CalendarEntity
DOMAIN = "calendar"
DOMAIN_DATA: HassKey[EntityComponent[CalendarEntity]] = HassKey(DOMAIN)
CONF_EVENT = "event" CONF_EVENT = "event"

View file

@ -23,7 +23,8 @@ from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from . import DOMAIN, CalendarEntity, CalendarEvent from . import CalendarEntity, CalendarEvent
from .const import DOMAIN, DOMAIN_DATA
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -94,7 +95,7 @@ type QueuedEventFetcher = Callable[[Timespan], Awaitable[list[QueuedCalendarEven
def get_entity(hass: HomeAssistant, entity_id: str) -> CalendarEntity: def get_entity(hass: HomeAssistant, entity_id: str) -> CalendarEntity:
"""Get the calendar entity for the provided entity_id.""" """Get the calendar entity for the provided entity_id."""
component: EntityComponent[CalendarEntity] = hass.data[DOMAIN] component: EntityComponent[CalendarEntity] = hass.data[DOMAIN_DATA]
if not (entity := component.get_entity(entity_id)) or not isinstance( if not (entity := component.get_entity(entity_id)) or not isinstance(
entity, CalendarEntity entity, CalendarEntity
): ):

View file

@ -73,6 +73,7 @@ from .const import ( # noqa: F401
DATA_CAMERA_PREFS, DATA_CAMERA_PREFS,
DATA_RTSP_TO_WEB_RTC, DATA_RTSP_TO_WEB_RTC,
DOMAIN, DOMAIN,
DOMAIN_DATA,
PREF_ORIENTATION, PREF_ORIENTATION,
PREF_PRELOAD_STREAM, PREF_PRELOAD_STREAM,
SERVICE_RECORD, SERVICE_RECORD,
@ -362,7 +363,7 @@ 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[Camera] = hass.data[DOMAIN] component = hass.data[DOMAIN_DATA]
await asyncio.gather( await asyncio.gather(
*(camera.async_refresh_providers() for camera in component.entities) *(camera.async_refresh_providers() for camera in component.entities)
) )
@ -380,7 +381,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[Camera]( component = hass.data[DOMAIN_DATA] = EntityComponent[Camera](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
@ -455,14 +456,12 @@ 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[Camera] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[Camera] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)
CACHED_PROPERTIES_WITH_ATTR_ = { CACHED_PROPERTIES_WITH_ATTR_ = {

View file

@ -1,8 +1,10 @@
"""Constants for Camera component.""" """Constants for Camera component."""
from __future__ import annotations
from enum import StrEnum from enum import StrEnum
from functools import partial from functools import partial
from typing import Final from typing import TYPE_CHECKING, Final
from homeassistant.helpers.deprecation import ( from homeassistant.helpers.deprecation import (
DeprecatedConstantEnum, DeprecatedConstantEnum,
@ -10,8 +12,15 @@ from homeassistant.helpers.deprecation import (
check_if_deprecated_constant, check_if_deprecated_constant,
dir_with_deprecated_constants, dir_with_deprecated_constants,
) )
from homeassistant.util.hass_dict import HassKey
if TYPE_CHECKING:
from homeassistant.helpers.entity_component import EntityComponent
from . import Camera
DOMAIN: Final = "camera" DOMAIN: Final = "camera"
DOMAIN_DATA: HassKey[EntityComponent[Camera]] = HassKey(DOMAIN)
DATA_CAMERA_PREFS: Final = "camera_prefs" DATA_CAMERA_PREFS: Final = "camera_prefs"
DATA_RTSP_TO_WEB_RTC: Final = "rtsp_to_web_rtc" DATA_RTSP_TO_WEB_RTC: Final = "rtsp_to_web_rtc"

View file

@ -16,10 +16,9 @@ from homeassistant.components.stream import FORMAT_CONTENT_TYPE, HLS_PROVIDER
from homeassistant.const import ATTR_FRIENDLY_NAME from homeassistant.const import ATTR_FRIENDLY_NAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_component import EntityComponent
from . import Camera, _async_stream_endpoint_url from . import Camera, _async_stream_endpoint_url
from .const import DOMAIN, StreamType from .const import DOMAIN, DOMAIN_DATA, StreamType
async def async_get_media_source(hass: HomeAssistant) -> CameraMediaSource: async def async_get_media_source(hass: HomeAssistant) -> CameraMediaSource:
@ -59,7 +58,7 @@ 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[Camera] = self.hass.data[DOMAIN] component = self.hass.data[DOMAIN_DATA]
camera = component.get_entity(item.identifier) camera = component.get_entity(item.identifier)
if not camera: if not camera:
@ -108,7 +107,7 @@ class CameraMediaSource(MediaSource):
return _media_source_for_camera(self.hass, camera, content_type) return _media_source_for_camera(self.hass, camera, content_type)
component: EntityComponent[Camera] = self.hass.data[DOMAIN] component = self.hass.data[DOMAIN_DATA]
results = await asyncio.gather( results = await asyncio.gather(
*(_filter_browsable_camera(camera) for camera in component.entities), *(_filter_browsable_camera(camera) for camera in component.entities),
return_exceptions=True, return_exceptions=True,

View file

@ -37,6 +37,7 @@ from homeassistant.helpers.entity_platform import EntityPlatform
from homeassistant.helpers.temperature import display_temp as show_temp from homeassistant.helpers.temperature import display_temp as show_temp
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import async_get_issue_tracker, async_suggest_report_issue from homeassistant.loader import async_get_issue_tracker, async_suggest_report_issue
from homeassistant.util.hass_dict import HassKey
from homeassistant.util.unit_conversion import TemperatureConverter from homeassistant.util.unit_conversion import TemperatureConverter
from .const import ( # noqa: F401 from .const import ( # noqa: F401
@ -114,6 +115,7 @@ from .const import ( # noqa: F401
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN_DATA: HassKey[EntityComponent[ClimateEntity]] = HassKey(DOMAIN)
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
@ -150,7 +152,7 @@ SET_TEMPERATURE_SCHEMA = vol.All(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up climate entities.""" """Set up climate entities."""
component = hass.data[DOMAIN] = EntityComponent[ClimateEntity]( component = hass.data[DOMAIN_DATA] = EntityComponent[ClimateEntity](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
await component.async_setup(config) await component.async_setup(config)
@ -223,14 +225,12 @@ 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[ClimateEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[ClimateEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)
class ClimateEntityDescription(EntityDescription, frozen_or_thawed=True): class ClimateEntityDescription(EntityDescription, frozen_or_thawed=True):

View file

@ -36,6 +36,7 @@ from .const import (
ATTR_LANGUAGE, ATTR_LANGUAGE,
ATTR_TEXT, ATTR_TEXT,
DOMAIN, DOMAIN,
DOMAIN_DATA,
HOME_ASSISTANT_AGENT, HOME_ASSISTANT_AGENT,
OLD_HOME_ASSISTANT_AGENT, OLD_HOME_ASSISTANT_AGENT,
SERVICE_PROCESS, SERVICE_PROCESS,
@ -132,7 +133,6 @@ def async_get_conversation_languages(
all conversation agents. all conversation agents.
""" """
agent_manager = get_agent_manager(hass) agent_manager = get_agent_manager(hass)
entity_component: EntityComponent[ConversationEntity] = hass.data[DOMAIN]
agents: list[ConversationEntity | AbstractConversationAgent] agents: list[ConversationEntity | AbstractConversationAgent]
if agent_id: if agent_id:
@ -148,7 +148,7 @@ def async_get_conversation_languages(
agents = [agent] agents = [agent]
else: else:
agents = list(entity_component.entities) agents = list(hass.data[DOMAIN_DATA].entities)
for info in agent_manager.async_get_agent_info(): for info in agent_manager.async_get_agent_info():
agent = agent_manager.async_get_agent(info.id) agent = agent_manager.async_get_agent(info.id)
assert agent is not None assert agent is not None
@ -208,10 +208,8 @@ async def async_prepare_agent(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Register the process service.""" """Register the process service."""
entity_component: EntityComponent[ConversationEntity] = EntityComponent( entity_component = EntityComponent[ConversationEntity](_LOGGER, DOMAIN, hass)
_LOGGER, DOMAIN, hass hass.data[DOMAIN_DATA] = entity_component
)
hass.data[DOMAIN] = entity_component
await async_setup_default_agent( await async_setup_default_agent(
hass, entity_component, config.get(DOMAIN, {}).get("intents", {}) hass, entity_component, config.get(DOMAIN, {}).get("intents", {})
@ -269,11 +267,9 @@ 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[ConversationEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[ConversationEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)

View file

@ -10,9 +10,8 @@ import voluptuous as vol
from homeassistant.core import Context, HomeAssistant, async_get_hass, callback from homeassistant.core import Context, HomeAssistant, async_get_hass, callback
from homeassistant.helpers import config_validation as cv, singleton from homeassistant.helpers import config_validation as cv, singleton
from homeassistant.helpers.entity_component import EntityComponent
from .const import DOMAIN, HOME_ASSISTANT_AGENT, OLD_HOME_ASSISTANT_AGENT from .const import DOMAIN_DATA, HOME_ASSISTANT_AGENT, OLD_HOME_ASSISTANT_AGENT
from .default_agent import async_get_default_agent from .default_agent import async_get_default_agent
from .entity import ConversationEntity from .entity import ConversationEntity
from .models import ( from .models import (
@ -54,8 +53,7 @@ def async_get_agent(
return async_get_default_agent(hass) return async_get_default_agent(hass)
if "." in agent_id: if "." in agent_id:
entity_component: EntityComponent[ConversationEntity] = hass.data[DOMAIN] return hass.data[DOMAIN_DATA].get_entity(agent_id)
return entity_component.get_entity(agent_id)
manager = get_agent_manager(hass) manager = get_agent_manager(hass)

View file

@ -1,6 +1,16 @@
"""Const for conversation integration.""" """Const for conversation integration."""
from __future__ import annotations
from enum import IntFlag from enum import IntFlag
from typing import TYPE_CHECKING
from homeassistant.util.hass_dict import HassKey
if TYPE_CHECKING:
from homeassistant.helpers.entity_component import EntityComponent
from .entity import ConversationEntity
DOMAIN = "conversation" DOMAIN = "conversation"
DEFAULT_EXPOSED_ATTRIBUTES = {"device_class"} DEFAULT_EXPOSED_ATTRIBUTES = {"device_class"}
@ -15,6 +25,8 @@ ATTR_CONVERSATION_ID = "conversation_id"
SERVICE_PROCESS = "process" SERVICE_PROCESS = "process"
SERVICE_RELOAD = "reload" SERVICE_RELOAD = "reload"
DOMAIN_DATA: HassKey[EntityComponent[ConversationEntity]] = HassKey(DOMAIN)
class ConversationEntityFeature(IntFlag): class ConversationEntityFeature(IntFlag):
"""Supported features of the conversation entity.""" """Supported features of the conversation entity."""

View file

@ -19,7 +19,6 @@ from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.const import MATCH_ALL from homeassistant.const import MATCH_ALL
from homeassistant.core import HomeAssistant, State, callback from homeassistant.core import HomeAssistant, State, callback
from homeassistant.helpers import config_validation as cv, intent from homeassistant.helpers import config_validation as cv, intent
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.util import language as language_util from homeassistant.util import language as language_util
from .agent_manager import ( from .agent_manager import (
@ -28,7 +27,7 @@ from .agent_manager import (
async_get_agent, async_get_agent,
get_agent_manager, get_agent_manager,
) )
from .const import DOMAIN from .const import DOMAIN_DATA
from .default_agent import ( from .default_agent import (
METADATA_CUSTOM_FILE, METADATA_CUSTOM_FILE,
METADATA_CUSTOM_SENTENCE, METADATA_CUSTOM_SENTENCE,
@ -113,13 +112,11 @@ async def websocket_list_agents(
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
) -> None: ) -> None:
"""List conversation agents and, optionally, if they support a given language.""" """List conversation agents and, optionally, if they support a given language."""
entity_component: EntityComponent[ConversationEntity] = hass.data[DOMAIN]
country = msg.get("country") country = msg.get("country")
language = msg.get("language") language = msg.get("language")
agents = [] agents = []
for entity in entity_component.entities: for entity in hass.data[DOMAIN_DATA].entities:
supported_languages = entity.supported_languages supported_languages = entity.supported_languages
if language and supported_languages != MATCH_ALL: if language and supported_languages != MATCH_ALL:
supported_languages = language_util.matches( supported_languages = language_util.matches(

View file

@ -41,11 +41,13 @@ from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
from homeassistant.util.hass_dict import HassKey
from .const import DOMAIN, INTENT_CLOSE_COVER, INTENT_OPEN_COVER # noqa: F401 from .const import DOMAIN, INTENT_CLOSE_COVER, INTENT_OPEN_COVER # noqa: F401
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN_DATA: HassKey[EntityComponent[CoverEntity]] = HassKey(DOMAIN)
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
@ -151,7 +153,7 @@ def is_closed(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 covers.""" """Track states and offer events for covers."""
component = hass.data[DOMAIN] = EntityComponent[CoverEntity]( component = hass.data[DOMAIN_DATA] = EntityComponent[CoverEntity](
_LOGGER, DOMAIN, hass, SCAN_INTERVAL _LOGGER, DOMAIN, hass, SCAN_INTERVAL
) )
@ -231,14 +233,12 @@ 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[CoverEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].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[CoverEntity] = hass.data[DOMAIN] return await hass.data[DOMAIN_DATA].async_unload_entry(entry)
return await component.async_unload_entry(entry)
class CoverEntityDescription(EntityDescription, frozen_or_thawed=True): class CoverEntityDescription(EntityDescription, frozen_or_thawed=True):