Add option to also reload plugin mechanisms (#3081)

This commit is contained in:
Matthias Mair 2022-05-29 00:25:40 +02:00 committed by GitHub
parent 4d8836378b
commit 9a2300d920
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 27 deletions

View File

@ -522,7 +522,7 @@ class TestSettings(helpers.InvenTreeTestCase):
# Set dynamic setting to True and rerun to launch install # Set dynamic setting to True and rerun to launch install
InvenTreeSetting.set_setting('PLUGIN_ON_STARTUP', True, self.user) InvenTreeSetting.set_setting('PLUGIN_ON_STARTUP', True, self.user)
registry.reload_plugins() registry.reload_plugins(full_reload=True)
# Check that there was anotehr run # Check that there was anotehr run
response = registry.install_plugin_file() response = registry.install_plugin_file()

View File

@ -86,9 +86,11 @@ class PluginsRegistry:
# region public functions # region public functions
# region loading / unloading # region loading / unloading
def load_plugins(self): def load_plugins(self, full_reload: bool = False):
""" """Load and activate all IntegrationPlugins
Load and activate all IntegrationPlugins
Args:
full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False.
""" """
if not settings.PLUGINS_ENABLED: if not settings.PLUGINS_ENABLED:
# Plugins not enabled, do nothing # Plugins not enabled, do nothing
@ -109,7 +111,7 @@ class PluginsRegistry:
try: try:
# We are using the db so for migrations etc we need to try this block # We are using the db so for migrations etc we need to try this block
self._init_plugins(blocked_plugin) self._init_plugins(blocked_plugin)
self._activate_plugins() self._activate_plugins(full_reload=full_reload)
registered_successful = True registered_successful = True
except (OperationalError, ProgrammingError): # pragma: no cover except (OperationalError, ProgrammingError): # pragma: no cover
# Exception if the database has not been migrated yet # Exception if the database has not been migrated yet
@ -123,7 +125,7 @@ class PluginsRegistry:
# Initialize apps without any plugins # Initialize apps without any plugins
self._clean_registry() self._clean_registry()
self._clean_installed_apps() self._clean_installed_apps()
self._activate_plugins(force_reload=True) self._activate_plugins(force_reload=True, full_reload=full_reload)
# We do not want to end in an endless loop # We do not want to end in an endless loop
retry_counter -= 1 retry_counter -= 1
@ -137,6 +139,10 @@ class PluginsRegistry:
# now the loading will re-start up with init # now the loading will re-start up with init
# disable full reload after the first round
if full_reload:
full_reload = False
# Remove maintenance mode # Remove maintenance mode
if not _maintenance: if not _maintenance:
set_maintenance_mode(False) set_maintenance_mode(False)
@ -170,9 +176,11 @@ class PluginsRegistry:
set_maintenance_mode(False) # pragma: no cover set_maintenance_mode(False) # pragma: no cover
logger.info('Finished unloading plugins') logger.info('Finished unloading plugins')
def reload_plugins(self): def reload_plugins(self, full_reload: bool = False):
""" """Safely reload IntegrationPlugins
Safely reload IntegrationPlugins
Args:
full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False.
""" """
# Do not reload whe currently loading # Do not reload whe currently loading
@ -183,7 +191,7 @@ class PluginsRegistry:
with maintenance_mode_on(): with maintenance_mode_on():
self.unload_plugins() self.unload_plugins()
self.load_plugins() self.load_plugins(full_reload)
logger.info('Finished reloading plugins') logger.info('Finished reloading plugins')
@ -335,12 +343,12 @@ class PluginsRegistry:
# save for later reference # save for later reference
self.plugins_inactive[plug_key] = plugin_db_setting # pragma: no cover self.plugins_inactive[plug_key] = plugin_db_setting # pragma: no cover
def _activate_plugins(self, force_reload=False): def _activate_plugins(self, force_reload=False, full_reload: bool = False):
""" """Run activation functions for all plugins
Run activation functions for all plugins
:param force_reload: force reload base apps, defaults to False Args:
:type force_reload: bool, optional force_reload (bool, optional): Also reload base apps. Defaults to False.
full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False.
""" """
# activate integrations # activate integrations
plugins = self.plugins.items() plugins = self.plugins.items()
@ -348,7 +356,7 @@ class PluginsRegistry:
self.activate_plugin_settings(plugins) self.activate_plugin_settings(plugins)
self.activate_plugin_schedule(plugins) self.activate_plugin_schedule(plugins)
self.activate_plugin_app(plugins, force_reload=force_reload) self.activate_plugin_app(plugins, force_reload=force_reload, full_reload=full_reload)
def _deactivate_plugins(self): def _deactivate_plugins(self):
"""Run deactivation functions for all plugins""" """Run deactivation functions for all plugins"""
@ -432,15 +440,15 @@ class PluginsRegistry:
""" """
pass pass
def activate_plugin_app(self, plugins, force_reload=False): def activate_plugin_app(self, plugins, force_reload=False, full_reload: bool = False):
""" """Activate AppMixin plugins - add custom apps and reload
Activate AppMixin plugins - add custom apps and reload
:param plugins: list of IntegrationPlugins that should be installed Args:
:type plugins: dict plugins (dict): List of IntegrationPlugins that should be installed
:param force_reload: only reload base apps, defaults to False force_reload (bool, optional): Only reload base apps. Defaults to False.
:type force_reload: bool, optional full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False.
""" """
from common.models import InvenTreeSetting from common.models import InvenTreeSetting
if settings.PLUGIN_TESTING or InvenTreeSetting.get_setting('ENABLE_PLUGINS_APP'): if settings.PLUGIN_TESTING or InvenTreeSetting.get_setting('ENABLE_PLUGINS_APP'):
@ -461,9 +469,9 @@ class PluginsRegistry:
# first startup or force loading of base apps -> registry is prob false # first startup or force loading of base apps -> registry is prob false
if self.apps_loading or force_reload: if self.apps_loading or force_reload:
self.apps_loading = False self.apps_loading = False
self._reload_apps(force_reload=True) self._reload_apps(force_reload=True, full_reload=full_reload)
else: else:
self._reload_apps() self._reload_apps(full_reload=full_reload)
# rediscover models/ admin sites # rediscover models/ admin sites
self._reregister_contrib_apps() self._reregister_contrib_apps()
@ -589,8 +597,17 @@ class PluginsRegistry:
global_pattern[0] = re_path('', include(urlpatterns)) global_pattern[0] = re_path('', include(urlpatterns))
clear_url_caches() clear_url_caches()
def _reload_apps(self, force_reload: bool = False): def _reload_apps(self, force_reload: bool = False, full_reload: bool = False):
self.is_loading = True # set flag to disable loop reloading """Internal: reload apps using django internal functions
Args:
force_reload (bool, optional): Also reload base apps. Defaults to False.
full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False.
"""
# If full_reloading is set to true we do not want to set the flag
if not full_reload:
self.is_loading = True # set flag to disable loop reloading
if force_reload: if force_reload:
# we can not use the built in functions as we need to brute force the registry # we can not use the built in functions as we need to brute force the registry
apps.app_configs = OrderedDict() apps.app_configs = OrderedDict()