1 """Helper to import modules from asyncio."""
3 from __future__
import annotations
6 from contextlib
import suppress
10 from types
import ModuleType
15 _LOGGER = logging.getLogger(__name__)
17 DATA_IMPORT_CACHE: HassKey[dict[str, ModuleType]] =
HassKey(
"import_cache")
18 DATA_IMPORT_FUTURES: HassKey[dict[str, asyncio.Future[ModuleType]]] =
HassKey(
21 DATA_IMPORT_FAILURES: HassKey[dict[str, bool]] =
HassKey(
"import_failures")
24 def _get_module(cache: dict[str, ModuleType], name: str) -> ModuleType:
26 cache[name] = importlib.import_module(name)
31 """Import a module or return it from the cache."""
32 cache = hass.data.setdefault(DATA_IMPORT_CACHE, {})
33 if module := cache.get(name):
36 failure_cache = hass.data.setdefault(DATA_IMPORT_FAILURES, {})
37 if name
in failure_cache:
38 raise ModuleNotFoundError(f
"{name} not found", name=name)
40 import_futures = hass.data.setdefault(DATA_IMPORT_FUTURES, {})
41 if future := import_futures.get(name):
44 if name
in sys.modules:
47 import_future = hass.loop.create_future()
48 import_futures[name] = import_future
50 module = await hass.async_add_import_executor_job(_get_module, cache, name)
51 import_future.set_result(module)
52 except BaseException
as ex:
53 if isinstance(ex, ModuleNotFoundError):
54 failure_cache[name] =
True
55 import_future.set_exception(ex)
56 with suppress(BaseException):
60 import_future.result()
63 del import_futures[name]
ModuleType async_import_module(HomeAssistant hass, str name)
ModuleType _get_module(dict[str, ModuleType] cache, str name)