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