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:
parent
7c595ee2da
commit
7643820e59
3 changed files with 37 additions and 2 deletions
|
@ -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()
|
||||
|
|
|
@ -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."""
|
||||
|
||||
|
|
|
@ -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."""
|
||||
|
|
Loading…
Add table
Reference in a new issue