1 """Helpers to help with integration platforms."""
3 from __future__
import annotations
6 from collections.abc
import Awaitable, Callable
7 from dataclasses
import dataclass
8 from functools
import partial
10 from types
import ModuleType
11 from typing
import Any
17 async_get_integrations,
18 async_get_loaded_integration,
19 async_register_preload_platform,
26 _LOGGER = logging.getLogger(__name__)
27 DATA_INTEGRATION_PLATFORMS: HassKey[list[IntegrationPlatform]] =
HassKey(
28 "integration_platforms"
32 @dataclass(slots=True, frozen=True)
34 """An integration platform."""
37 process_job: HassJob[[HomeAssistant, str, Any], Awaitable[
None] |
None]
38 seen_components: set[str]
44 integration_platforms: list[IntegrationPlatform],
45 event: Event[EventComponentLoaded],
47 """Process integration platforms for a component."""
48 if "." in (component_name := event.data[ATTR_COMPONENT]):
53 integration_platforms_by_name: dict[str, IntegrationPlatform] = {}
54 for integration_platform
in integration_platforms:
55 if component_name
in integration_platform.seen_components:
57 integration_platform.seen_components.add(component_name)
58 integration_platforms_by_name[integration_platform.platform_name] = (
62 if not integration_platforms_by_name:
66 platforms_that_exist = integration.platforms_exists(integration_platforms_by_name)
67 if not platforms_that_exist:
72 platforms: dict[str, ModuleType] = {}
73 for platform_name
in platforms_that_exist:
74 if platform := integration.get_platform_cached(platform_name):
75 platforms[platform_name] = platform
85 integration_platforms_by_name,
91 hass.async_create_task_internal(
93 hass, integration, platforms_that_exist, integration_platforms_by_name
101 integration: Integration,
102 platforms_that_exist: list[str],
103 integration_platforms_by_name: dict[str, IntegrationPlatform],
105 """Process integration platforms for a component."""
108 platforms = await integration.async_get_platforms(platforms_that_exist)
111 "Unexpected error importing integration platforms for %s",
120 integration_platforms_by_name,
122 await asyncio.gather(*futures)
128 integration: Integration,
129 platforms: dict[str, ModuleType],
130 integration_platforms_by_name: dict[str, IntegrationPlatform],
131 ) -> list[asyncio.Future[Awaitable[
None] |
None]]:
132 """Process integration platforms for a component.
134 Only the platforms that are passed in will be processed.
138 for platform_name, platform
in platforms.items()
139 if (integration_platform := integration_platforms_by_name[platform_name])
141 future := hass.async_run_hass_job(
142 integration_platform.process_job,
151 def _format_err(name: str, platform_name: str, *args: Any) -> str:
152 """Format error message."""
153 return f
"Exception in {name} when processing platform '{platform_name}': {args}"
161 process_platform: Callable[[HomeAssistant, str, Any], Awaitable[
None] |
None],
162 wait_for_platforms: bool =
False,
164 """Process a specific platform for all current and future loaded integrations."""
165 if DATA_INTEGRATION_PLATFORMS
not in hass.data:
166 integration_platforms = hass.data[DATA_INTEGRATION_PLATFORMS] = []
167 hass.bus.async_listen(
168 EVENT_COMPONENT_LOADED,
170 _async_integration_platform_component_loaded,
172 integration_platforms,
176 integration_platforms = hass.data[DATA_INTEGRATION_PLATFORMS]
179 top_level_components = hass.config.top_level_components.copy()
183 partial(_format_err,
str(process_platform), platform_name),
185 f
"process_platform {platform_name}",
188 platform_name, process_job, top_level_components
194 integration_platforms.append(integration_platform)
195 if not top_level_components:
211 future = hass.async_create_task_internal(
213 hass, platform_name, top_level_components.copy(), process_job
217 if wait_for_platforms:
224 top_level_components: set[str],
225 process_job: HassJob,
227 """Process integration platforms for a component."""
229 loaded_integrations: list[Integration] = [
231 for integration
in integrations.values()
232 if not isinstance(integration, Exception)
238 futures: list[asyncio.Future[
None]] = []
239 for integration
in loaded_integrations:
240 if not integration.platforms_exists((platform_name,)):
243 platform = await integration.async_get_platform(platform_name)
246 "Unexpected error importing %s for %s",
252 if future := hass.async_run_hass_job(
253 process_job, hass, integration.domain, platform
255 futures.append(future)
258 await asyncio.gather(*futures)
Integration async_get_loaded_integration(HomeAssistant hass, str domain)
dict[str, Integration|Exception] async_get_integrations(HomeAssistant hass, Iterable[str] domains)
None async_register_preload_platform(HomeAssistant hass, str platform_name)