2021-09-11 00:47:01 -07:00
|
|
|
"""Register all plugins."""
|
|
|
|
|
|
|
|
# Standard Library
|
2021-09-11 17:55:27 -07:00
|
|
|
import sys
|
2021-10-04 01:38:44 -07:00
|
|
|
import shutil
|
2021-09-16 17:12:30 -07:00
|
|
|
import typing as t
|
2021-09-11 17:55:27 -07:00
|
|
|
from inspect import isclass, getmembers
|
|
|
|
from pathlib import Path
|
|
|
|
from importlib.util import module_from_spec, spec_from_file_location
|
|
|
|
|
2021-09-11 00:47:01 -07:00
|
|
|
# Local
|
|
|
|
from . import _builtin
|
2021-09-11 11:17:38 -07:00
|
|
|
from ._input import InputPlugin
|
2021-09-11 00:47:01 -07:00
|
|
|
from ._output import OutputPlugin
|
2021-09-11 11:17:38 -07:00
|
|
|
from ._manager import InputPluginManager, OutputPluginManager
|
2021-09-11 00:47:01 -07:00
|
|
|
|
2021-09-11 17:55:27 -07:00
|
|
|
|
2021-09-16 17:12:30 -07:00
|
|
|
def _is_class(module: t.Any, obj: object) -> bool:
|
2021-09-13 14:10:50 -07:00
|
|
|
if isclass(obj):
|
|
|
|
# Get the object's containing module name.
|
|
|
|
obj_module_name: str = getattr(obj, "__module__", "")
|
|
|
|
# Get the module's name.
|
|
|
|
module_name: str = getattr(module, "__name__", None)
|
|
|
|
# Only validate objects that are members of the module.
|
|
|
|
return module_name in obj_module_name
|
|
|
|
return False
|
2021-09-11 17:55:27 -07:00
|
|
|
|
|
|
|
|
2021-09-16 17:12:30 -07:00
|
|
|
def _register_from_module(module: t.Any, **kwargs: t.Any) -> t.Tuple[str, ...]:
|
2021-09-11 17:55:27 -07:00
|
|
|
"""Register defined classes from the module."""
|
|
|
|
failures = ()
|
|
|
|
defs = getmembers(module, lambda o: _is_class(module, o))
|
2021-09-15 00:57:45 -07:00
|
|
|
sys.modules[module.__name__] = module
|
2021-09-11 17:55:27 -07:00
|
|
|
for name, plugin in defs:
|
|
|
|
if issubclass(plugin, OutputPlugin):
|
|
|
|
manager = OutputPluginManager()
|
|
|
|
elif issubclass(plugin, InputPlugin):
|
|
|
|
manager = InputPluginManager()
|
|
|
|
else:
|
|
|
|
failures += (name,)
|
|
|
|
continue
|
2021-09-12 18:27:33 -07:00
|
|
|
manager.register(plugin, **kwargs)
|
2021-09-11 17:55:27 -07:00
|
|
|
return failures
|
|
|
|
return failures
|
|
|
|
|
|
|
|
|
2021-09-16 17:12:30 -07:00
|
|
|
def _module_from_file(file: Path) -> t.Any:
|
2021-09-11 17:55:27 -07:00
|
|
|
"""Import a plugin module from its file Path object."""
|
2021-10-04 01:38:44 -07:00
|
|
|
plugins_dir = Path(__file__).parent / "external"
|
|
|
|
dst = plugins_dir / f"imported_{file.name}"
|
|
|
|
shutil.copy2(file, dst)
|
|
|
|
name = f"imported_{file.name.split('.')[0]}"
|
|
|
|
spec = spec_from_file_location(f"hyperglass.plugins.external.{name}", dst)
|
2021-09-11 17:55:27 -07:00
|
|
|
module = module_from_spec(spec)
|
|
|
|
spec.loader.exec_module(module)
|
|
|
|
return module
|
|
|
|
|
2021-09-11 00:47:01 -07:00
|
|
|
|
2021-09-13 14:10:50 -07:00
|
|
|
def init_builtin_plugins() -> None:
|
2021-09-11 17:55:27 -07:00
|
|
|
"""Initialize all built-in plugins."""
|
|
|
|
_register_from_module(_builtin)
|
|
|
|
|
|
|
|
|
2021-09-16 17:12:30 -07:00
|
|
|
def register_plugin(plugin_file: Path, **kwargs) -> t.Tuple[str, ...]:
|
2021-09-11 17:55:27 -07:00
|
|
|
"""Register an external plugin by file path."""
|
|
|
|
if plugin_file.exists():
|
|
|
|
module = _module_from_file(plugin_file)
|
2021-09-26 11:39:46 -07:00
|
|
|
results = _register_from_module(module, ref=plugin_file.stem, **kwargs)
|
2021-09-11 17:55:27 -07:00
|
|
|
return results
|
|
|
|
raise FileNotFoundError(str(plugin_file))
|