diff --git a/.github/workflows/qc_checks.yaml b/.github/workflows/qc_checks.yaml index 9bc0484fa0..8b35066349 100644 --- a/.github/workflows/qc_checks.yaml +++ b/.github/workflows/qc_checks.yaml @@ -133,6 +133,22 @@ jobs: invoke check-server coverage run -m unittest discover -s test/ + docstyle: + name: Style [Python Docstrings] + runs-on: ubuntu-20.04 + + needs: pre-commit + continue-on-error: true + + steps: + - uses: actions/checkout@v1 + - name: Enviroment Setup + uses: ./.github/actions/setup + with: + install: true + - name: Run flake8 + run: flake8 InvenTree + coverage: name: Tests - DB [SQLite] + Coverage runs-on: ubuntu-20.04 diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index fe970ee5d4..38f085e220 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -1,5 +1,5 @@ -""" -Version information for InvenTree. +"""Version information for InvenTree. + Provides information on the current InvenTree version """ @@ -17,12 +17,12 @@ INVENTREE_SW_VERSION = "0.8.0 dev" def inventreeInstanceName(): - """ Returns the InstanceName settings for the current database """ + """Returns the InstanceName settings for the current database.""" return common.models.InvenTreeSetting.get_setting("INVENTREE_INSTANCE", "") def inventreeInstanceTitle(): - """ Returns the InstanceTitle for the current database """ + """Returns the InstanceTitle for the current database.""" if common.models.InvenTreeSetting.get_setting("INVENTREE_INSTANCE_TITLE", False): return common.models.InvenTreeSetting.get_setting("INVENTREE_INSTANCE", "") else: @@ -30,13 +30,12 @@ def inventreeInstanceTitle(): def inventreeVersion(): - """ Returns the InvenTree version string """ + """Returns the InvenTree version string.""" return INVENTREE_SW_VERSION.lower().strip() def inventreeVersionTuple(version=None): - """ Return the InvenTree version string as (maj, min, sub) tuple """ - + """Return the InvenTree version string as (maj, min, sub) tuple.""" if version is None: version = INVENTREE_SW_VERSION @@ -46,21 +45,16 @@ def inventreeVersionTuple(version=None): def isInvenTreeDevelopmentVersion(): - """ - Return True if current InvenTree version is a "development" version - """ + """Return True if current InvenTree version is a "development" version.""" return inventreeVersion().endswith('dev') def inventreeDocsVersion(): - """ - Return the version string matching the latest documentation. + """Return the version string matching the latest documentation. Development -> "latest" Release -> "major.minor.sub" e.g. "0.5.2" - """ - if isInvenTreeDevelopmentVersion(): return "latest" else: @@ -68,13 +62,10 @@ def inventreeDocsVersion(): def isInvenTreeUpToDate(): - """ - Test if the InvenTree instance is "up to date" with the latest version. + """Test if the InvenTree instance is "up to date" with the latest version. - A background task periodically queries GitHub for latest version, - and stores it to the database as INVENTREE_LATEST_VERSION + A background task periodically queries GitHub for latest version, and stores it to the database as INVENTREE_LATEST_VERSION """ - latest = common.models.InvenTreeSetting.get_setting('INVENTREE_LATEST_VERSION', backup_value=None, create=False) # No record for "latest" version - we must assume we are up to date! @@ -93,13 +84,12 @@ def inventreeApiVersion(): def inventreeDjangoVersion(): - """ Return the version of Django library """ + """Return the version of Django library.""" return django.get_version() def inventreeCommitHash(): - """ Returns the git commit hash for the running codebase """ - + """ Returns the git commit hash for the running codebase.""" # First look in the environment variables, i.e. if running in docker commit_hash = os.environ.get('INVENTREE_COMMIT_HASH', '') @@ -113,8 +103,7 @@ def inventreeCommitHash(): def inventreeCommitDate(): - """ Returns the git commit date for the running codebase """ - + """Returns the git commit date for the running codebase.""" # First look in the environment variables, e.g. if running in docker commit_date = os.environ.get('INVENTREE_COMMIT_DATE', '') diff --git a/InvenTree/common/notifications.py b/InvenTree/common/notifications.py index aa39ad20ef..ab6e0b1003 100644 --- a/InvenTree/common/notifications.py +++ b/InvenTree/common/notifications.py @@ -12,9 +12,7 @@ logger = logging.getLogger('inventree') # region methods class NotificationMethod: - """ - Base class for notification methods - """ + """Base class for notification methods.""" METHOD_NAME = '' METHOD_ICON = None @@ -92,11 +90,11 @@ class NotificationMethod: # region plugins def get_plugin(self): - """Returns plugin class""" + """Returns plugin class.""" return False def global_setting_disable(self): - """Check if the method is defined in a plugin and has a global setting""" + """Check if the method is defined in a plugin and has a global setting.""" # Check if plugin has a setting if not self.GLOBAL_SETTING: return False @@ -115,9 +113,7 @@ class NotificationMethod: return False def usersetting(self, target): - """ - Returns setting for this method for a given user - """ + """Returns setting for this method for a given user.""" return NotificationUserSetting.get_setting(f'NOTIFICATION_METHOD_{self.METHOD_NAME.upper()}', user=target, method=self.METHOD_NAME) # endregion @@ -204,10 +200,7 @@ class UIMessageNotification(SingleNotificationMethod): def trigger_notification(obj, category=None, obj_ref='pk', **kwargs): - """ - Send out a notification - """ - + """Send out a notification.""" targets = kwargs.get('targets', None) target_fnc = kwargs.get('target_fnc', None) target_args = kwargs.get('target_args', []) diff --git a/InvenTree/label/api.py b/InvenTree/label/api.py index 7988bfb32f..7b35b5b1ed 100644 --- a/InvenTree/label/api.py +++ b/InvenTree/label/api.py @@ -21,9 +21,7 @@ from .serializers import (PartLabelSerializer, StockItemLabelSerializer, class LabelListView(generics.ListAPIView): - """ - Generic API class for label templates - """ + """Generic API class for label templates.""" filter_backends = [ DjangoFilterBackend, @@ -41,13 +39,11 @@ class LabelListView(generics.ListAPIView): class LabelPrintMixin: - """ - Mixin for printing labels - """ + """Mixin for printing labels.""" def get_plugin(self, request): - """ - Return the label printing plugin associated with this request. + """Return the label printing plugin associated with this request. + This is provided in the url, e.g. ?plugin=myprinter Requires: @@ -56,7 +52,6 @@ class LabelPrintMixin: - matching plugin implements the 'labels' mixin - matching plugin is enabled """ - if not settings.PLUGINS_ENABLED: return None # pragma: no cover @@ -80,10 +75,7 @@ class LabelPrintMixin: raise NotFound(f"Plugin '{plugin_key}' not found") def print(self, request, items_to_print): - """ - Print this label template against a number of pre-validated items - """ - + """Print this label template against a number of pre-validated items.""" # Check the request to determine if the user has selected a label printing plugin plugin = self.get_plugin(request) @@ -119,26 +111,20 @@ class LabelPrintMixin: label_name += ".pdf" if plugin is not None: - """ - Label printing is to be handled by a plugin, - rather than being exported to PDF. + """Label printing is to be handled by a plugin, rather than being exported to PDF. In this case, we do the following: - Individually generate each label, exporting as an image file - Pass all the images through to the label printing plugin - Return a JSON response indicating that the printing has been offloaded - """ # Label instance label_instance = self.get_object() for idx, output in enumerate(outputs): - """ - For each output, we generate a temporary image file, - which will then get sent to the printer - """ + """For each output, we generate a temporary image file, which will then get sent to the printer.""" # Generate PDF data for the label pdf = output.get_document().write_pdf() @@ -159,20 +145,14 @@ class LabelPrintMixin: }) elif debug_mode: - """ - Contatenate all rendered templates into a single HTML string, - and return the string as a HTML response. - """ + """Contatenate all rendered templates into a single HTML string, and return the string as a HTML response.""" html = "\n".join(outputs) return HttpResponse(html) else: - """ - Concatenate all rendered pages into a single PDF object, - and return the resulting document! - """ + """Concatenate all rendered pages into a single PDF object, and return the resulting document!""" pages = [] @@ -198,15 +178,10 @@ class LabelPrintMixin: class StockItemLabelMixin: - """ - Mixin for extracting stock items from query params - """ + """Mixin for extracting stock items from query params.""" def get_items(self): - """ - Return a list of requested stock items - """ - + """Return a list of requested stock items.""" items = [] params = self.request.query_params @@ -231,25 +206,20 @@ class StockItemLabelMixin: class StockItemLabelList(LabelListView, StockItemLabelMixin): - """ - API endpoint for viewing list of StockItemLabel objects. + """API endpoint for viewing list of StockItemLabel objects. Filterable by: - enabled: Filter by enabled / disabled status - item: Filter by single stock item - items: Filter by list of stock items - """ queryset = StockItemLabel.objects.all() serializer_class = StockItemLabelSerializer def filter_queryset(self, queryset): - """ - Filter the StockItem label queryset. - """ - + """Filter the StockItem label queryset.""" queryset = super().filter_queryset(queryset) # List of StockItem objects to match against @@ -304,42 +274,30 @@ class StockItemLabelList(LabelListView, StockItemLabelMixin): class StockItemLabelDetail(generics.RetrieveUpdateDestroyAPIView): - """ - API endpoint for a single StockItemLabel object - """ + """API endpoint for a single StockItemLabel object.""" queryset = StockItemLabel.objects.all() serializer_class = StockItemLabelSerializer class StockItemLabelPrint(generics.RetrieveAPIView, StockItemLabelMixin, LabelPrintMixin): - """ - API endpoint for printing a StockItemLabel object - """ + """API endpoint for printing a StockItemLabel object.""" queryset = StockItemLabel.objects.all() serializer_class = StockItemLabelSerializer def get(self, request, *args, **kwargs): - """ - Check if valid stock item(s) have been provided. - """ - + """Check if valid stock item(s) have been provided.""" items = self.get_items() return self.print(request, items) class StockLocationLabelMixin: - """ - Mixin for extracting stock locations from query params - """ + """Mixin for extracting stock locations from query params.""" def get_locations(self): - """ - Return a list of requested stock locations - """ - + """Return a list of requested stock locations.""" locations = [] params = self.request.query_params @@ -364,8 +322,7 @@ class StockLocationLabelMixin: class StockLocationLabelList(LabelListView, StockLocationLabelMixin): - """ - API endpoint for viewiing list of StockLocationLabel objects. + """API endpoint for viewiing list of StockLocationLabel objects. Filterable by: @@ -378,10 +335,7 @@ class StockLocationLabelList(LabelListView, StockLocationLabelMixin): serializer_class = StockLocationLabelSerializer def filter_queryset(self, queryset): - """ - Filter the StockLocationLabel queryset - """ - + """Filter the StockLocationLabel queryset.""" queryset = super().filter_queryset(queryset) # List of StockLocation objects to match against @@ -436,18 +390,14 @@ class StockLocationLabelList(LabelListView, StockLocationLabelMixin): class StockLocationLabelDetail(generics.RetrieveUpdateDestroyAPIView): - """ - API endpoint for a single StockLocationLabel object - """ + """API endpoint for a single StockLocationLabel object.""" queryset = StockLocationLabel.objects.all() serializer_class = StockLocationLabelSerializer class StockLocationLabelPrint(generics.RetrieveAPIView, StockLocationLabelMixin, LabelPrintMixin): - """ - API endpoint for printing a StockLocationLabel object - """ + """API endpoint for printing a StockLocationLabel object.""" queryset = StockLocationLabel.objects.all() seiralizer_class = StockLocationLabelSerializer @@ -460,15 +410,10 @@ class StockLocationLabelPrint(generics.RetrieveAPIView, StockLocationLabelMixin, class PartLabelMixin: - """ - Mixin for extracting Part objects from query parameters - """ + """Mixin for extracting Part objects from query parameters.""" def get_parts(self): - """ - Return a list of requested Part objects - """ - + """Return a list of requested Part objects.""" parts = [] params = self.request.query_params @@ -491,9 +436,7 @@ class PartLabelMixin: class PartLabelList(LabelListView, PartLabelMixin): - """ - API endpoint for viewing list of PartLabel objects - """ + """API endpoint for viewing list of PartLabel objects.""" queryset = PartLabel.objects.all() serializer_class = PartLabelSerializer @@ -539,27 +482,20 @@ class PartLabelList(LabelListView, PartLabelMixin): class PartLabelDetail(generics.RetrieveUpdateDestroyAPIView): - """ - API endpoint for a single PartLabel object - """ + """API endpoint for a single PartLabel object.""" queryset = PartLabel.objects.all() serializer_class = PartLabelSerializer class PartLabelPrint(generics.RetrieveAPIView, PartLabelMixin, LabelPrintMixin): - """ - API endpoint for printing a PartLabel object - """ + """API endpoint for printing a PartLabel object.""" queryset = PartLabel.objects.all() serializer_class = PartLabelSerializer def get(self, request, *args, **kwargs): - """ - Check if valid part(s) have been provided - """ - + """Check if valid part(s) have been provided.""" parts = self.get_parts() return self.print(request, parts) diff --git a/InvenTree/plugin/base/label/label.py b/InvenTree/plugin/base/label/label.py index 56eaf1bc20..6880a8b3e6 100644 --- a/InvenTree/plugin/base/label/label.py +++ b/InvenTree/plugin/base/label/label.py @@ -1,4 +1,5 @@ -"""Functions to print a label to a mixin printer""" +"""Functions to print a label to a mixin printer.""" + import logging import sys import traceback @@ -16,20 +17,19 @@ from plugin.registry import registry logger = logging.getLogger('inventree') -def print_label(plugin_slug, pdf_data, filename=None, label_instance=None, user=None): - """ - Print label with the provided plugin. +def print_label(plugin_slug: str, pdf_data, filename=None, label_instance=None, user=None): + """Print label with the provided plugin. This task is nominally handled by the background worker. - If the printing fails (throws an exception) then the user is notified. - Arguments: - plugin_slug: The unique slug (key) of the plugin - pdf_data: Binary PDF data - filename: The intended name of the printed label + Args: + plugin_slug (str): The unique slug (key) of the plugin. + pdf_data: Binary PDF data. + filename: The intended name of the printed label. Defaults to None. + label_instance (Union[LabelTemplate, None], optional): The template instance that should be printed. Defaults to None. + user (Union[User, None], optional): User that should be informed of errors. Defaults to None. """ - logger.info(f"Plugin '{plugin_slug}' is printing a label '{filename}'") plugin = registry.plugins.get(plugin_slug, None) diff --git a/InvenTree/plugin/base/label/mixins.py b/InvenTree/plugin/base/label/mixins.py index 4858090739..b439d28c97 100644 --- a/InvenTree/plugin/base/label/mixins.py +++ b/InvenTree/plugin/base/label/mixins.py @@ -1,11 +1,10 @@ -"""Plugin mixin classes for label plugins""" +"""Plugin mixin classes for label plugins.""" from plugin.helpers import MixinNotImplementedError class LabelPrintingMixin: - """ - Mixin which enables direct printing of stock labels. + """Mixin which enables direct printing of stock labels. Each plugin must provide a NAME attribute, which is used to uniquely identify the printer. @@ -13,9 +12,7 @@ class LabelPrintingMixin: """ class MixinMeta: - """ - Meta options for this mixin - """ + """Meta options for this mixin.""" MIXIN_NAME = 'Label printing' def __init__(self): # pragma: no cover @@ -24,8 +21,7 @@ class LabelPrintingMixin: self.add_mixin('labels', True, __class__) def print_label(self, **kwargs): - """ - Callback to print a single label + """Callback to print a single label. kwargs: pdf_data: Raw PDF data of the rendered label @@ -36,6 +32,5 @@ class LabelPrintingMixin: filename: The filename of this PDF label user: The user who printed this label """ - # Unimplemented (to be implemented by the particular plugin class) raise MixinNotImplementedError('This Plugin must implement a `print_label` method') diff --git a/InvenTree/plugin/base/label/test_label_mixin.py b/InvenTree/plugin/base/label/test_label_mixin.py index 6ba68c9512..1a16e2d8c8 100644 --- a/InvenTree/plugin/base/label/test_label_mixin.py +++ b/InvenTree/plugin/base/label/test_label_mixin.py @@ -1,4 +1,5 @@ -"""Unit tests for the label printing mixin""" +"""Unit tests for the label printing mixin.""" + import os from django.apps import apps @@ -18,7 +19,7 @@ from stock.models import StockItem, StockLocation class LabelMixinTests(InvenTreeAPITestCase): - """Test that the Label mixin operates correctly""" + """Test that the Label mixin operates correctly.""" fixtures = [ 'category', @@ -30,14 +31,13 @@ class LabelMixinTests(InvenTreeAPITestCase): roles = 'all' def do_activate_plugin(self): - """Activate the 'samplelabel' plugin""" - + """Activate the 'samplelabel' plugin.""" config = registry.get_plugin('samplelabel').plugin_config() config.active = True config.save() def do_url(self, parts, plugin_ref, label, url_name: str = 'api-part-label-print', url_single: str = 'part', invalid: bool = False): - """Generate an URL to print a label""" + """Generate an URL to print a label.""" # Construct URL kwargs = {} if label: @@ -64,7 +64,7 @@ class LabelMixinTests(InvenTreeAPITestCase): return url def test_wrong_implementation(self): - """Test that a wrong implementation raises an error""" + """Test that a wrong implementation raises an error.""" class WrongPlugin(LabelPrintingMixin, InvenTreePlugin): pass @@ -74,8 +74,7 @@ class LabelMixinTests(InvenTreeAPITestCase): plugin.print_label(filename='test') def test_installed(self): - """Test that the sample printing plugin is installed""" - + """Test that the sample printing plugin is installed.""" # Get all label plugins plugins = registry.with_mixin('labels') self.assertEqual(len(plugins), 1) @@ -85,8 +84,7 @@ class LabelMixinTests(InvenTreeAPITestCase): self.assertEqual(len(plugins), 0) def test_api(self): - """Test that we can filter the API endpoint by mixin""" - + """Test that we can filter the API endpoint by mixin.""" url = reverse('api-plugin-list') # Try POST (disallowed) @@ -130,8 +128,7 @@ class LabelMixinTests(InvenTreeAPITestCase): self.assertEqual(data['key'], 'samplelabel') def test_printing_process(self): - """Test that a label can be printed""" - + """Test that a label can be printed.""" # Ensure the labels were created apps.get_app_config('label').create_labels() @@ -194,13 +191,13 @@ class LabelMixinTests(InvenTreeAPITestCase): self.do_activate_plugin() def run_print_test(label, qs, url_name, url_single): - """Run tests on single and multiple page printing + """Run tests on single and multiple page printing. Args: - label (_type_): class of the label - qs (_type_): class of the base queryset - url_name (_type_): url for endpoints - url_single (_type_): item lookup reference + label: class of the label + qs: class of the base queryset + url_name: url for endpoints + url_single: item lookup reference """ label = label.objects.first() qs = qs.objects.all() diff --git a/InvenTree/plugin/registry.py b/InvenTree/plugin/registry.py index 4a14341b44..574cf654ff 100644 --- a/InvenTree/plugin/registry.py +++ b/InvenTree/plugin/registry.py @@ -1,5 +1,4 @@ -""" -Registry for loading and managing multiple plugins at run-time +"""Registry for loading and managing multiple plugins at run-time. - Holds the class and the object that contains all code to maintain plugin states - Manages setup and teardown of plugin class instances @@ -31,9 +30,7 @@ logger = logging.getLogger('inventree') class PluginsRegistry: - """ - The PluginsRegistry class - """ + """The PluginsRegistry class.""" def __init__(self) -> None: """Initialize registry. @@ -59,10 +56,7 @@ class PluginsRegistry: self.mixins_settings = {} def get_plugin(self, slug): - """ - Lookup plugin by slug (unique key). - """ - + """Lookup plugin by slug (unique key).""" if slug not in self.plugins: logger.warning(f"Plugin registry has no record of plugin '{slug}'") return None @@ -70,15 +64,13 @@ class PluginsRegistry: return self.plugins[slug] def call_plugin_function(self, slug, func, *args, **kwargs): - """ - Call a member function (named by 'func') of the plugin named by 'slug'. + """Call a member function (named by 'func') of the plugin named by 'slug'. As this is intended to be run by the background worker, we do not perform any try/except here. Instead, any error messages are returned to the worker. """ - plugin = self.get_plugin(slug) if not plugin: @@ -91,7 +83,7 @@ class PluginsRegistry: # region public functions # region loading / unloading 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. @@ -154,10 +146,7 @@ class PluginsRegistry: logger.info('Finished loading plugins') def unload_plugins(self): - """ - Unload and deactivate all IntegrationPlugins - """ - + """Unload and deactivate all IntegrationPlugins.""" if not settings.PLUGINS_ENABLED: # Plugins not enabled, do nothing return # pragma: no cover @@ -181,12 +170,11 @@ class PluginsRegistry: logger.info('Finished unloading plugins') def reload_plugins(self, full_reload: bool = False): - """Safely reload IntegrationPlugins + """Safely reload. Args: full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False. """ - # Do not reload whe currently loading if self.is_loading: return # pragma: no cover @@ -200,8 +188,7 @@ class PluginsRegistry: logger.info('Finished reloading plugins') def collect_plugins(self): - """Collect plugins from all possible ways of loading""" - + """Collect plugins from all possible ways of loading.""" if not settings.PLUGINS_ENABLED: # Plugins not enabled, do nothing return # pragma: no cover @@ -230,10 +217,7 @@ class PluginsRegistry: logger.info(", ".join([a.__module__ for a in self.plugin_modules])) def install_plugin_file(self): - """ - Make sure all plugins are installed in the current enviroment - """ - + """Make sure all plugins are installed in the current enviroment.""" if settings.PLUGIN_FILE_CHECKED: logger.info('Plugin file was already checked') return True @@ -254,9 +238,7 @@ class PluginsRegistry: # region registry functions def with_mixin(self, mixin: str, active=None): - """ - Returns reference to all plugins that have a specified mixin enabled - """ + """Returns reference to all plugins that have a specified mixin enabled.""" result = [] for plugin in self.plugins.values(): @@ -277,14 +259,12 @@ class PluginsRegistry: # region general internal loading /activating / deactivating / deloading def _init_plugins(self, disabled=None): - """ - Initialise all found plugins + """Initialise all found plugins. :param disabled: loading path of disabled app, defaults to None :type disabled: str, optional :raises error: IntegrationPluginError """ - from plugin.models import PluginConfig logger.info('Starting plugin initialisation') @@ -348,7 +328,7 @@ class PluginsRegistry: self.plugins_inactive[plug_key] = plugin_db_setting # pragma: no cover def _activate_plugins(self, force_reload=False, full_reload: bool = False): - """Run activation functions for all plugins + """Run activation functions for all plugins. Args: force_reload (bool, optional): Also reload base apps. Defaults to False. @@ -363,8 +343,7 @@ class PluginsRegistry: self.activate_plugin_app(plugins, force_reload=force_reload, full_reload=full_reload) def _deactivate_plugins(self): - """Run deactivation functions for all plugins""" - + """Run deactivation functions for all plugins.""" self.deactivate_plugin_app() self.deactivate_plugin_schedule() self.deactivate_plugin_settings() @@ -437,21 +416,20 @@ class PluginsRegistry: logger.warning("activate_integration_schedule failed, database not ready") def deactivate_plugin_schedule(self): - """ - Deactivate ScheduleMixin - currently nothing is done + """Deactivate ScheduleMixin. + + Currently nothing is done here. """ pass 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. Args: plugins (dict): List of IntegrationPlugins that should be installed force_reload (bool, optional): Only reload base apps. Defaults to False. full_reload (bool, optional): Reload everything - including plugin mechanism. Defaults to False. """ - from common.models import InvenTreeSetting if settings.PLUGIN_TESTING or InvenTreeSetting.get_setting('ENABLE_PLUGINS_APP'): @@ -516,8 +494,9 @@ class PluginsRegistry: reload(app_config.module.admin) def _get_plugin_path(self, plugin): - """parse plugin path - the input can be eiter: + """Parse plugin path. + + The input can be eiter: - a local file / dir - a package """ @@ -601,13 +580,12 @@ class PluginsRegistry: clear_url_caches() def _reload_apps(self, force_reload: bool = False, full_reload: bool = False): - """Internal: reload apps using django internal functions + """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 @@ -622,9 +600,9 @@ class PluginsRegistry: self.is_loading = False def _try_reload(self, cmd, *args, **kwargs): - """ - wrapper to try reloading the apps - throws an custom error that gets handled by the loading function + """Wrapper to try reloading the apps. + + Throws an custom error that gets handled by the loading function. """ try: cmd(*args, **kwargs) @@ -638,5 +616,5 @@ registry = PluginsRegistry() def call_function(plugin_name, function_name, *args, **kwargs): - """ Global helper function to call a specific member function of a plugin """ + """Global helper function to call a specific member function of a plugin.""" return registry.call_plugin_function(plugin_name, function_name, *args, **kwargs)