diff --git a/hyperglass/plugins/_input.py b/hyperglass/plugins/_input.py index 488bc22..aebc7cc 100644 --- a/hyperglass/plugins/_input.py +++ b/hyperglass/plugins/_input.py @@ -16,6 +16,7 @@ InputPluginReturn = t.Union[None, bool] class InputPlugin(HyperglassPlugin, DirectivePlugin): """Plugin to validate user input prior to running commands.""" + _type = "input" failure_reason: t.Optional[str] = None def validate(self, query: "Query") -> InputPluginReturn: diff --git a/hyperglass/plugins/_output.py b/hyperglass/plugins/_output.py index eac4567..ba7995f 100644 --- a/hyperglass/plugins/_output.py +++ b/hyperglass/plugins/_output.py @@ -21,6 +21,8 @@ OutputType = Union["OutputDataModel", Series[str]] class OutputPlugin(HyperglassPlugin, DirectivePlugin, PlatformPlugin): """Plugin to interact with device command output.""" + _type = "output" + def process(self, *, output: OutputType, query: "Query") -> OutputType: """Process or manipulate output from a device.""" log.warning("Output plugin '{}' has not implemented a 'process()' method", self.name) diff --git a/hyperglass/plugins/external/.gitignore b/hyperglass/plugins/external/.gitignore new file mode 100644 index 0000000..9beee42 --- /dev/null +++ b/hyperglass/plugins/external/.gitignore @@ -0,0 +1,4 @@ +# Ignore all files as they're imported at runtime. +* +!__init__.py +!.gitignore diff --git a/hyperglass/plugins/external/__init__.py b/hyperglass/plugins/external/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hyperglass/plugins/main.py b/hyperglass/plugins/main.py index 4fa1c51..7e9b7f5 100644 --- a/hyperglass/plugins/main.py +++ b/hyperglass/plugins/main.py @@ -2,22 +2,18 @@ # Standard Library import sys +import shutil import typing as t 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 - # Local from . import _builtin from ._input import InputPlugin from ._output import OutputPlugin from ._manager import InputPluginManager, OutputPluginManager -_PLUGIN_GLOBALS = {"InputPlugin": InputPlugin, "OutputPlugin": OutputPlugin, "log": log} - def _is_class(module: t.Any, obj: object) -> bool: if isclass(obj): @@ -50,11 +46,12 @@ def _register_from_module(module: t.Any, **kwargs: t.Any) -> t.Tuple[str, ...]: def _module_from_file(file: Path) -> t.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) + 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) module = module_from_spec(spec) - for k, v in _PLUGIN_GLOBALS.items(): - setattr(module, k, v) spec.loader.exec_module(module) return module