Source code for ska_sdp_batchlet.plugins.utils
import importlib
from typing import TypeVar
__all__ = ("load_plugin", "instantiate_plugins")
BasePlugin = TypeVar("BasePlugin")
[docs]
def load_plugin(
plugin_base_class: type[BasePlugin], name: str, path: str = None, **_
) -> type[BasePlugin]:
"""
Validates and returns a plugin class.
Parameters
----------
plugin_base_class
The base class type that the plugin must inherit from.
name
The name of the plugin class to validate.
path
The module path of the plugin. If None, it will fallback
to ``plugin_base_class.DEFAULT_PACKAGE_PATH``.
Returns
-------
The validated plugin class.
Raises
------
ImportError
If the specified class is not found in the module.
TypeError
If the class is not a subclass of `plugin_base_class`.
"""
cls = None
if path:
spec = importlib.util.spec_from_file_location(
f"__temp_plugin_module_{path.split('/')[-1].split('.py')[0]}", path
)
if spec is None:
raise ImportError(f"Module not found at path '{path}'")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
else:
module_path = plugin_base_class.DEFAULT_PACKAGE_PATH
module = importlib.import_module(module_path)
try:
cls = getattr(module, name)
except AttributeError as exc:
raise ImportError(
f"Class '{name}' not found in module '{module.__name__}'"
) from exc
if not issubclass(cls, plugin_base_class):
raise TypeError(
f"{cls.__name__} must be a subclass of "
f"{plugin_base_class.__name__}"
)
return cls
[docs]
def instantiate_plugins(
plugin_base_class: type[BasePlugin], plugin_configs: list[dict]
) -> list[BasePlugin]:
"""
Instantiate plugins based on the configuration.
Parameters
----------
plugin_base_class
The base class type that the plugins must inherit from.
plugin_configs
List of plugin configurations. Each configuration is a dictionary with
following keys:
- name: Name of the plugin class to load
- path: (optional) Path to the python module which contains the
plugin class
- kwargs: (optional) Extra key-word argumments passed to the
plugin class while instantiating.
Returns
-------
List of fully initialized plugin objects
Raises
------
ImportError
If the specified class is not found in the module.
TypeError
If the class is not a subclass of `plugin_base_class`.
"""
return [
load_plugin(plugin_base_class, **plugin_config)(
**plugin_config.get("kwargs", {})
)
for plugin_config in plugin_configs
]