mirror of
https://github.com/home-assistant/core.git
synced 2025-04-26 02:07:54 +00:00
Load integrations with requirements in device_automation (#33714)
* Load integrations with requirements in device_automation - Split cached loader behavior out of async_get_integration - Use cached loader for both async_get_integration and async_get_integration_with_requirements - Use async_get_integration_with_requirements for device_automation resolves #33104 * Duplicate caching logic in requirements, remove loader mods * Update homeassistant/requirements.py Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
5ff50e8b4f
commit
3b246fb40a
@ -13,7 +13,8 @@ from homeassistant.const import CONF_DEVICE_ID, CONF_DOMAIN, CONF_PLATFORM
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.entity_registry import async_entries_for_device
|
from homeassistant.helpers.entity_registry import async_entries_for_device
|
||||||
from homeassistant.loader import IntegrationNotFound, async_get_integration
|
from homeassistant.loader import IntegrationNotFound
|
||||||
|
from homeassistant.requirements import async_get_integration_with_requirements
|
||||||
|
|
||||||
from .exceptions import DeviceNotFound, InvalidDeviceAutomationConfig
|
from .exceptions import DeviceNotFound, InvalidDeviceAutomationConfig
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ async def async_get_device_automation_platform(
|
|||||||
"""
|
"""
|
||||||
platform_name = TYPES[automation_type][0]
|
platform_name = TYPES[automation_type][0]
|
||||||
try:
|
try:
|
||||||
integration = await async_get_integration(hass, domain)
|
integration = await async_get_integration_with_requirements(hass, domain)
|
||||||
platform = integration.get_platform(platform_name)
|
platform = integration.get_platform(platform_name)
|
||||||
except IntegrationNotFound:
|
except IntegrationNotFound:
|
||||||
raise InvalidDeviceAutomationConfig(f"Integration '{domain}' not found")
|
raise InvalidDeviceAutomationConfig(f"Integration '{domain}' not found")
|
||||||
|
@ -3,15 +3,21 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Iterable, List, Optional, Set
|
from typing import Any, Dict, Iterable, List, Optional, Set, Union, cast
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.loader import Integration, async_get_integration
|
from homeassistant.loader import (
|
||||||
|
Integration,
|
||||||
|
IntegrationNotFound,
|
||||||
|
_async_mount_config_dir,
|
||||||
|
async_get_integration,
|
||||||
|
)
|
||||||
import homeassistant.util.package as pkg_util
|
import homeassistant.util.package as pkg_util
|
||||||
|
|
||||||
DATA_PIP_LOCK = "pip_lock"
|
DATA_PIP_LOCK = "pip_lock"
|
||||||
DATA_PKG_CACHE = "pkg_cache"
|
DATA_PKG_CACHE = "pkg_cache"
|
||||||
|
DATA_INTEGRATIONS_WITH_REQS = "integrations_with_reqs"
|
||||||
CONSTRAINT_FILE = "package_constraints.txt"
|
CONSTRAINT_FILE = "package_constraints.txt"
|
||||||
PROGRESS_FILE = ".pip_progress"
|
PROGRESS_FILE = ".pip_progress"
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -19,6 +25,7 @@ DISCOVERY_INTEGRATIONS: Dict[str, Iterable[str]] = {
|
|||||||
"ssdp": ("ssdp",),
|
"ssdp": ("ssdp",),
|
||||||
"zeroconf": ("zeroconf", "homekit"),
|
"zeroconf": ("zeroconf", "homekit"),
|
||||||
}
|
}
|
||||||
|
_UNDEF = object()
|
||||||
|
|
||||||
|
|
||||||
class RequirementsNotFound(HomeAssistantError):
|
class RequirementsNotFound(HomeAssistantError):
|
||||||
@ -50,6 +57,27 @@ async def async_get_integration_with_requirements(
|
|||||||
if hass.config.skip_pip:
|
if hass.config.skip_pip:
|
||||||
return integration
|
return integration
|
||||||
|
|
||||||
|
cache = hass.data.get(DATA_INTEGRATIONS_WITH_REQS)
|
||||||
|
if cache is None:
|
||||||
|
cache = hass.data[DATA_INTEGRATIONS_WITH_REQS] = {}
|
||||||
|
|
||||||
|
int_or_evt: Union[Integration, asyncio.Event, None] = cache.get(domain, _UNDEF)
|
||||||
|
|
||||||
|
if isinstance(int_or_evt, asyncio.Event):
|
||||||
|
await int_or_evt.wait()
|
||||||
|
int_or_evt = cache.get(domain, _UNDEF)
|
||||||
|
|
||||||
|
# When we have waited and it's _UNDEF, it doesn't exist
|
||||||
|
# We don't cache that it doesn't exist, or else people can't fix it
|
||||||
|
# and then restart, because their config will never be valid.
|
||||||
|
if int_or_evt is _UNDEF:
|
||||||
|
raise IntegrationNotFound(domain)
|
||||||
|
|
||||||
|
if int_or_evt is not _UNDEF:
|
||||||
|
return cast(Integration, int_or_evt)
|
||||||
|
|
||||||
|
event = cache[domain] = asyncio.Event()
|
||||||
|
|
||||||
if integration.requirements:
|
if integration.requirements:
|
||||||
await async_process_requirements(
|
await async_process_requirements(
|
||||||
hass, integration.domain, integration.requirements
|
hass, integration.domain, integration.requirements
|
||||||
@ -77,6 +105,8 @@ async def async_get_integration_with_requirements(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cache[domain] = integration
|
||||||
|
event.set()
|
||||||
return integration
|
return integration
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user