From 94cc74ddf0fecc090dbde90f763cffbdf5ac1bc0 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 20 Jul 2022 18:13:57 +1000 Subject: [PATCH] Allow plugins to be loaded from an external directory --- InvenTree/plugin/helpers.py | 14 ++++++++++---- InvenTree/plugin/registry.py | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/InvenTree/plugin/helpers.py b/InvenTree/plugin/helpers.py index 53326ab286..3036e6a9b6 100644 --- a/InvenTree/plugin/helpers.py +++ b/InvenTree/plugin/helpers.py @@ -172,10 +172,16 @@ class GitStatus: # region plugin finders -def get_modules(pkg): +def get_modules(pkg, path=None): """Get all modules in a package.""" context = {} - for loader, name, _ in pkgutil.walk_packages(pkg.__path__): + + if path is None: + path = pkg.__path__ + elif type(path) is not list: + path = [path] + + for loader, name, _ in pkgutil.walk_packages(path): try: module = loader.find_module(name).load_module(name) pkg_names = getattr(module, '__all__', None) @@ -199,7 +205,7 @@ def get_classes(module): return inspect.getmembers(module, inspect.isclass) -def get_plugins(pkg, baseclass): +def get_plugins(pkg, baseclass, path=None): """Return a list of all modules under a given package. - Modules must be a subclass of the provided 'baseclass' @@ -207,7 +213,7 @@ def get_plugins(pkg, baseclass): """ plugins = [] - modules = get_modules(pkg) + modules = get_modules(pkg, path=path) # Iterate through each module in the package for mod in modules: diff --git a/InvenTree/plugin/registry.py b/InvenTree/plugin/registry.py index efed23f6bb..85ecd28df1 100644 --- a/InvenTree/plugin/registry.py +++ b/InvenTree/plugin/registry.py @@ -197,7 +197,23 @@ class PluginsRegistry: # Collect plugins from paths for plugin in settings.PLUGIN_DIRS: - modules = get_plugins(importlib.import_module(plugin), InvenTreePlugin) + + parent_path = None + + # If a "path" is provided, some special handling is required + if os.path.sep in plugin: + path_split = [el for el in plugin.split(os.path.sep)] + + if len(path_split) > 0: + parent_path = os.path.sep.join(path_split[:-1]) + + if not parent_path.endswith(os.path.sep): + parent_path += os.path.sep + + plugin = path_split[-1] + + modules = get_plugins(importlib.import_module(plugin), InvenTreePlugin, path=parent_path) + if modules: [self.plugin_modules.append(item) for item in modules]