diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 1fed551bdf..ad564185b8 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,12 +1,15 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 410 +INVENTREE_API_VERSION = 411 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v411 -> 2025-06-19 : https://github.com/inventree/InvenTree/pull/10630 + - Editorialy changes to machine api - no functional changes + v410 -> 2025-06-12 : https://github.com/inventree/InvenTree/pull/9761 - Add supplier search and import API endpoints - Add part parameter bulk create API endpoint diff --git a/src/backend/InvenTree/machine/api.py b/src/backend/InvenTree/machine/api.py index 1f370d5974..24342cc3f9 100644 --- a/src/backend/InvenTree/machine/api.py +++ b/src/backend/InvenTree/machine/api.py @@ -166,7 +166,7 @@ class MachineTypesList(APIView): @extend_schema(responses={200: MachineSerializers.MachineTypeSerializer(many=True)}) def get(self, request): - """List all machine types.""" + """List of all machine types.""" machine_types = list(registry.get_machine_types()) results = MachineSerializers.MachineTypeSerializer( machine_types, many=True diff --git a/src/backend/InvenTree/machine/machine_type.py b/src/backend/InvenTree/machine/machine_type.py index 13be37be38..65532b7218 100644 --- a/src/backend/InvenTree/machine/machine_type.py +++ b/src/backend/InvenTree/machine/machine_type.py @@ -48,6 +48,9 @@ class MachineStatus(StatusCode): """ +MachinePropertyType = Literal['str', 'bool', 'progress', 'int', 'float'] + + class MachineProperty(TypedDict, total=False): """Type definition for machine properties. @@ -62,7 +65,7 @@ class MachineProperty(TypedDict, total=False): key: str value: Union[str, bool, int, float] group: str - type: Literal['str', 'bool', 'progress', 'int', 'float'] + type: MachinePropertyType max_progress: Union[int, None] diff --git a/src/backend/InvenTree/machine/models.py b/src/backend/InvenTree/machine/models.py index fd8c62df34..b81b1c7a00 100755 --- a/src/backend/InvenTree/machine/models.py +++ b/src/backend/InvenTree/machine/models.py @@ -11,6 +11,7 @@ from django.utils.translation import gettext_lazy as _ import common.models from machine import registry +from machine.machine_type import BaseMachineType class MachineConfig(models.Model): @@ -83,7 +84,7 @@ class MachineConfig(models.Model): return machine @property - def machine(self): + def machine(self) -> Optional[BaseMachineType]: """Machine instance getter.""" return registry.get_machine(self.pk) diff --git a/src/backend/InvenTree/machine/registry.py b/src/backend/InvenTree/machine/registry.py index bc6480d2bb..4fd442bbe2 100644 --- a/src/backend/InvenTree/machine/registry.py +++ b/src/backend/InvenTree/machine/registry.py @@ -384,7 +384,7 @@ class MachineRegistry( return list(self.machine_types.values()) @machine_registry_entrypoint() - def get_machine(self, pk: Union[str, UUID]): + def get_machine(self, pk: Union[str, UUID]) -> Optional[BaseMachineType]: """Get machine from registry by pk.""" return self.machines.get(str(pk), None) diff --git a/src/backend/InvenTree/machine/serializers.py b/src/backend/InvenTree/machine/serializers.py index 1105bd391c..303b1e45d6 100644 --- a/src/backend/InvenTree/machine/serializers.py +++ b/src/backend/InvenTree/machine/serializers.py @@ -2,16 +2,19 @@ from typing import Union +from django.utils.translation import gettext_lazy as _ + from rest_framework import serializers from common.serializers import GenericReferencedSettingSerializer from InvenTree.helpers_mixin import ClassProviderMixin from machine import registry +from machine.machine_type import MachinePropertyType from machine.models import MachineConfig, MachineSetting class MachinePropertySerializer(serializers.Serializer): - """Serializer for a MachineProperty.""" + """Machine Properties are set by the driver/machine to represent specific state.""" class Meta: """Meta for serializer.""" @@ -19,11 +22,28 @@ class MachinePropertySerializer(serializers.Serializer): fields = ['key', 'value', 'group', 'type', 'max_progress'] read_only_fields = fields - key = serializers.CharField() - value = serializers.CharField() - group = serializers.CharField() - type = serializers.CharField() - max_progress = serializers.IntegerField() + key = serializers.CharField( + label=_('Key'), help_text=_('Key of the property'), required=True + ) + value = serializers.CharField( + label=_('Value'), help_text=_('Value of the property'), required=True + ) + group = serializers.CharField( + label=_('Group'), help_text=_('Grouping of the property'), required=False + ) + type = serializers.ChoiceField( + label=_('Type'), + choices=MachinePropertyType.__args__, + help_text=_('Type of the property'), + default='str', + required=False, + ) + max_progress = serializers.IntegerField( + label=_('Max Progress'), + help_text=_('Maximum value for progress type, required if type=progress'), + required=False, + allow_null=True, + ) class MachineConfigSerializer(serializers.ModelSerializer): @@ -66,35 +86,35 @@ class MachineConfigSerializer(serializers.ModelSerializer): ) def get_initialized(self, obj: MachineConfig) -> bool: - """Serializer method for the initialized field.""" + """Indicator if machine is initialized.""" return getattr(obj.machine, 'initialized', False) def get_status(self, obj: MachineConfig) -> int: - """Serializer method for the status field.""" + """Numerical machine status if available, else -1.""" status = getattr(obj.machine, 'status', None) if status is not None: return status.value return -1 def get_status_model(self, obj: MachineConfig) -> Union[str, None]: - """Serializer method for the status model field.""" + """Textual machine status name if available, else None.""" if obj.machine and obj.machine.MACHINE_STATUS: return obj.machine.MACHINE_STATUS.__name__ def get_status_text(self, obj: MachineConfig) -> str: - """Serializer method for the status text field.""" + """Current status text for machine.""" return getattr(obj.machine, 'status_text', '') def get_errors(self, obj: MachineConfig) -> list[str]: - """Serializer method for the errors field.""" + """List of machine errors.""" return [str(err) for err in obj.errors] def get_is_driver_available(self, obj: MachineConfig) -> bool: - """Serializer method for the is_driver_available field.""" + """Indicator if driver for machine is available.""" return obj.is_driver_available() def get_restart_required(self, obj: MachineConfig) -> bool: - """Serializer method for the restart_required field.""" + """Indicator if machine restart is required.""" return getattr(obj.machine, 'restart_required', False) @@ -148,11 +168,11 @@ class BaseMachineClassSerializer(serializers.Serializer): is_builtin = serializers.SerializerMethodField('get_is_builtin') def get_provider_file(self, obj: ClassProviderMixin) -> str: - """Serializer method for the provider_file field.""" + """File that contains the class definition.""" return obj.get_provider_file() def get_provider_plugin(self, obj: ClassProviderMixin) -> Union[dict, None]: - """Serializer method for the provider_plugin field.""" + """Plugin(s) that contain(s) the class definition.""" plugin = obj.get_provider_plugin() if plugin: return { @@ -163,12 +183,12 @@ class BaseMachineClassSerializer(serializers.Serializer): return None def get_is_builtin(self, obj: ClassProviderMixin) -> bool: - """Serializer method for the is_builtin field.""" + """Indicates if the machine type is build into the InvenTree source code.""" return obj.get_is_builtin() class MachineTypeSerializer(BaseMachineClassSerializer): - """Serializer for a BaseMachineType class.""" + """Available machine types.""" class Meta(BaseMachineClassSerializer.Meta): """Meta for a serializer.""" @@ -177,7 +197,7 @@ class MachineTypeSerializer(BaseMachineClassSerializer): class MachineDriverSerializer(BaseMachineClassSerializer): - """Serializer for a BaseMachineDriver class.""" + """Machine drivers.""" class Meta(BaseMachineClassSerializer.Meta): """Meta for a serializer.""" @@ -189,7 +209,7 @@ class MachineDriverSerializer(BaseMachineClassSerializer): driver_errors = serializers.SerializerMethodField('get_errors') def get_errors(self, obj) -> list[str]: - """Serializer method for the errors field.""" + """Errors registered against driver.""" driver_instance = registry.get_driver_instance(obj.SLUG) if driver_instance is None: @@ -198,7 +218,7 @@ class MachineDriverSerializer(BaseMachineClassSerializer): class MachineRegistryErrorSerializer(serializers.Serializer): - """Serializer for a machine registry error.""" + """Machine registry error.""" class Meta: """Meta for a serializer.""" @@ -209,7 +229,7 @@ class MachineRegistryErrorSerializer(serializers.Serializer): class MachineRegistryStatusSerializer(serializers.Serializer): - """Serializer for machine registry status.""" + """Machine registry status, showing all errors that were registered.""" class Meta: """Meta for a serializer."""