2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-30 18:50:53 +00:00

Improve plugin testing (#3517)

* refactor entrypoint into helpers

* Add lookup by metadata
This is geared towards plugins packaged in pkgs that differ in name from their top module

* Make module lookup predictable in changing pkg-envs

* remove no coverage from plugin packages

* ignore coverage for production loadin

* refactor plugin collection - move assigment out

* do not cover fs errors

* test custom dir loading

* test module meta fetcher

* add a bit more safety

* do not cover sanity checkers

* add folder loading test

* ignore again for cleaner diffs for now

* ignore safety catch

* rename test

* Add test for package installs

* fix docstring name

* depreciate test for now

* Fix for out of BASE_DIR paths

* ignore catch

* remove unneeded complexity

* add testing for outside folders

* more docstrings and simpler methods

* make call simpler
This commit is contained in:
Matthias Mair
2022-08-16 05:09:48 +02:00
committed by GitHub
parent 858d48afe7
commit 188ddc3be3
7 changed files with 130 additions and 20 deletions

View File

@ -4,6 +4,7 @@
- Manages setup and teardown of plugin class instances
"""
import imp
import importlib
import logging
import os
@ -200,7 +201,7 @@ class PluginsRegistry:
if settings.TESTING:
custom_dirs = os.getenv('INVENTREE_PLUGIN_TEST_DIR', None)
else:
else: # pragma: no cover
custom_dirs = get_setting('INVENTREE_PLUGIN_DIR', 'plugin_dir')
# Load from user specified directories (unless in testing mode)
@ -215,7 +216,7 @@ class PluginsRegistry:
if not pd.exists():
try:
pd.mkdir(exist_ok=True)
except Exception:
except Exception: # pragma: no cover
logger.error(f"Could not create plugin directory '{pd}'")
continue
@ -225,24 +226,31 @@ class PluginsRegistry:
if not init_filename.exists():
try:
init_filename.write_text("# InvenTree plugin directory\n")
except Exception:
except Exception: # pragma: no cover
logger.error(f"Could not create file '{init_filename}'")
continue
# By this point, we have confirmed that the directory at least exists
if pd.exists() and pd.is_dir():
# By this point, we have confirmed that the directory at least exists
logger.info(f"Added plugin directory: '{pd}'")
dirs.append(pd)
# Convert to python dot-path
if pd.is_relative_to(settings.BASE_DIR):
pd_path = '.'.join(pd.relative_to(settings.BASE_DIR).parts)
else:
pd_path = str(pd)
# Add path
dirs.append(pd_path)
logger.info(f"Added plugin directory: '{pd}' as '{pd_path}'")
return dirs
def collect_plugins(self):
"""Collect plugins from all possible ways of loading."""
"""Collect plugins from all possible ways of loading. Returned as list."""
if not settings.PLUGINS_ENABLED:
# Plugins not enabled, do nothing
return # pragma: no cover
self.plugin_modules = [] # clear
collected_plugins = []
# Collect plugins from paths
for plugin in self.plugin_dirs():
@ -258,26 +266,33 @@ class PluginsRegistry:
parent_path = str(parent_obj.parent)
plugin = parent_obj.name
modules = get_plugins(importlib.import_module(plugin), InvenTreePlugin, path=parent_path)
# Gather Modules
if parent_path:
raw_module = imp.load_source(plugin, str(parent_obj.joinpath('__init__.py')))
else:
raw_module = importlib.import_module(plugin)
modules = get_plugins(raw_module, InvenTreePlugin, path=parent_path)
if modules:
[self.plugin_modules.append(item) for item in modules]
[collected_plugins.append(item) for item in modules]
# Check if not running in testing mode and apps should be loaded from hooks
if (not settings.PLUGIN_TESTING) or (settings.PLUGIN_TESTING and settings.PLUGIN_TESTING_SETUP):
# Collect plugins from setup entry points
for entry in get_entrypoints(): # pragma: no cover
for entry in get_entrypoints():
try:
plugin = entry.load()
plugin.is_package = True
plugin._get_package_metadata()
self.plugin_modules.append(plugin)
except Exception as error:
collected_plugins.append(plugin)
except Exception as error: # pragma: no cover
handle_error(error, do_raise=False, log_name='discovery')
# Log collected plugins
logger.info(f'Collected {len(self.plugin_modules)} plugins!')
logger.info(", ".join([a.__module__ for a in self.plugin_modules]))
logger.info(f'Collected {len(collected_plugins)} plugins!')
logger.info(", ".join([a.__module__ for a in collected_plugins]))
return collected_plugins
def install_plugin_file(self):
"""Make sure all plugins are installed in the current enviroment."""