Plugin API refactor (#3637)

* out-of-scope: refactor plugin lookup

* lookup by settings (runtime not predefined)

* Add registry function to set state of plugin quickly

* Ensure plugin is active before assertations
This commit is contained in:
Matthias Mair 2022-10-17 13:08:28 +02:00 committed by GitHub
parent 0b0594c7ff
commit 0bab40fe88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 11 deletions

View File

@ -11,6 +11,7 @@ from django.urls import reverse
from InvenTree.api_tester import InvenTreeAPITestCase, PluginMixin
from InvenTree.helpers import InvenTreeTestCase, str2bool
from plugin import registry
from plugin.models import NotificationUserSetting
from .api import WebhookView
@ -560,6 +561,9 @@ class PluginSettingsApiTest(PluginMixin, InvenTreeAPITestCase):
def test_valid_plugin_slug(self):
"""Test that an valid plugin slug runs through."""
# Activate plugin
registry.set_plugin_state('sample', True)
# get data
url = reverse('api-plugin-setting-detail', kwargs={'plugin': 'sample', 'key': 'API_KEY'})
response = self.get(url, expected_code=200)

View File

@ -16,6 +16,7 @@ from plugin.base.action.api import ActionPluginView
from plugin.base.barcodes.api import barcode_api_urls
from plugin.base.locate.api import LocatePluginView
from plugin.models import PluginConfig, PluginSetting
from plugin.plugin import InvenTreePlugin
from plugin.registry import registry
@ -146,6 +147,38 @@ class PluginSettingList(ListAPI):
]
def check_plugin(plugin_slug: str) -> InvenTreePlugin:
"""Check that a plugin for the provided slug exsists and get the config.
Args:
plugin_slug (str): Slug for plugin.
Raises:
NotFound: If plugin is not installed
NotFound: If plugin is not correctly registered
NotFound: If plugin is not active
Returns:
InvenTreePlugin: The config object for the provided plugin.
"""
# Check that the 'plugin' specified is valid!
if not PluginConfig.objects.filter(key=plugin_slug).exists():
raise NotFound(detail=f"Plugin '{plugin_slug}' not installed")
# Get the list of settings available for the specified plugin
plugin = registry.get_plugin(plugin_slug)
if plugin is None:
# This only occurs if the plugin mechanism broke
raise NotFound(detail=f"Plugin '{plugin_slug}' not found") # pragma: no cover
# Check that the plugin is activated
if not plugin.is_active():
raise NotFound(detail=f"Plugin '{plugin_slug}' is not active")
return plugin
class PluginSettingDetail(RetrieveUpdateAPI):
"""Detail endpoint for a plugin-specific setting.
@ -164,18 +197,10 @@ class PluginSettingDetail(RetrieveUpdateAPI):
plugin_slug = self.kwargs['plugin']
key = self.kwargs['key']
# Check that the 'plugin' specified is valid!
if not PluginConfig.objects.filter(key=plugin_slug).exists():
raise NotFound(detail=f"Plugin '{plugin_slug}' not installed")
# Look up plugin
plugin = check_plugin(plugin_slug)
# Get the list of settings available for the specified plugin
plugin = registry.get_plugin(plugin_slug)
if plugin is None:
# This only occurs if the plugin mechanism broke
raise NotFound(detail=f"Plugin '{plugin_slug}' not found") # pragma: no cover
settings = getattr(plugin, 'SETTINGS', {})
settings = getattr(plugin, 'settings', {})
if key not in settings:
raise NotFound(detail=f"Plugin '{plugin_slug}' has no setting matching '{key}'")

View File

@ -67,6 +67,21 @@ class PluginsRegistry:
return self.plugins[slug]
def set_plugin_state(self, slug, state):
"""Set the state(active/inactive) of a plugin.
Args:
slug (str): Plugin slug
state (bool): Plugin state - true = active, false = inactive
"""
if slug not in self.plugins_full:
logger.warning(f"Plugin registry has no record of plugin '{slug}'")
return
plugin = self.plugins_full[slug].db
plugin.active = state
plugin.save()
def call_plugin_function(self, slug, func, *args, **kwargs):
"""Call a member function (named by 'func') of the plugin named by 'slug'.