Improvements to PrintingOptionsSerializer (#12434)

* Fixed issue with default `driver_options on `InvenTreeLabelPlugin`

* Provide current `machine` to `LabelPrinterBaseDriver.get_printing_options_serializer`
This commit is contained in:
Dean
2026-07-23 11:15:10 +10:00
committed by GitHub
parent e3825b5aa9
commit 346d7e0a70
4 changed files with 149 additions and 10 deletions
@@ -207,6 +207,10 @@ class LabelPrinterBaseDriver(BaseDriver):
```
"""
def __init__(self, machine=None, *args, **kwargs):
"""Initialize the printing options serializer."""
super().__init__(*args, **kwargs)
copies = serializers.IntegerField(
default=1,
label=_('Copies'),
+94 -8
View File
@@ -62,7 +62,7 @@ class TestDriverMachineInterface(TestMachineRegistryMixin, TestCase):
# Check state now
self.assertEqual(len(registry.get_machine_types()), 1)
self.assertEqual(len(registry.get_driver_types()), 3)
self.assertEqual(len(registry.get_driver_types()), 4)
self.assertEqual(len(registry.get_machines()), 0)
# Check for expected machine registry errors
@@ -79,6 +79,7 @@ class TestDriverMachineInterface(TestMachineRegistryMixin, TestCase):
for slug in [
'sample-printer-driver',
'test-label-printer-api',
'test-label-printer-options',
'test-label-printer-error',
]:
instance = registry.get_driver_instance(slug)
@@ -187,23 +188,22 @@ class TestLabelPrinterMachineType(InvenTreeAPITestCase):
else:
self.assertIsNone(machine)
def create_machine(self):
def create_machine(self, driver_key):
"""Create a new label printing machine."""
registry.initialize(main=True)
PLG_KEY = 'label-printer-test-plugin'
DRIVER_KEY = 'test-label-printer-api'
# Ensure that the driver is initialized
plg_registry.set_plugin_state(PLG_KEY, True)
driver = registry.get_driver_instance(DRIVER_KEY)
driver = registry.get_driver_instance(driver_key)
self.assertIsNotNone(driver)
machine_config = MachineConfig.objects.create(
name='Test Label Printer',
machine_type='label-printer',
driver=DRIVER_KEY,
driver=driver_key,
active=True,
)
@@ -218,7 +218,7 @@ class TestLabelPrinterMachineType(InvenTreeAPITestCase):
"""Test arbitrary function calls against a machine."""
from machine.registry import call_machine_function
machine = self.create_machine()
machine = self.create_machine('test-label-printer-api')
with self.assertRaises(AttributeError):
call_machine_function(machine.pk, 'fake_function', custom_arg=123)
@@ -231,7 +231,7 @@ class TestLabelPrinterMachineType(InvenTreeAPITestCase):
"""Test the print label method."""
plugin_ref = 'inventreelabelmachine'
machine = self.create_machine()
machine = self.create_machine('test-label-printer-api')
# setup the label app
apps.get_app_config('report').create_default_labels()
@@ -297,9 +297,95 @@ class TestLabelPrinterMachineType(InvenTreeAPITestCase):
self.assertIn('is not a valid choice', str(response.data['machine']))
def test_printing_options_serializer(self):
"""Test the printing options serializer."""
plugin_ref = 'inventreelabelmachine'
machine = self.create_machine('test-label-printer-options')
machine.set_setting('LABEL', 'D', '18')
# setup the label app
apps.get_app_config('report').create_default_labels()
plg_registry.reload_plugins()
config = cast(PluginConfig, plg_registry.get_plugin(plugin_ref).plugin_config())
config.active = True
config.save()
parts = Part.objects.all()[:2]
template = LabelTemplate.objects.filter(enabled=True, model_type='part').first()
assert template
url = reverse('api-label-print')
# Test print using machine defaults (LABEL: 18)
with self.assertLogs('inventree', level='WARNING') as cm:
self.post(
url,
{
'plugin': config.key,
'items': [a.pk for a in parts],
'template': template.pk,
'machine': str(machine.pk),
},
expected_code=201,
)
# Check for expected messages
messages = [
'Printing Label: TestingLabelPrinterDriverOptions',
f'machine: {machine.pk}',
f'label: {template.pk}',
f'item: {parts[0].pk}',
f'item: {parts[1].pk}',
'options: label: 18',
]
for message in messages:
result = False
for item in cm.records:
if message in str(item):
result = True
break
self.assertTrue(result, f'Message not found: {message}')
# Test print using print options (label: 24)
with self.assertLogs('inventree', level='WARNING') as cm:
self.post(
url,
{
'plugin': config.key,
'items': [a.pk for a in parts],
'template': template.pk,
'machine': str(machine.pk),
'driver_options': {'label': '24'},
},
expected_code=201,
)
# Check for expected messages
messages = [
'Printing Label: TestingLabelPrinterDriverOptions',
f'machine: {machine.pk}',
f'label: {template.pk}',
f'item: {parts[0].pk}',
f'item: {parts[1].pk}',
'options: label: 24',
]
for message in messages:
result = False
for item in cm.records:
if message in str(item):
result = True
break
self.assertTrue(result, f'Message not found: {message}')
def test_location_invalid_pk(self):
"""Test that location property returns None for an invalid PK without raising."""
machine = self.create_machine()
machine = self.create_machine('test-label-printer-api')
machine.set_setting('LOCATION', 'M', 999999)
@@ -181,16 +181,17 @@ class InvenTreeLabelPlugin(LabelPrintingMixin, InvenTreePlugin):
label=_('Options'),
depends_on=['machine'],
field_serializer='get_driver_options',
default={},
required=False,
)
def get_driver_options(self, fields):
"""Returns the selected machines serializer."""
_, driver = get_machine_and_driver(fields['machine'])
machine, driver = get_machine_and_driver(fields['machine'])
if driver is None:
return None
return driver.get_printing_options_serializer(
self.context['request'], context=self.context
self.context['request'], context=self.context, machine=machine
)
@@ -1,6 +1,7 @@
"""Plugins for testing label machines."""
import structlog
from rest_framework import serializers
from machine.machine_type import BaseDriver
from plugin import InvenTreePlugin
@@ -46,6 +47,52 @@ class TestingLabelPrinterDriver(LabelPrinterBaseDriver):
return x * y
class TestingLabelPrinterDriverOptions(LabelPrinterBaseDriver):
"""Test driver for label printing."""
SLUG = 'test-label-printer-options'
NAME = 'Test label printer options'
DESCRIPTION = 'This is a test label printer driver for testing.'
MACHINE_SETTINGS = {
'LABEL': {
'name': 'Label Media',
'description': 'Select label media type',
'choices': [('12', '12mm'), ('18', '18mm'), ('24', '24mm')],
'default': '12',
'required': True,
}
}
def print_label(self, machine, label, item, **kwargs) -> None:
"""Override print_label."""
# Simply output some warning messages,
# which we can check for in the unit test
logger.warn('Printing Label: TestingLabelPrinterDriverOptions')
logger.warn(f'machine: {machine.pk}')
logger.warn(f'label: {label.pk}')
logger.warn(f'item: {item.pk}')
for k, v in kwargs['printing_options'].items():
logger.warn(f'options: {k}: {v}')
class PrintingOptionsSerializer(LabelPrinterBaseDriver.PrintingOptionsSerializer):
"""Printing options serializer for print driver testing."""
def __init__(self, machine=None, *args, **kwargs):
"""Initialize the printing options serializer."""
super().__init__(*args, **kwargs)
self.fields['label'].default = machine.get_setting('LABEL', 'D')
label = serializers.ChoiceField(
label='Label Media',
help_text='Select label media type',
choices=[('12', '12mm'), ('18', '18mm'), ('24', '24mm')],
default='12',
)
class TestingLabelPrinterDriverError1(LabelPrinterBaseDriver):
"""Test driver for label printing."""
@@ -93,6 +140,7 @@ class LabelPrinterMachineTest(MachineDriverMixin, SettingsMixin, InvenTreePlugin
"""Return a list of drivers registered by this plugin."""
return [
TestingLabelPrinterDriver,
TestingLabelPrinterDriverOptions,
TestingLabelPrinterDriverError1,
TestingLabelPrinterDriverError2,
TestingLabelPrinterDriverNotImplemented,