mirror of
https://github.com/ivan-usov-org/bec.git
synced 2025-04-21 18:20:01 +02:00
feat: add loader/helper for widget plugins
This commit is contained in:
parent
7bebf0a3a5
commit
f78623a0c1
@ -51,6 +51,19 @@ def get_plugin_class(class_spec: str, additional_modules=None) -> type:
|
|||||||
return getattr(module, class_name)
|
return getattr(module, class_name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_widget_plugins() -> dict[str, type]:
|
||||||
|
"""
|
||||||
|
Load all widget plugins.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary with the plugin names as keys and the plugin classes as values.
|
||||||
|
"""
|
||||||
|
if not (widget_plugin := _get_available_plugins("bec.widgets.user_widgets")):
|
||||||
|
return {}
|
||||||
|
# Implemented in the plugin repo to avoid introducing a dependency on bec_widgets here.
|
||||||
|
return widget_plugin[0].get_all_plugin_widgets()
|
||||||
|
|
||||||
|
|
||||||
def get_scan_plugins() -> dict:
|
def get_scan_plugins() -> dict:
|
||||||
"""
|
"""
|
||||||
Load all scan plugins.
|
Load all scan plugins.
|
||||||
@ -88,7 +101,7 @@ def get_file_writer_plugins() -> dict:
|
|||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_metadata_schema_registry() -> tuple[dict, type[BasicScanMetadata]]:
|
def get_metadata_schema_registry() -> tuple[dict, type[BasicScanMetadata] | None]:
|
||||||
module = _get_available_plugins("bec.scans.metadata_schema")
|
module = _get_available_plugins("bec.scans.metadata_schema")
|
||||||
if len(module) == 0:
|
if len(module) == 0:
|
||||||
return {}, None
|
return {}, None
|
||||||
@ -179,3 +192,7 @@ def _import_module(module_name: str):
|
|||||||
"""
|
"""
|
||||||
module = importlib.import_module(module_name)
|
module = importlib.import_module(module_name)
|
||||||
return module
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
plugs = get_widget_plugins()
|
||||||
|
@ -309,7 +309,7 @@ class Scans:
|
|||||||
params = {}
|
params = {}
|
||||||
for cmds in partition(bundle_size, args):
|
for cmds in partition(bundle_size, args):
|
||||||
cmds_serialized = [
|
cmds_serialized = [
|
||||||
cmd._compile_function_path() if hasattr(cmd, "_compile_function_path") else cmd
|
(cmd._compile_function_path() if hasattr(cmd, "_compile_function_path") else cmd)
|
||||||
for cmd in cmds
|
for cmd in cmds
|
||||||
]
|
]
|
||||||
params[cmds_serialized[0]] = cmds_serialized[1:]
|
params[cmds_serialized[0]] = cmds_serialized[1:]
|
||||||
|
@ -137,7 +137,8 @@ class PluginStructure:
|
|||||||
|
|
||||||
self.create_dir(f"{self.plugin_name}/bec_widgets/configs")
|
self.create_dir(f"{self.plugin_name}/bec_widgets/configs")
|
||||||
self.create_dir(f"{self.plugin_name}/bec_widgets/widgets")
|
self.create_dir(f"{self.plugin_name}/bec_widgets/widgets")
|
||||||
self.create_init_file(f"{self.plugin_name}/bec_widgets/widgets")
|
widget_init = os.path.join(current_dir, "plugin_setup_files", "widgets_init_file.py")
|
||||||
|
os.system(f"cp {widget_init} {self.plugin_name}/bec_widgets/widgets/__init__.py")
|
||||||
|
|
||||||
def add_file_writer(self):
|
def add_file_writer(self):
|
||||||
self.create_dir(f"{self.plugin_name}/file_writer")
|
self.create_dir(f"{self.plugin_name}/file_writer")
|
||||||
|
53
bec_lib/util_scripts/plugin_setup_files/widgets_init_file.py
Normal file
53
bec_lib/util_scripts/plugin_setup_files/widgets_init_file.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"""Module for user-created widget files and some utilities to load them."""
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
import pkgutil
|
||||||
|
from importlib import util as importlib_util
|
||||||
|
from importlib.machinery import FileFinder, SourceFileLoader
|
||||||
|
from types import ModuleType
|
||||||
|
|
||||||
|
from bec_widgets import BECWidget
|
||||||
|
from my_plugin_repo.bec_widgets import widgets
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_plugin_widgets() -> dict[str, BECWidget]:
|
||||||
|
"""BEC uses this function to load widgets from this plugin repository. Don't modify it unless
|
||||||
|
you are absolutely certain of what you are doing!"""
|
||||||
|
return _all_widgets_from_all_submodules(widgets)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_widgets_from_module(module: ModuleType) -> dict[str, BECWidget]:
|
||||||
|
"""Find any BECWidget subclasses in the given module and return them with their names."""
|
||||||
|
return dict(
|
||||||
|
inspect.getmembers(
|
||||||
|
module,
|
||||||
|
predicate=lambda item: inspect.isclass(item)
|
||||||
|
and issubclass(item, BECWidget)
|
||||||
|
and item is not BECWidget,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _all_widgets_from_all_submodules(module):
|
||||||
|
"""Recursively load submodules, find any BECWidgets, and return them all as a flat dict."""
|
||||||
|
widgets = _get_widgets_from_module(module)
|
||||||
|
if not hasattr(module, "__path__"):
|
||||||
|
return widgets
|
||||||
|
submodule_specs = (
|
||||||
|
module_info.module_finder.find_spec(module_info.name)
|
||||||
|
for module_info in pkgutil.iter_modules(module.__path__)
|
||||||
|
if isinstance(module_info.module_finder, FileFinder)
|
||||||
|
)
|
||||||
|
for submodule in (
|
||||||
|
importlib_util.module_from_spec(spec) for spec in submodule_specs if spec is not None
|
||||||
|
):
|
||||||
|
assert isinstance(
|
||||||
|
submodule.__loader__, SourceFileLoader
|
||||||
|
), "Module found from FileFinder should have SourceFileLoader!"
|
||||||
|
submodule.__loader__.exec_module(submodule)
|
||||||
|
widgets.update(_all_widgets_from_all_submodules(submodule))
|
||||||
|
return widgets
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": # pragma: no cover
|
||||||
|
print(get_all_plugin_widgets())
|
Loading…
x
Reference in New Issue
Block a user