mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
fix docstrings 5
This commit is contained in:
parent
61287dba2b
commit
391c8b4ac1
@ -1,6 +1,5 @@
|
||||
"""
|
||||
Plugin mixin classes for barcode plugin
|
||||
"""
|
||||
"""Plugin mixin classes for barcode plugin"""
|
||||
|
||||
import hashlib
|
||||
import string
|
||||
|
||||
@ -10,15 +9,13 @@ from stock.serializers import LocationSerializer, StockItemSerializer
|
||||
|
||||
|
||||
def hash_barcode(barcode_data):
|
||||
"""
|
||||
Calculate an MD5 hash of barcode data.
|
||||
"""Calculate an MD5 hash of barcode data.
|
||||
|
||||
HACK: Remove any 'non printable' characters from the hash,
|
||||
as it seems browers will remove special control characters...
|
||||
|
||||
TODO: Work out a way around this!
|
||||
"""
|
||||
|
||||
barcode_data = str(barcode_data).strip()
|
||||
|
||||
printable_chars = filter(lambda x: x in string.printable, barcode_data)
|
||||
@ -30,16 +27,16 @@ def hash_barcode(barcode_data):
|
||||
|
||||
|
||||
class BarcodeMixin:
|
||||
"""
|
||||
Mixin that enables barcode handeling
|
||||
"""Mixin that enables barcode handeling
|
||||
|
||||
Custom barcode plugins should use and extend this mixin as necessary.
|
||||
"""
|
||||
|
||||
ACTION_NAME = ""
|
||||
|
||||
class MixinMeta:
|
||||
"""
|
||||
meta options for this mixin
|
||||
"""
|
||||
"""Meta options for this mixin"""
|
||||
|
||||
MIXIN_NAME = 'Barcode'
|
||||
|
||||
def __init__(self):
|
||||
@ -48,35 +45,27 @@ class BarcodeMixin:
|
||||
|
||||
@property
|
||||
def has_barcode(self):
|
||||
"""
|
||||
Does this plugin have everything needed to process a barcode
|
||||
"""
|
||||
"""Does this plugin have everything needed to process a barcode"""
|
||||
return True
|
||||
|
||||
def init(self, barcode_data):
|
||||
"""
|
||||
Initialize the BarcodePlugin instance
|
||||
"""Initialize the BarcodePlugin instance
|
||||
|
||||
Args:
|
||||
barcode_data - The raw barcode data
|
||||
"""
|
||||
|
||||
self.data = barcode_data
|
||||
|
||||
def getStockItem(self):
|
||||
"""
|
||||
Attempt to retrieve a StockItem associated with this barcode.
|
||||
"""Attempt to retrieve a StockItem associated with this barcode.
|
||||
|
||||
Default implementation returns None
|
||||
"""
|
||||
|
||||
return None # pragma: no cover
|
||||
|
||||
def getStockItemByHash(self):
|
||||
"""Attempt to retrieve a StockItem associated with this barcode, based on the barcode hash.
|
||||
"""
|
||||
Attempt to retrieve a StockItem associated with this barcode,
|
||||
based on the barcode hash.
|
||||
"""
|
||||
|
||||
try:
|
||||
item = StockItem.objects.get(uid=self.hash())
|
||||
return item
|
||||
@ -84,48 +73,37 @@ class BarcodeMixin:
|
||||
return None
|
||||
|
||||
def renderStockItem(self, item):
|
||||
"""
|
||||
Render a stock item to JSON response
|
||||
"""
|
||||
|
||||
"""Render a stock item to JSON response"""
|
||||
serializer = StockItemSerializer(item, part_detail=True, location_detail=True, supplier_part_detail=True)
|
||||
return serializer.data
|
||||
|
||||
def getStockLocation(self):
|
||||
"""
|
||||
Attempt to retrieve a StockLocation associated with this barcode.
|
||||
"""Attempt to retrieve a StockLocation associated with this barcode.
|
||||
|
||||
Default implementation returns None
|
||||
"""
|
||||
|
||||
return None # pragma: no cover
|
||||
|
||||
def renderStockLocation(self, loc):
|
||||
"""
|
||||
Render a stock location to a JSON response
|
||||
"""
|
||||
|
||||
"""Render a stock location to a JSON response"""
|
||||
serializer = LocationSerializer(loc)
|
||||
return serializer.data
|
||||
|
||||
def getPart(self):
|
||||
"""
|
||||
Attempt to retrieve a Part associated with this barcode.
|
||||
"""Attempt to retrieve a Part associated with this barcode.
|
||||
|
||||
Default implementation returns None
|
||||
"""
|
||||
|
||||
return None # pragma: no cover
|
||||
|
||||
def renderPart(self, part):
|
||||
"""
|
||||
Render a part to JSON response
|
||||
"""
|
||||
|
||||
"""Render a part to JSON response"""
|
||||
serializer = PartSerializer(part)
|
||||
return serializer.data
|
||||
|
||||
def hash(self):
|
||||
"""
|
||||
Calculate a hash for the barcode data.
|
||||
"""Calculate a hash for the barcode data.
|
||||
|
||||
This is supposed to uniquely identify the barcode contents,
|
||||
at least within the bardcode sub-type.
|
||||
|
||||
@ -134,13 +112,9 @@ class BarcodeMixin:
|
||||
|
||||
This may be sufficient for most applications, but can obviously be overridden
|
||||
by a subclass.
|
||||
|
||||
"""
|
||||
|
||||
return hash_barcode(self.data)
|
||||
|
||||
def validate(self):
|
||||
"""
|
||||
Default implementation returns False
|
||||
"""
|
||||
"""Default implementation returns False"""
|
||||
return False # pragma: no cover
|
||||
|
@ -1,8 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Unit tests for Barcode endpoints
|
||||
"""
|
||||
"""Unit tests for Barcode endpoints"""
|
||||
|
||||
from django.urls import reverse
|
||||
|
||||
@ -62,10 +58,7 @@ class BarcodeAPITest(InvenTreeAPITestCase):
|
||||
self.assertIsNone(data['plugin'])
|
||||
|
||||
def test_find_part(self):
|
||||
"""
|
||||
Test that we can lookup a part based on ID
|
||||
"""
|
||||
|
||||
"""Test that we can lookup a part based on ID"""
|
||||
response = self.client.post(
|
||||
self.scan_url,
|
||||
{
|
||||
@ -98,10 +91,7 @@ class BarcodeAPITest(InvenTreeAPITestCase):
|
||||
self.assertEqual(response.data['part'], 'Part does not exist')
|
||||
|
||||
def test_find_stock_item(self):
|
||||
"""
|
||||
Test that we can lookup a stock item based on ID
|
||||
"""
|
||||
|
||||
"""Test that we can lookup a stock item based on ID"""
|
||||
response = self.client.post(
|
||||
self.scan_url,
|
||||
{
|
||||
@ -119,7 +109,6 @@ class BarcodeAPITest(InvenTreeAPITestCase):
|
||||
|
||||
def test_invalid_item(self):
|
||||
"""Test response for invalid stock item"""
|
||||
|
||||
response = self.client.post(
|
||||
self.scan_url,
|
||||
{
|
||||
@ -135,10 +124,7 @@ class BarcodeAPITest(InvenTreeAPITestCase):
|
||||
self.assertEqual(response.data['stockitem'], 'Stock item does not exist')
|
||||
|
||||
def test_find_location(self):
|
||||
"""
|
||||
Test that we can lookup a stock location based on ID
|
||||
"""
|
||||
|
||||
"""Test that we can lookup a stock location based on ID"""
|
||||
response = self.client.post(
|
||||
self.scan_url,
|
||||
{
|
||||
@ -156,7 +142,6 @@ class BarcodeAPITest(InvenTreeAPITestCase):
|
||||
|
||||
def test_invalid_location(self):
|
||||
"""Test response for an invalid location"""
|
||||
|
||||
response = self.client.post(
|
||||
self.scan_url,
|
||||
{
|
||||
@ -215,10 +200,7 @@ class BarcodeAPITest(InvenTreeAPITestCase):
|
||||
self.assertEqual(pk, item.pk)
|
||||
|
||||
def test_association(self):
|
||||
"""
|
||||
Test that a barcode can be associated with a StockItem
|
||||
"""
|
||||
|
||||
"""Test that a barcode can be associated with a StockItem"""
|
||||
item = StockItem.objects.get(pk=522)
|
||||
|
||||
self.assertEqual(len(item.uid), 0)
|
||||
|
@ -1,6 +1,4 @@
|
||||
"""
|
||||
Functions for triggering and responding to server side events
|
||||
"""
|
||||
"""Functions for triggering and responding to server side events"""
|
||||
|
||||
import logging
|
||||
|
||||
@ -17,13 +15,11 @@ logger = logging.getLogger('inventree')
|
||||
|
||||
|
||||
def trigger_event(event, *args, **kwargs):
|
||||
"""
|
||||
Trigger an event with optional arguments.
|
||||
"""Trigger an event with optional arguments.
|
||||
|
||||
This event will be stored in the database,
|
||||
and the worker will respond to it later on.
|
||||
"""
|
||||
|
||||
if not settings.PLUGINS_ENABLED:
|
||||
# Do nothing if plugins are not enabled
|
||||
return # pragma: no cover
|
||||
@ -44,8 +40,7 @@ def trigger_event(event, *args, **kwargs):
|
||||
|
||||
|
||||
def register_event(event, *args, **kwargs):
|
||||
"""
|
||||
Register the event with any interested plugins.
|
||||
"""Register the event with any interested plugins.
|
||||
|
||||
Note: This function is processed by the background worker,
|
||||
as it performs multiple database access operations.
|
||||
@ -80,14 +75,11 @@ def register_event(event, *args, **kwargs):
|
||||
|
||||
|
||||
def process_event(plugin_slug, event, *args, **kwargs):
|
||||
"""
|
||||
Respond to a triggered event.
|
||||
"""Respond to a triggered event.
|
||||
|
||||
This function is run by the background worker process.
|
||||
|
||||
This function may queue multiple functions to be handled by the background worker.
|
||||
"""
|
||||
|
||||
logger.info(f"Plugin '{plugin_slug}' is processing triggered event '{event}'")
|
||||
|
||||
plugin = registry.plugins.get(plugin_slug, None)
|
||||
@ -100,11 +92,10 @@ def process_event(plugin_slug, event, *args, **kwargs):
|
||||
|
||||
|
||||
def allow_table_event(table_name):
|
||||
"""
|
||||
Determine if an automatic event should be fired for a given table.
|
||||
"""Determine if an automatic event should be fired for a given table.
|
||||
|
||||
We *do not* want events to be fired for some tables!
|
||||
"""
|
||||
|
||||
if isImportingData():
|
||||
# Prevent table events during the data import process
|
||||
return False # pragma: no cover
|
||||
@ -143,10 +134,7 @@ def allow_table_event(table_name):
|
||||
|
||||
@receiver(post_save)
|
||||
def after_save(sender, instance, created, **kwargs):
|
||||
"""
|
||||
Trigger an event whenever a database entry is saved
|
||||
"""
|
||||
|
||||
"""Trigger an event whenever a database entry is saved"""
|
||||
table = sender.objects.model._meta.db_table
|
||||
|
||||
instance_id = getattr(instance, 'id', None)
|
||||
@ -173,10 +161,7 @@ def after_save(sender, instance, created, **kwargs):
|
||||
|
||||
@receiver(post_delete)
|
||||
def after_delete(sender, instance, **kwargs):
|
||||
"""
|
||||
Trigger an event whenever a database entry is deleted
|
||||
"""
|
||||
|
||||
"""Trigger an event whenever a database entry is deleted"""
|
||||
table = sender.objects.model._meta.db_table
|
||||
|
||||
if not allow_table_event(table):
|
||||
|
@ -4,24 +4,22 @@ from plugin.helpers import MixinNotImplementedError
|
||||
|
||||
|
||||
class EventMixin:
|
||||
"""
|
||||
Mixin that provides support for responding to triggered events.
|
||||
"""Mixin that provides support for responding to triggered events.
|
||||
|
||||
Implementing classes must provide a "process_event" function:
|
||||
"""
|
||||
|
||||
def process_event(self, event, *args, **kwargs):
|
||||
"""
|
||||
Function to handle events
|
||||
"""Function to handle events
|
||||
|
||||
Must be overridden by plugin
|
||||
"""
|
||||
# Default implementation does not do anything
|
||||
raise MixinNotImplementedError
|
||||
|
||||
class MixinMeta:
|
||||
"""
|
||||
Meta options for this mixin
|
||||
"""
|
||||
"""Meta options for this mixin"""
|
||||
|
||||
MIXIN_NAME = 'Events'
|
||||
|
||||
def __init__(self):
|
||||
|
@ -1,6 +1,4 @@
|
||||
"""
|
||||
Plugin mixin classes
|
||||
"""
|
||||
"""Plugin mixin classes"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
@ -21,9 +19,7 @@ logger = logging.getLogger('inventree')
|
||||
|
||||
|
||||
class SettingsMixin:
|
||||
"""
|
||||
Mixin that enables global settings for the plugin
|
||||
"""
|
||||
"""Mixin that enables global settings for the plugin"""
|
||||
|
||||
class MixinMeta:
|
||||
MIXIN_NAME = 'Settings'
|
||||
@ -35,23 +31,15 @@ class SettingsMixin:
|
||||
|
||||
@property
|
||||
def has_settings(self):
|
||||
"""
|
||||
Does this plugin use custom global settings
|
||||
"""
|
||||
"""Does this plugin use custom global settings"""
|
||||
return bool(self.settings)
|
||||
|
||||
def get_setting(self, key):
|
||||
"""
|
||||
Return the 'value' of the setting associated with this plugin
|
||||
"""
|
||||
|
||||
"""Return the 'value' of the setting associated with this plugin"""
|
||||
return PluginSetting.get_setting(key, plugin=self)
|
||||
|
||||
def set_setting(self, key, value, user=None):
|
||||
"""
|
||||
Set plugin setting value by key
|
||||
"""
|
||||
|
||||
"""Set plugin setting value by key"""
|
||||
try:
|
||||
plugin, _ = PluginConfig.objects.get_or_create(key=self.plugin_slug(), name=self.plugin_name())
|
||||
except (OperationalError, ProgrammingError): # pragma: no cover
|
||||
@ -66,8 +54,7 @@ class SettingsMixin:
|
||||
|
||||
|
||||
class ScheduleMixin:
|
||||
"""
|
||||
Mixin that provides support for scheduled tasks.
|
||||
"""Mixin that provides support for scheduled tasks.
|
||||
|
||||
Implementing classes must provide a dict object called SCHEDULED_TASKS,
|
||||
which provides information on the tasks to be scheduled.
|
||||
@ -99,9 +86,8 @@ class ScheduleMixin:
|
||||
SCHEDULED_TASKS = {}
|
||||
|
||||
class MixinMeta:
|
||||
"""
|
||||
Meta options for this mixin
|
||||
"""
|
||||
"""Meta options for this mixin"""
|
||||
|
||||
MIXIN_NAME = 'Schedule'
|
||||
|
||||
def __init__(self):
|
||||
@ -116,16 +102,11 @@ class ScheduleMixin:
|
||||
|
||||
@property
|
||||
def has_scheduled_tasks(self):
|
||||
"""
|
||||
Are tasks defined for this plugin
|
||||
"""
|
||||
"""Are tasks defined for this plugin"""
|
||||
return bool(self.scheduled_tasks)
|
||||
|
||||
def validate_scheduled_tasks(self):
|
||||
"""
|
||||
Check that the provided scheduled tasks are valid
|
||||
"""
|
||||
|
||||
"""Check that the provided scheduled tasks are valid"""
|
||||
if not self.has_scheduled_tasks:
|
||||
raise MixinImplementationError("SCHEDULED_TASKS not defined")
|
||||
|
||||
@ -147,25 +128,18 @@ class ScheduleMixin:
|
||||
raise MixinImplementationError(f"Task '{key}' is missing 'minutes' parameter")
|
||||
|
||||
def get_task_name(self, key):
|
||||
"""
|
||||
Task name for key
|
||||
"""
|
||||
"""Task name for key"""
|
||||
# Generate a 'unique' task name
|
||||
slug = self.plugin_slug()
|
||||
return f"plugin.{slug}.{key}"
|
||||
|
||||
def get_task_names(self):
|
||||
"""
|
||||
All defined task names
|
||||
"""
|
||||
"""All defined task names"""
|
||||
# Returns a list of all task names associated with this plugin instance
|
||||
return [self.get_task_name(key) for key in self.scheduled_tasks.keys()]
|
||||
|
||||
def register_tasks(self):
|
||||
"""
|
||||
Register the tasks with the database
|
||||
"""
|
||||
|
||||
"""Register the tasks with the database"""
|
||||
try:
|
||||
from django_q.models import Schedule
|
||||
|
||||
@ -182,10 +156,7 @@ class ScheduleMixin:
|
||||
func_name = task['func'].strip()
|
||||
|
||||
if '.' in func_name:
|
||||
"""
|
||||
Dotted notation indicates that we wish to run a globally defined function,
|
||||
from a specified Python module.
|
||||
"""
|
||||
"""Dotted notation indicates that we wish to run a globally defined function, from a specified Python module."""
|
||||
|
||||
Schedule.objects.create(
|
||||
name=task_name,
|
||||
@ -196,8 +167,7 @@ class ScheduleMixin:
|
||||
)
|
||||
|
||||
else:
|
||||
"""
|
||||
Non-dotted notation indicates that we wish to call a 'member function' of the calling plugin.
|
||||
"""Non-dotted notation indicates that we wish to call a 'member function' of the calling plugin.
|
||||
|
||||
This is managed by the plugin registry itself.
|
||||
"""
|
||||
@ -218,10 +188,7 @@ class ScheduleMixin:
|
||||
logger.warning("register_tasks failed, database not ready")
|
||||
|
||||
def unregister_tasks(self):
|
||||
"""
|
||||
Deregister the tasks with the database
|
||||
"""
|
||||
|
||||
"""Deregister the tasks with the database"""
|
||||
try:
|
||||
from django_q.models import Schedule
|
||||
|
||||
@ -240,14 +207,11 @@ class ScheduleMixin:
|
||||
|
||||
|
||||
class UrlsMixin:
|
||||
"""
|
||||
Mixin that enables custom URLs for the plugin
|
||||
"""
|
||||
"""Mixin that enables custom URLs for the plugin"""
|
||||
|
||||
class MixinMeta:
|
||||
"""
|
||||
Meta options for this mixin
|
||||
"""
|
||||
"""Meta options for this mixin"""
|
||||
|
||||
MIXIN_NAME = 'URLs'
|
||||
|
||||
def __init__(self):
|
||||
@ -256,54 +220,41 @@ class UrlsMixin:
|
||||
self.urls = self.setup_urls()
|
||||
|
||||
def setup_urls(self):
|
||||
"""
|
||||
Setup url endpoints for this plugin
|
||||
"""
|
||||
"""Setup url endpoints for this plugin"""
|
||||
return getattr(self, 'URLS', None)
|
||||
|
||||
@property
|
||||
def base_url(self):
|
||||
"""
|
||||
Base url for this plugin
|
||||
"""
|
||||
"""Base url for this plugin"""
|
||||
return f'{PLUGIN_BASE}/{self.slug}/'
|
||||
|
||||
@property
|
||||
def internal_name(self):
|
||||
"""
|
||||
Internal url pattern name
|
||||
"""
|
||||
"""Internal url pattern name"""
|
||||
return f'plugin:{self.slug}:'
|
||||
|
||||
@property
|
||||
def urlpatterns(self):
|
||||
"""
|
||||
Urlpatterns for this plugin
|
||||
"""
|
||||
"""Urlpatterns for this plugin"""
|
||||
if self.has_urls:
|
||||
return re_path(f'^{self.slug}/', include((self.urls, self.slug)), name=self.slug)
|
||||
return None
|
||||
|
||||
@property
|
||||
def has_urls(self):
|
||||
"""
|
||||
Does this plugin use custom urls
|
||||
"""
|
||||
"""Does this plugin use custom urls"""
|
||||
return bool(self.urls)
|
||||
|
||||
|
||||
class NavigationMixin:
|
||||
"""
|
||||
Mixin that enables custom navigation links with the plugin
|
||||
"""
|
||||
"""Mixin that enables custom navigation links with the plugin"""
|
||||
|
||||
NAVIGATION_TAB_NAME = None
|
||||
NAVIGATION_TAB_ICON = "fas fa-question"
|
||||
|
||||
class MixinMeta:
|
||||
"""
|
||||
Meta options for this mixin
|
||||
"""
|
||||
"""Meta options for this mixin"""
|
||||
|
||||
MIXIN_NAME = 'Navigation Links'
|
||||
|
||||
def __init__(self):
|
||||
@ -312,9 +263,7 @@ class NavigationMixin:
|
||||
self.navigation = self.setup_navigation()
|
||||
|
||||
def setup_navigation(self):
|
||||
"""
|
||||
Setup navigation links for this plugin
|
||||
"""
|
||||
"""Setup navigation links for this plugin"""
|
||||
nav_links = getattr(self, 'NAVIGATION', None)
|
||||
if nav_links:
|
||||
# check if needed values are configured
|
||||
@ -325,16 +274,12 @@ class NavigationMixin:
|
||||
|
||||
@property
|
||||
def has_naviation(self):
|
||||
"""
|
||||
Does this plugin define navigation elements
|
||||
"""
|
||||
"""Does this plugin define navigation elements"""
|
||||
return bool(self.navigation)
|
||||
|
||||
@property
|
||||
def navigation_name(self):
|
||||
"""
|
||||
Name for navigation tab
|
||||
"""
|
||||
"""Name for navigation tab"""
|
||||
name = getattr(self, 'NAVIGATION_TAB_NAME', None)
|
||||
if not name:
|
||||
name = self.human_name
|
||||
@ -342,21 +287,16 @@ class NavigationMixin:
|
||||
|
||||
@property
|
||||
def navigation_icon(self):
|
||||
"""
|
||||
Icon-name for navigation tab
|
||||
"""
|
||||
"""Icon-name for navigation tab"""
|
||||
return getattr(self, 'NAVIGATION_TAB_ICON', "fas fa-question")
|
||||
|
||||
|
||||
class AppMixin:
|
||||
"""
|
||||
Mixin that enables full django app functions for a plugin
|
||||
"""
|
||||
"""Mixin that enables full django app functions for a plugin"""
|
||||
|
||||
class MixinMeta:
|
||||
"""m
|
||||
Mta options for this mixin
|
||||
"""
|
||||
"""Meta options for this mixin"""
|
||||
|
||||
MIXIN_NAME = 'App registration'
|
||||
|
||||
def __init__(self):
|
||||
@ -365,15 +305,12 @@ class AppMixin:
|
||||
|
||||
@property
|
||||
def has_app(self):
|
||||
"""
|
||||
This plugin is always an app with this plugin
|
||||
"""
|
||||
"""This plugin is always an app with this plugin"""
|
||||
return True
|
||||
|
||||
|
||||
class APICallMixin:
|
||||
"""
|
||||
Mixin that enables easier API calls for a plugin
|
||||
"""Mixin that enables easier API calls for a plugin
|
||||
|
||||
Steps to set up:
|
||||
1. Add this mixin before (left of) SettingsMixin and PluginBase
|
||||
@ -424,7 +361,7 @@ class APICallMixin:
|
||||
API_TOKEN = 'Bearer'
|
||||
|
||||
class MixinMeta:
|
||||
"""meta options for this mixin"""
|
||||
"""Meta options for this mixin"""
|
||||
MIXIN_NAME = 'API calls'
|
||||
|
||||
def __init__(self):
|
||||
@ -487,8 +424,7 @@ class APICallMixin:
|
||||
|
||||
|
||||
class PanelMixin:
|
||||
"""
|
||||
Mixin which allows integration of custom 'panels' into a particular page.
|
||||
"""Mixin which allows integration of custom 'panels' into a particular page.
|
||||
|
||||
The mixin provides a number of key functionalities:
|
||||
|
||||
@ -540,17 +476,15 @@ class PanelMixin:
|
||||
self.add_mixin('panel', True, __class__)
|
||||
|
||||
def get_custom_panels(self, view, request):
|
||||
""" This method *must* be implemented by the plugin class """
|
||||
"""This method *must* be implemented by the plugin class"""
|
||||
raise MixinNotImplementedError(f"{__class__} is missing the 'get_custom_panels' method")
|
||||
|
||||
def get_panel_context(self, view, request, context):
|
||||
"""
|
||||
Build the context data to be used for template rendering.
|
||||
"""Build the context data to be used for template rendering.
|
||||
Custom class can override this to provide any custom context data.
|
||||
|
||||
(See the example in "custom_panel_sample.py")
|
||||
"""
|
||||
|
||||
# Provide some standard context items to the template for rendering
|
||||
context['plugin'] = self
|
||||
context['request'] = request
|
||||
|
@ -1,4 +1,4 @@
|
||||
""" Unit tests for base mixins for plugins """
|
||||
"""Unit tests for base mixins for plugins"""
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
@ -170,9 +170,7 @@ class APICallMixinTest(BaseMixinDefinition, TestCase):
|
||||
API_TOKEN_SETTING = 'API_TOKEN'
|
||||
|
||||
def get_external_url(self, simple: bool = True):
|
||||
'''
|
||||
returns data from the sample endpoint
|
||||
'''
|
||||
"""Returns data from the sample endpoint"""
|
||||
return self.api_call('api/users/2', simple_response=simple)
|
||||
self.mixin = MixinCls()
|
||||
|
||||
@ -263,7 +261,6 @@ class PanelMixinTests(InvenTreeTestCase):
|
||||
|
||||
def test_installed(self):
|
||||
"""Test that the sample panel plugin is installed"""
|
||||
|
||||
plugins = registry.with_mixin('panel')
|
||||
|
||||
self.assertTrue(len(plugins) > 0)
|
||||
@ -276,7 +273,6 @@ class PanelMixinTests(InvenTreeTestCase):
|
||||
|
||||
def test_disabled(self):
|
||||
"""Test that the panels *do not load* if the plugin is not enabled"""
|
||||
|
||||
plugin = registry.get_plugin('samplepanel')
|
||||
|
||||
plugin.set_setting('ENABLE_HELLO_WORLD', True)
|
||||
@ -308,7 +304,6 @@ class PanelMixinTests(InvenTreeTestCase):
|
||||
"""
|
||||
Test that the panels *do* load if the plugin is enabled
|
||||
"""
|
||||
|
||||
plugin = registry.get_plugin('samplepanel')
|
||||
|
||||
self.assertEqual(len(registry.with_mixin('panel', active=True)), 0)
|
||||
@ -383,7 +378,6 @@ class PanelMixinTests(InvenTreeTestCase):
|
||||
|
||||
def test_mixin(self):
|
||||
"""Test that ImplementationError is raised"""
|
||||
|
||||
with self.assertRaises(MixinNotImplementedError):
|
||||
class Wrong(PanelMixin, InvenTreePlugin):
|
||||
pass
|
||||
|
@ -1,4 +1,5 @@
|
||||
"""Functions to print a label to a mixin printer"""
|
||||
|
||||
import logging
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@ -10,8 +11,7 @@ logger = logging.getLogger('inventree')
|
||||
|
||||
|
||||
def print_label(plugin_slug, label_image, 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.
|
||||
|
||||
@ -21,7 +21,6 @@ def print_label(plugin_slug, label_image, label_instance=None, user=None):
|
||||
plugin_slug: The unique slug (key) of the plugin
|
||||
label_image: A PIL.Image image object to be printed
|
||||
"""
|
||||
|
||||
logger.info(f"Plugin '{plugin_slug}' is printing a label")
|
||||
|
||||
plugin = registry.plugins.get(plugin_slug, None)
|
||||
|
Loading…
Reference in New Issue
Block a user