Add loader.async_get_loaded_integration (#99440)

* Add loader.async_get_loaded_integration

* Decorate async_get_loaded_integration with @callback
This commit is contained in:
Erik Montnemery 2023-09-04 14:12:33 +02:00 committed by GitHub
parent 7c595ee2da
commit 7643820e59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 2 deletions

View File

@ -32,7 +32,7 @@ from urllib.parse import urlparse
import voluptuous as vol
import yarl
from . import block_async_io, loader, util
from . import block_async_io, util
from .const import (
ATTR_DOMAIN,
ATTR_FRIENDLY_NAME,
@ -310,6 +310,9 @@ class HomeAssistant:
def __init__(self, config_dir: str) -> None:
"""Initialize new Home Assistant object."""
# pylint: disable-next=import-outside-toplevel
from . import loader
self.loop = asyncio.get_running_loop()
self._tasks: set[asyncio.Future[Any]] = set()
self._background_tasks: set[asyncio.Future[Any]] = set()

View File

@ -25,6 +25,7 @@ from awesomeversion import (
import voluptuous as vol
from . import generated
from .core import HomeAssistant, callback
from .generated.application_credentials import APPLICATION_CREDENTIALS
from .generated.bluetooth import BLUETOOTH
from .generated.dhcp import DHCP
@ -37,7 +38,6 @@ from .util.json import JSON_DECODE_EXCEPTIONS, json_loads
# Typing imports that create a circular dependency
if TYPE_CHECKING:
from .config_entries import ConfigEntry
from .core import HomeAssistant
from .helpers import device_registry as dr
from .helpers.typing import ConfigType
@ -875,6 +875,22 @@ def _resolve_integrations_from_root(
return integrations
@callback
def async_get_loaded_integration(hass: HomeAssistant, domain: str) -> Integration:
"""Get an integration which is already loaded.
Raises IntegrationNotLoaded if the integration is not loaded.
"""
cache = hass.data[DATA_INTEGRATIONS]
if TYPE_CHECKING:
cache = cast(dict[str, Integration | asyncio.Future[None]], cache)
int_or_fut = cache.get(domain, _UNDEF)
# Integration is never subclassed, so we can check for type
if type(int_or_fut) is Integration: # noqa: E721
return int_or_fut
raise IntegrationNotLoaded(domain)
async def async_get_integration(hass: HomeAssistant, domain: str) -> Integration:
"""Get integration."""
integrations_or_excs = await async_get_integrations(hass, [domain])
@ -970,6 +986,15 @@ class IntegrationNotFound(LoaderError):
self.domain = domain
class IntegrationNotLoaded(LoaderError):
"""Raised when a component is not loaded."""
def __init__(self, domain: str) -> None:
"""Initialize a component not found error."""
super().__init__(f"Integration '{domain}' not loaded.")
self.domain = domain
class CircularDependency(LoaderError):
"""Raised when a circular dependency is found when resolving components."""

View File

@ -150,10 +150,17 @@ async def test_custom_integration_version_not_valid(
async def test_get_integration(hass: HomeAssistant) -> None:
"""Test resolving integration."""
with pytest.raises(loader.IntegrationNotLoaded):
loader.async_get_loaded_integration(hass, "hue")
integration = await loader.async_get_integration(hass, "hue")
assert hue == integration.get_component()
assert hue_light == integration.get_platform("light")
integration = loader.async_get_loaded_integration(hass, "hue")
assert hue == integration.get_component()
assert hue_light == integration.get_platform("light")
async def test_get_integration_exceptions(hass: HomeAssistant) -> None:
"""Test resolving integration."""