Source code for mrfmsim.plugin

from types import ModuleType
import sys
from collections import defaultdict
import warnings
from importlib.metadata import entry_points


[docs]def load_plugins(host_module, entry_point_group): """Load plugins into mrfmsim main package. The plugin is loaded at startup. The loading is done by searching for the entry point of installed packages. The name of the entry point is the attribute in mrfmsim to access the plugin. If the plugin with the same name is already loaded, the plugin will be renamed by the name of the plugin and the module name. ..Note:: Currently, there is no option to block certain plugins. :param list mrfmsim_module: mrfmsim module """ plugin_dict = defaultdict(list) eps = entry_points(group=entry_point_group) host_name = host_module.__name__ for ep in eps: m = ep.load() # load the module ep_dict = { "module": m, "name": ep.name, "plugins": getattr(m, f"__{host_name}_plugin__", []), } plugin_dict[ep.name].append(ep_dict) for submodule_name, module in plugin_dict.items(): submodule = getattr(host_module, submodule_name, None) if submodule is None: path = f"{host_name}.{submodule_name}" submodule = ModuleType(path) sys.modules[path] = submodule setattr(host_module, submodule_name, submodule) for ep_dict in module: for plugin in ep_dict["plugins"]: plugin_object = getattr(ep_dict["module"], plugin) plugin_name = plugin if hasattr(submodule, plugin): # use the affix of the plugin name = ep_dict["name"] affix = name.split("_")[1] if name.startswith(host_name) else name plugin_name = f"{affix}_{plugin}" warnings.warn( f"Duplicated plugin name: {plugin} in {submodule_name}, " f"import as {plugin_name}." ) # register the object setattr(submodule, plugin_name, plugin_object) return plugin_dict