2021-09-11 00:47:01 -07:00
|
|
|
"""Register all plugins."""
|
|
|
|
|
|
|
|
# Standard Library
|
2021-09-11 17:55:27 -07:00
|
|
|
import sys
|
|
|
|
from typing import Any, Tuple
|
|
|
|
from inspect import isclass, getmembers
|
|
|
|
from pathlib import Path
|
|
|
|
from importlib.util import module_from_spec, spec_from_file_location
|
|
|
|
|
|
|
|
# Project
|
|
|
|
from hyperglass.log import log
|
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
|
|
|
_PLUGIN_GLOBALS = {"InputPlugin": InputPlugin, "OutputPlugin": OutputPlugin, "log": log}
|
|
|
|
|
|
|
|
|
|
|
|
def _is_class(module: Any, obj: object) -> bool:
|
|
|
|
return isclass(obj) and obj.__module__ == module.__name__
|
|
|
|
|
|
|
|
|
2021-09-12 18:27:33 -07:00
|
|
|
def _register_from_module(module: Any, **kwargs: Any) -> 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))
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
def _module_from_file(file: Path) -> Any:
|
|
|
|
"""Import a plugin module from its file Path object."""
|
|
|
|
name = file.name.split(".")[0]
|
|
|
|
spec = spec_from_file_location(f"hyperglass.plugins.external.{name}", file)
|
|
|
|
module = module_from_spec(spec)
|
|
|
|
for k, v in _PLUGIN_GLOBALS.items():
|
|
|
|
setattr(module, k, v)
|
|
|
|
spec.loader.exec_module(module)
|
|
|
|
sys.modules[module.__name__] = module
|
|
|
|
return module
|
|
|
|
|
2021-09-11 00:47:01 -07:00
|
|
|
|
|
|
|
def init_plugins() -> None:
|
2021-09-11 17:55:27 -07:00
|
|
|
"""Initialize all built-in plugins."""
|
|
|
|
_register_from_module(_builtin)
|
|
|
|
|
|
|
|
|
2021-09-12 18:27:33 -07:00
|
|
|
def register_plugin(plugin_file: Path, **kwargs) -> 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-12 18:27:33 -07:00
|
|
|
results = _register_from_module(module, **kwargs)
|
2021-09-11 17:55:27 -07:00
|
|
|
return results
|
|
|
|
raise FileNotFoundError(str(plugin_file))
|