|
|
|
|
@ -1,8 +1,9 @@
|
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
|
|
from contextlib import suppress
|
|
|
|
|
import inspect
|
|
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
|
import importlib
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
|
|
from types import SimpleNamespace
|
|
|
|
|
from collections import namedtuple
|
|
|
|
|
@ -10,6 +11,7 @@ import sys
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
import shepherd.scheduler
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PluginLoadError(Exception):
|
|
|
|
|
@ -259,12 +261,19 @@ def find_plugins(plugin_names, plugin_dir=None):
|
|
|
|
|
raise PluginLoadError("Could not find plugin "+plugin_name)
|
|
|
|
|
|
|
|
|
|
# Scan imported module for Plugin subclass
|
|
|
|
|
attrs = [getattr(mod, name) for name in dir(mod)]
|
|
|
|
|
for attr in attrs:
|
|
|
|
|
with suppress(TypeError):
|
|
|
|
|
if issubclass(attr, Plugin):
|
|
|
|
|
plugin_classes[plugin_name] = attr
|
|
|
|
|
break
|
|
|
|
|
def is_module_plugin(member, module=mod):
|
|
|
|
|
return (inspect.isclass(member) and member.__module__ ==
|
|
|
|
|
module.__name__ and issubclass(member, Plugin))
|
|
|
|
|
|
|
|
|
|
class_list = inspect.getmembers(mod, is_module_plugin)
|
|
|
|
|
|
|
|
|
|
if class_list:
|
|
|
|
|
if len(class_list) > 1:
|
|
|
|
|
log.warning(
|
|
|
|
|
F"Plugin module {mod.__name__} has more than one shepherd.Plugin subclass.")
|
|
|
|
|
_, plugin_classes[plugin_name] = class_list[0]
|
|
|
|
|
log.info(F"Loading plugin {plugin_classes[plugin_name].__name__}"
|
|
|
|
|
" from module {mod.__name__}")
|
|
|
|
|
else:
|
|
|
|
|
raise PluginLoadError("Imported shepherd plugin modules must contain a"
|
|
|
|
|
" subclass of shepherd.plugin.Plugin, such as"
|
|
|
|
|
|