|
|
|
@ -5,8 +5,10 @@ import logging
|
|
|
|
import sys
|
|
|
|
import sys
|
|
|
|
import pkgutil
|
|
|
|
import pkgutil
|
|
|
|
import pkg_resources
|
|
|
|
import pkg_resources
|
|
|
|
|
|
|
|
from configspec import ConfigSpecification
|
|
|
|
from .. import base_plugins
|
|
|
|
from .. import base_plugins
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -35,8 +37,66 @@ def plugin_attachment(hookname):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PluginInterface():
|
|
|
|
class PluginInterface():
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
|
|
def _load_interface(module, plugin_name) -> "PluginInterface":
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
Finds PluginInterface instance in a plugin and returns it.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
def is_plugininterface(member):
|
|
|
|
|
|
|
|
return isinstance(member, PluginInterface)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface_list = inspect.getmembers(module, is_plugininterface)
|
|
|
|
|
|
|
|
if not interface_list:
|
|
|
|
|
|
|
|
raise PluginLoadError("Imported shepherd plugins must contain an instance"
|
|
|
|
|
|
|
|
" of PluginInterface")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(interface_list) > 1:
|
|
|
|
|
|
|
|
log.warning(F"Plugin module {module.__name__} has more"
|
|
|
|
|
|
|
|
F" than one PluginInterface instance.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_, interface = interface_list[0]
|
|
|
|
|
|
|
|
interface._plugin_name = plugin_name
|
|
|
|
|
|
|
|
return interface
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _load_confspec(self, module):
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
If not already registered, looks for a ConfigSpecification instance in a plugin,
|
|
|
|
|
|
|
|
using a blank one by default.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
if self._confspec is not None:
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_confspec(member):
|
|
|
|
|
|
|
|
return isinstance(member, ConfigSpecification)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
confspec_list = inspect.getmembers(module, is_confspec)
|
|
|
|
|
|
|
|
if not confspec_list:
|
|
|
|
|
|
|
|
self._confspec = ConfigSpecification()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(confspec_list) > 1:
|
|
|
|
|
|
|
|
log.warning(F"Plugin {self._plugin_name} has more"
|
|
|
|
|
|
|
|
F" than one root ConfigSpecification instance.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.register_confspec(confspec_list[0][1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _load_pluginclass(self, module):
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
def __init__(self):
|
|
|
|
self._confspec = None
|
|
|
|
self._confspec = None
|
|
|
|
|
|
|
|
self._loaded = False
|
|
|
|
|
|
|
|
self._plugin_name = "<not yet loaded>"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _load_guard(self):
|
|
|
|
|
|
|
|
if self._loaded:
|
|
|
|
|
|
|
|
raise PluginLoadError("Cannot call interface register functions once"
|
|
|
|
|
|
|
|
" plugin is loaded")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def register_confspec(self, confspec):
|
|
|
|
|
|
|
|
self._load_guard()
|
|
|
|
|
|
|
|
if not isinstance(confspec, ConfigSpecification):
|
|
|
|
|
|
|
|
raise PluginLoadError("confspec must be an instance of ConfigSpecification")
|
|
|
|
|
|
|
|
self._confspec = confspec
|
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
@property
|
|
|
|
def confspec(self):
|
|
|
|
def confspec(self):
|
|
|
|
@ -121,20 +181,8 @@ def load_plugin(plugin_name, plugin_dir=None):
|
|
|
|
if not mod:
|
|
|
|
if not mod:
|
|
|
|
raise PluginLoadError("Could not find plugin "+plugin_name)
|
|
|
|
raise PluginLoadError("Could not find plugin "+plugin_name)
|
|
|
|
|
|
|
|
|
|
|
|
# Scan imported module for PluginInterface instance
|
|
|
|
interface = PluginInterface._load_interface(mod, plugin_name)
|
|
|
|
def is_plugininterface(member):
|
|
|
|
interface._load_confspec(mod)
|
|
|
|
return isinstance(member, PluginInterface)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface_list = inspect.getmembers(mod, is_plugininterface)
|
|
|
|
|
|
|
|
if not interface_list:
|
|
|
|
|
|
|
|
raise PluginLoadError("Imported shepherd plugins must contain an instance"
|
|
|
|
|
|
|
|
" of PluginInterface")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(interface_list) > 1:
|
|
|
|
|
|
|
|
log.warning(F"Plugin module {mod.__name__} has more"
|
|
|
|
|
|
|
|
F" than one PluginInterface instance.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_, interface = interface_list[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO Populate plugin interface
|
|
|
|
# TODO Populate plugin interface
|
|
|
|
|
|
|
|
|
|
|
|
|