Source code for betty.plugin.lazy
"""
Lazily load plugins.
"""
from abc import abstractmethod
from collections.abc import AsyncIterator, Mapping, Sequence
from typing import Generic, TypeVar
from typing_extensions import override
from betty.factory import Factory
from betty.machine_name import MachineName
from betty.plugin import PluginRepository, Plugin, PluginNotFound
_PluginT = TypeVar("_PluginT", bound=Plugin)
[docs]
class LazyPluginRepositoryBase(PluginRepository[_PluginT], Generic[_PluginT]):
"""
Lazily load plugins.
"""
[docs]
def __init__(self, *, factory: Factory | None = None):
super().__init__(factory=factory)
self.__plugins: Mapping[str, type[_PluginT]] | None = None
[docs]
@override
async def get(self, plugin_id: MachineName) -> type[_PluginT]:
try:
return (await self._plugins())[plugin_id]
except KeyError:
raise PluginNotFound.new(plugin_id, await self.select()) from None
async def _plugins(self) -> Mapping[str, type[_PluginT]]:
"""
Get the plugins, lazily loading them when needed.
"""
if self.__plugins is None:
self.__plugins = {
plugin.plugin_id(): plugin for plugin in await self._load_plugins()
}
return self.__plugins
@abstractmethod
async def _load_plugins(self) -> Sequence[type[_PluginT]]:
"""
Load the plugins.
"""
pass
@override
async def __aiter__(self) -> AsyncIterator[type[_PluginT]]:
for plugin in (await self._plugins()).values():
yield plugin