From 8013c48ae9ac0ad54bf0f0a80c2d66fda2018ef7 Mon Sep 17 00:00:00 2001 From: thatmattlove Date: Mon, 4 Oct 2021 01:38:44 -0700 Subject: [PATCH] Copy plugins to module instead of kludgy import --- hyperglass/plugins/_input.py | 1 + hyperglass/plugins/_output.py | 2 ++ hyperglass/plugins/external/.gitignore | 4 ++++ hyperglass/plugins/external/__init__.py | 0 hyperglass/plugins/main.py | 15 ++++++--------- 5 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 hyperglass/plugins/external/.gitignore create mode 100644 hyperglass/plugins/external/__init__.py 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