mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
add live reloading
This commit is contained in:
parent
e3d334f467
commit
c059583b08
@ -864,7 +864,9 @@ PLUGINS = []
|
|||||||
INTEGRATION_PLUGINS = {}
|
INTEGRATION_PLUGINS = {}
|
||||||
INTEGRATION_PLUGINS_INACTIVE = {}
|
INTEGRATION_PLUGINS_INACTIVE = {}
|
||||||
INTEGRATION_PLUGIN_GLOBALSETTING = {}
|
INTEGRATION_PLUGIN_GLOBALSETTING = {}
|
||||||
INTEGRATION_APPS_LOADED = False # Marks if apps were reloaded yet
|
|
||||||
|
INTEGRATION_APPS_LOADED = False # Marks if apps were reloaded yet
|
||||||
|
INTEGRATION_APPS_PATHS = [] # Holds all added plugin_paths
|
||||||
|
|
||||||
# Test settings
|
# Test settings
|
||||||
PLUGIN_TESTING = get_setting('PLUGIN_TESTING', TESTING) # used to force enable everything plugin
|
PLUGIN_TESTING = get_setting('PLUGIN_TESTING', TESTING) # used to force enable everything plugin
|
||||||
|
@ -8,6 +8,8 @@ from typing import OrderedDict
|
|||||||
from django.apps import AppConfig, apps
|
from django.apps import AppConfig, apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.utils import OperationalError, ProgrammingError
|
from django.db.utils import OperationalError, ProgrammingError
|
||||||
|
from django.conf.urls import url
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from importlib import metadata
|
from importlib import metadata
|
||||||
@ -25,14 +27,36 @@ class PluginAppConfig(AppConfig):
|
|||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
self.collect_plugins()
|
self.collect_plugins()
|
||||||
|
self.load_plugins()
|
||||||
|
|
||||||
|
def load_plugins(self):
|
||||||
|
logger.info('Start loading plugins')
|
||||||
try:
|
try:
|
||||||
# we are using the db from here - 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()
|
self.init_plugins()
|
||||||
self.activate_integration()
|
self.activate_plugins()
|
||||||
except (OperationalError, ProgrammingError):
|
except (OperationalError, ProgrammingError):
|
||||||
# Exception if the database has not been migrated yet
|
# Exception if the database has not been migrated yet
|
||||||
pass
|
logger.info('Database not accessible while loading plugins')
|
||||||
|
logger.info('Finished loading plugins')
|
||||||
|
|
||||||
|
def unload_plugins(self):
|
||||||
|
logger.info('Start unloading plugins')
|
||||||
|
# remove all plugins from registry
|
||||||
|
# plugins = settings.INTEGRATION_PLUGINS
|
||||||
|
settings.INTEGRATION_PLUGINS = {}
|
||||||
|
# plugins_inactive = settings.INTEGRATION_PLUGINS_INACTIVE
|
||||||
|
settings.INTEGRATION_PLUGINS_INACTIVE = {}
|
||||||
|
|
||||||
|
# deactivate all integrations
|
||||||
|
self.deactivate_plugins()
|
||||||
|
logger.info('Finished unloading plugins')
|
||||||
|
|
||||||
|
def reload_plugins(self):
|
||||||
|
logger.info('Start reloading plugins')
|
||||||
|
self.unload_plugins()
|
||||||
|
self.load_plugins()
|
||||||
|
logger.info('Finished reloading plugins')
|
||||||
|
|
||||||
def collect_plugins(self):
|
def collect_plugins(self):
|
||||||
"""collect integration plugins from all possible ways of loading"""
|
"""collect integration plugins from all possible ways of loading"""
|
||||||
@ -42,6 +66,7 @@ class PluginAppConfig(AppConfig):
|
|||||||
if modules:
|
if modules:
|
||||||
[settings.PLUGINS.append(item) for item in modules]
|
[settings.PLUGINS.append(item) for item in modules]
|
||||||
|
|
||||||
|
# check if 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):
|
if (not settings.PLUGIN_TESTING) or (settings.PLUGIN_TESTING and settings.PLUGIN_TESTING_SETUP):
|
||||||
# Collect plugins from setup entry points
|
# Collect plugins from setup entry points
|
||||||
for entry in metadata.entry_points().get('inventree_plugins', []):
|
for entry in metadata.entry_points().get('inventree_plugins', []):
|
||||||
@ -93,7 +118,7 @@ class PluginAppConfig(AppConfig):
|
|||||||
# save for later reference
|
# save for later reference
|
||||||
settings.INTEGRATION_PLUGINS_INACTIVE[plug_key] = plugin_db_setting
|
settings.INTEGRATION_PLUGINS_INACTIVE[plug_key] = plugin_db_setting
|
||||||
|
|
||||||
def activate_integration(self):
|
def activate_plugins(self):
|
||||||
"""fullfill integrations for all activated plugins"""
|
"""fullfill integrations for all activated plugins"""
|
||||||
# activate integrations
|
# activate integrations
|
||||||
plugins = settings.INTEGRATION_PLUGINS.items()
|
plugins = settings.INTEGRATION_PLUGINS.items()
|
||||||
@ -105,6 +130,11 @@ class PluginAppConfig(AppConfig):
|
|||||||
# if plugin apps are enabled
|
# if plugin apps are enabled
|
||||||
self.activate_integration_app(plugins)
|
self.activate_integration_app(plugins)
|
||||||
|
|
||||||
|
def deactivate_plugins(self):
|
||||||
|
self.deactivate_integration_app()
|
||||||
|
self.deactivate_integration_globalsettings()
|
||||||
|
|
||||||
|
# region integration_globalsettings
|
||||||
def activate_integration_globalsettings(self, plugins):
|
def activate_integration_globalsettings(self, plugins):
|
||||||
from common.models import InvenTreeSetting
|
from common.models import InvenTreeSetting
|
||||||
|
|
||||||
@ -118,6 +148,20 @@ class PluginAppConfig(AppConfig):
|
|||||||
# Add to settings dir
|
# Add to settings dir
|
||||||
InvenTreeSetting.GLOBAL_SETTINGS.update(plugin_setting)
|
InvenTreeSetting.GLOBAL_SETTINGS.update(plugin_setting)
|
||||||
|
|
||||||
|
def deactivate_integration_globalsettings(self):
|
||||||
|
from common.models import InvenTreeSetting
|
||||||
|
|
||||||
|
# collect all settings
|
||||||
|
plugin_settings = {}
|
||||||
|
for _, plugin_setting in settings.INTEGRATION_PLUGIN_GLOBALSETTING.items():
|
||||||
|
plugin_settings.update(plugin_setting)
|
||||||
|
|
||||||
|
# remove settings
|
||||||
|
for setting in plugin_settings:
|
||||||
|
InvenTreeSetting.GLOBAL_SETTINGS.pop(setting)
|
||||||
|
# endregion
|
||||||
|
|
||||||
|
# region integration_app
|
||||||
def activate_integration_app(self, plugins):
|
def activate_integration_app(self, plugins):
|
||||||
from common.models import InvenTreeSetting
|
from common.models import InvenTreeSetting
|
||||||
|
|
||||||
@ -137,12 +181,43 @@ class PluginAppConfig(AppConfig):
|
|||||||
plugin_path = plugin.PLUGIN_NAME
|
plugin_path = plugin.PLUGIN_NAME
|
||||||
if plugin_path not in settings.INSTALLED_APPS:
|
if plugin_path not in settings.INSTALLED_APPS:
|
||||||
settings.INSTALLED_APPS += [plugin_path]
|
settings.INSTALLED_APPS += [plugin_path]
|
||||||
|
settings.INTEGRATION_APPS_PATHS += [plugin_path]
|
||||||
apps_changed = True
|
apps_changed = True
|
||||||
|
|
||||||
# if apps were changed reload
|
|
||||||
# TODO this is a bit jankey to be honest
|
|
||||||
if apps_changed:
|
if apps_changed:
|
||||||
apps.app_configs = OrderedDict()
|
# if apps were changed reload
|
||||||
apps.apps_ready = apps.models_ready = apps.loading = apps.ready = False
|
self._reload_apps()
|
||||||
apps.clear_cache()
|
# update urls
|
||||||
apps.populate(settings.INSTALLED_APPS)
|
self._update_urls()
|
||||||
|
|
||||||
|
def deactivate_integration_app(self):
|
||||||
|
# remove plugin from installed_apps
|
||||||
|
for plugin in settings.INTEGRATION_APPS_PATHS:
|
||||||
|
settings.INSTALLED_APPS.remove(plugin)
|
||||||
|
|
||||||
|
# reset load flag and reload apps
|
||||||
|
settings.INTEGRATION_APPS_PATHS = []
|
||||||
|
settings.INTEGRATION_APPS_LOADED = False
|
||||||
|
self._reload_apps()
|
||||||
|
|
||||||
|
# update urls
|
||||||
|
self._update_urls()
|
||||||
|
|
||||||
|
def _update_urls(self):
|
||||||
|
from InvenTree.urls import urlpatterns as root_urlpatterns
|
||||||
|
# add admin urls
|
||||||
|
new_conf = url(r'^admin/', admin.site.urls, name='inventree-admin')
|
||||||
|
for index, a in enumerate(root_urlpatterns):
|
||||||
|
if hasattr(a, 'app_name') and a.app_name == 'admin':
|
||||||
|
root_urlpatterns[index] = new_conf
|
||||||
|
print('exchanged')
|
||||||
|
break
|
||||||
|
print('done')
|
||||||
|
|
||||||
|
def _reload_apps(self):
|
||||||
|
# TODO this is a bit jankey to be honest
|
||||||
|
apps.app_configs = OrderedDict()
|
||||||
|
apps.apps_ready = apps.models_ready = apps.loading = apps.ready = False
|
||||||
|
apps.clear_cache()
|
||||||
|
apps.populate(settings.INSTALLED_APPS)
|
||||||
|
# endregion
|
||||||
|
@ -7,6 +7,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.apps import apps
|
||||||
|
|
||||||
|
|
||||||
class PluginConfig(models.Model):
|
class PluginConfig(models.Model):
|
||||||
@ -46,3 +47,23 @@ class PluginConfig(models.Model):
|
|||||||
if not self.active:
|
if not self.active:
|
||||||
name += '(not active)'
|
name += '(not active)'
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.__org_active = self.active
|
||||||
|
|
||||||
|
def save(self, force_insert=False, force_update=False, *args, **kwargs):
|
||||||
|
"""extend save method to reload plugins if the 'active' status changes"""
|
||||||
|
ret = super().save(force_insert, force_update, *args, **kwargs)
|
||||||
|
app = apps.get_app_config('plugin')
|
||||||
|
|
||||||
|
if self.active is False and self.__org_active is True:
|
||||||
|
print('deactivated')
|
||||||
|
app.reload_plugins()
|
||||||
|
|
||||||
|
elif self.active is True and self.__org_active is False:
|
||||||
|
print('activated')
|
||||||
|
app.reload_plugins()
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user