Skip to content
This repository has been archived by the owner on Nov 9, 2024. It is now read-only.

Commit

Permalink
Added support for loading plugins from multiple directories
Browse files Browse the repository at this point in the history
  • Loading branch information
nint8835 committed Mar 28, 2017
1 parent f83bbf7 commit b488075
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 40 deletions.
23 changes: 12 additions & 11 deletions jigsaw/PluginLoader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
"""
Expand All @@ -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

Expand All @@ -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:
"""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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+",
Expand Down
56 changes: 28 additions & 28 deletions tests/test_jigsaw.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,42 @@

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
assert j.get_manifest("Missing Dependency Test") is not None


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")
Expand All @@ -54,54 +54,54 @@ 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")
assert j.get_plugin_loaded("Basic Test")


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():
Expand All @@ -114,85 +114,85 @@ 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")))
assert j.get_manifest("OS Error Test") is None


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")
assert not j.get_plugin_loaded("Basic Test")


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

0 comments on commit b488075

Please sign in to comment.