From b4880750d30de39b5002097bf8988d0bdfad132d Mon Sep 17 00:00:00 2001 From: Riley Flynn Date: Tue, 28 Mar 2017 19:42:33 -0230 Subject: [PATCH] Added support for loading plugins from multiple directories --- jigsaw/PluginLoader.py | 23 ++++++++--------- setup.py | 2 +- tests/test_jigsaw.py | 56 +++++++++++++++++++++--------------------- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/jigsaw/PluginLoader.py b/jigsaw/PluginLoader.py index 18ec4d3..3fac09a 100644 --- a/jigsaw/PluginLoader.py +++ b/jigsaw/PluginLoader.py @@ -14,11 +14,11 @@ class PluginLoader(object): Class that handles all of jigsaw's plugin management functions """ - def __init__(self, plugin_path: str="", log_level=logging.INFO, plugin_class=JigsawPlugin) -> None: + def __init__(self, plugin_paths: tuple=(), log_level=logging.INFO, plugin_class=JigsawPlugin) -> None: """ Initializes the plugin loader - :param plugin_path: Path to load plugins from + :param plugin_paths: Paths to load plugins from :param log_level: Log level :param plugin_class: Parent class of all plugins """ @@ -27,12 +27,12 @@ def __init__(self, plugin_path: str="", log_level=logging.INFO, plugin_class=Jig level=log_level) self._logger = logging.getLogger("Jigsaw") - if plugin_path == "": - self.plugin_path = os.path.join(os.getcwd(), "plugins") - self._logger.debug("No plugin path specified, using {}.".format(self.plugin_path)) + if len(plugin_paths) == 0: + self.plugin_paths = (os.path.join(os.getcwd(), "plugins"),) + self._logger.debug("No plugin path specified, using {}.".format(self.plugin_paths)) else: - self.plugin_path = plugin_path - self._logger.debug("Using specified plugin path of {}.".format(self.plugin_path)) + self.plugin_paths = plugin_paths + self._logger.debug("Using specified plugin paths of {}.".format(", ".join(self.plugin_paths))) self._plugin_class = plugin_class @@ -44,10 +44,11 @@ def load_manifests(self) -> None: """ Loads all plugin manifests on the plugin path """ - for item in os.listdir(self.plugin_path): - item_path = os.path.join(self.plugin_path, item) - if os.path.isdir(item_path): - self.load_manifest(item_path) + for path in self.plugin_paths: + for item in os.listdir(path): + item_path = os.path.join(path, item) + if os.path.isdir(item_path): + self.load_manifest(item_path) def load_manifest(self, path: str) -> None: """ diff --git a/setup.py b/setup.py index ed796ec..618fe9e 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="Jigsaw", - version="2.4.0", + version="3.0.0", packages=["jigsaw", ], license="MIT", description="A plugin framework for Python3.6+", diff --git a/tests/test_jigsaw.py b/tests/test_jigsaw.py index 11d005b..bb0d46d 100644 --- a/tests/test_jigsaw.py +++ b/tests/test_jigsaw.py @@ -10,16 +10,16 @@ def test_initializing_jigsaw_with_no_plugin_path_specified(): j = jigsaw.PluginLoader() - assert j.plugin_path == os.path.join(os.getcwd(), "plugins") + assert j.plugin_paths == (os.path.join(os.getcwd(), "plugins"), ) def test_initializing_jigsaw_with_custom_plugin_path(): - j = jigsaw.PluginLoader(os.path.join(os.getcwd(), "custom_plugins")) - assert j.plugin_path == os.path.join(os.getcwd(), "custom_plugins") + j = jigsaw.PluginLoader((os.path.join(os.getcwd(), "custom_plugins"),)) + assert j.plugin_paths == (os.path.join(os.getcwd(), "custom_plugins"), ) def test_loading_manifests(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() assert j.get_manifest("Basic Test") is not None assert j.get_manifest("Dependency Test") is not None @@ -27,25 +27,25 @@ def test_loading_manifests(): def test_getting_manifests(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() assert j.get_manifest("Basic Test") is not None def test_getting_manifest_for_missing_plugin(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() assert j.get_manifest("This should never exist") is None def test_loading_specific_manifest(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifest(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins", "BasicTest"))) assert j.get_manifest("Basic Test") is not None def test_load_plugins(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugins() assert j.get_plugin_loaded("Dependency Test") @@ -54,14 +54,14 @@ def test_load_plugins(): def test_load_specific_plugin(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Basic Test")) assert j.get_plugin_loaded("Basic Test") def test_loading_dependencies(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Dependency Test")) assert j.get_plugin_loaded("Dependency Test") @@ -69,39 +69,39 @@ def test_loading_dependencies(): def test_loading_with_missing_dependencies(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Missing Dependency Test")) assert not j.get_plugin_loaded("Missing Dependency Test") def test_getting_plugin(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Basic Test")) assert isinstance(j.get_plugin("Basic Test"), jigsaw.JigsawPlugin) def test_getting_missing_plugin(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) assert not isinstance(j.get_plugin("This should never exist"), jigsaw.JigsawPlugin) def test_getting_module(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Basic Test")) assert issubclass(j.get_module("Basic Test").Plugin, jigsaw.JigsawPlugin) def test_getting_module_of_missing_plugin(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) with pytest.raises(AttributeError): assert not issubclass(j.get_module("This should never exist").Plugin, jigsaw.JigsawPlugin) def test_getting_all_plugins(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugins() for item in j.get_all_plugins(): @@ -114,62 +114,62 @@ def test_getting_all_plugins(): def test_disable_all_plugins(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugins() j.disable_all_plugins() def test_enable_all_plugins(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugins() j.enable_all_plugins() def test_reload_all_plugins(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugins() j.reload_all_plugins() def test_reload_specific_plugin(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Basic Test")) j.reload_plugin("Basic Test") def test_load_invalid_plugin_manifest(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifest(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins", "InvalidManifestTest"))) assert j.get_manifest("Invalid Manifest Test") is None def test_loading_plugin_already_loaded(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Basic Test")) j.load_plugin(j.get_manifest("Basic Test")) def test_invalid_baseclass(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Invalid Baseclass Test")) assert not j.get_plugin_loaded("Invalid Baseclass Test") def test_error_on_plugin_load(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Error Test")) assert os.path.isfile(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins", "ErrorTest", "error.log"))) def test_oserror_on_load_plugin_manifest(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) os.mkdir(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins", "OSErrorTest", "plugin.json"))) j.load_manifest(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins", "OSErrorTest"))) os.rmdir(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins", "OSErrorTest", "plugin.json"))) @@ -177,7 +177,7 @@ def test_oserror_on_load_plugin_manifest(): def test_unload_plugin(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.load_plugin(j.get_manifest("Basic Test")) j.unload_plugin("Basic Test") @@ -185,14 +185,14 @@ def test_unload_plugin(): def test_reload_specific_manifest(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.reload_manifest(j.get_manifest("Basic Test")) assert j.get_manifest("Basic Test") is not None def test_reload_all_manifests(): - j = jigsaw.PluginLoader(os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins"))) + j = jigsaw.PluginLoader((os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "plugins")),)) j.load_manifests() j.reload_all_manifests() assert j.get_manifest("Basic Test") is not None