diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index 431dae9d0a..1d2884c829 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -8,7 +8,7 @@ import os import os.path import re from decimal import Decimal, InvalidOperation -from typing import Set, Type, TypeVar +from typing import TypeVar from wsgiref.util import FileWrapper from django.conf import settings @@ -889,7 +889,7 @@ def get_objectreference( Inheritors_T = TypeVar('Inheritors_T') -def inheritors(cls: Type[Inheritors_T]) -> Set[Type[Inheritors_T]]: +def inheritors(cls: type[Inheritors_T]) -> set[type[Inheritors_T]]: """Return all classes that are subclasses from the supplied cls.""" subcls = set() work = [cls] diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index e3581b7f3c..036ac98796 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -9,7 +9,7 @@ import time import warnings from dataclasses import dataclass from datetime import datetime, timedelta -from typing import Callable, List +from typing import Callable from django.conf import settings from django.core.exceptions import AppRegistryNotReady @@ -291,7 +291,7 @@ class ScheduledTask: class TaskRegister: """Registry for periodic tasks.""" - task_list: List[ScheduledTask] = [] + task_list: list[ScheduledTask] = [] def register(self, task, schedule, minutes: int = None): """Register a task with the que.""" diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index cf44ff6ff8..51092d4306 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -16,7 +16,7 @@ import uuid from datetime import datetime, timedelta, timezone from enum import Enum from secrets import compare_digest -from typing import Any, Callable, Dict, List, Tuple, TypedDict, Union +from typing import Any, Callable, TypedDict, Union from django.apps import apps from django.conf import settings @@ -157,7 +157,7 @@ class SettingsKeyType(TypedDict, total=False): units: Units of the particular setting (optional) validator: Validation function/list of functions for the setting (optional, default: None, e.g: bool, int, str, MinValueValidator, ...) default: Default value or function that returns default value (optional) - choices: (Function that returns) Tuple[str: key, str: display value] (optional) + choices: Function that returns or value of list[tuple[str: key, str: display value]] (optional) hidden: Hide this setting from settings page (optional) before_save: Function that gets called after save with *args, **kwargs (optional) after_save: Function that gets called after save with *args, **kwargs (optional) @@ -169,9 +169,9 @@ class SettingsKeyType(TypedDict, total=False): name: str description: str units: str - validator: Union[Callable, List[Callable], Tuple[Callable]] + validator: Union[Callable, list[Callable], tuple[Callable]] default: Union[Callable, Any] - choices: Union[Tuple[str, str], Callable[[], Tuple[str, str]]] + choices: Union[list[tuple[str, str]], Callable[[], list[tuple[str, str]]]] hidden: bool before_save: Callable[..., None] after_save: Callable[..., None] @@ -188,9 +188,9 @@ class BaseInvenTreeSetting(models.Model): extra_unique_fields: List of extra fields used to be unique, e.g. for PluginConfig -> plugin """ - SETTINGS: Dict[str, SettingsKeyType] = {} + SETTINGS: dict[str, SettingsKeyType] = {} - extra_unique_fields: List[str] = [] + extra_unique_fields: list[str] = [] class Meta: """Meta options for BaseInvenTreeSetting -> abstract stops creation of database entry.""" @@ -332,7 +332,7 @@ class BaseInvenTreeSetting(models.Model): cls, *, exclude_hidden=False, - settings_definition: Union[Dict[str, SettingsKeyType], None] = None, + settings_definition: Union[dict[str, SettingsKeyType], None] = None, **kwargs, ): """Return a list of "all" defined settings. @@ -352,7 +352,7 @@ class BaseInvenTreeSetting(models.Model): # Optionally filter by other keys results = results.filter(**filters) - settings: Dict[str, BaseInvenTreeSetting] = {} + settings: dict[str, BaseInvenTreeSetting] = {} # Query the database for setting in results: @@ -394,7 +394,7 @@ class BaseInvenTreeSetting(models.Model): cls, *, exclude_hidden=False, - settings_definition: Union[Dict[str, SettingsKeyType], None] = None, + settings_definition: Union[dict[str, SettingsKeyType], None] = None, **kwargs, ): """Return a dict of "all" defined global settings. @@ -409,7 +409,7 @@ class BaseInvenTreeSetting(models.Model): **kwargs, ) - settings: Dict[str, Any] = {} + settings: dict[str, Any] = {} for key, setting in all_settings.items(): settings[key] = setting.value @@ -421,7 +421,7 @@ class BaseInvenTreeSetting(models.Model): cls, *, exclude_hidden=False, - settings_definition: Union[Dict[str, SettingsKeyType], None] = None, + settings_definition: Union[dict[str, SettingsKeyType], None] = None, **kwargs, ): """Check if all required settings are set by definition. @@ -436,7 +436,7 @@ class BaseInvenTreeSetting(models.Model): **kwargs, ) - missing_settings: List[str] = [] + missing_settings: list[str] = [] for setting in all_settings.values(): if setting.required: @@ -1171,6 +1171,16 @@ def reload_plugin_registry(setting): registry.reload_plugins(full_reload=True, force_reload=True, collect=True) +class InvenTreeSettingsKeyType(SettingsKeyType): + """InvenTreeSettingsKeyType has additional properties only global settings support. + + Attributes: + requires_restart: If True, a server restart is required after changing the setting + """ + + requires_restart: bool + + class InvenTreeSetting(BaseInvenTreeSetting): """An InvenTreeSetting object is a key:value pair used for storing single values (e.g. one-off settings values). @@ -1178,6 +1188,8 @@ class InvenTreeSetting(BaseInvenTreeSetting): even if that key does not exist. """ + SETTINGS: dict[str, InvenTreeSettingsKeyType] + class Meta: """Meta options for InvenTreeSetting.""" diff --git a/InvenTree/machine/machine_type.py b/InvenTree/machine/machine_type.py index d92d0540d4..7be615a66e 100644 --- a/InvenTree/machine/machine_type.py +++ b/InvenTree/machine/machine_type.py @@ -1,6 +1,6 @@ """Base machine type/base driver.""" -from typing import TYPE_CHECKING, Any, Dict, List, Literal, Tuple, Type, Union +from typing import TYPE_CHECKING, Any, Literal, Union from generic.states import StatusCode from InvenTree.helpers_mixin import ClassProviderMixin, ClassValidationMixin @@ -59,7 +59,7 @@ class BaseDriver(ClassValidationMixin, ClassProviderMixin): NAME: str DESCRIPTION: str - MACHINE_SETTINGS: Dict[str, SettingsKeyType] + MACHINE_SETTINGS: dict[str, SettingsKeyType] machine_type: str @@ -89,7 +89,7 @@ class BaseDriver(ClassValidationMixin, ClassProviderMixin): """ def update_machine( - self, old_machine_state: Dict[str, Any], machine: 'BaseMachineType' + self, old_machine_state: dict[str, Any], machine: 'BaseMachineType' ): """This method gets called for each update of a machine. @@ -156,11 +156,11 @@ class BaseMachineType(ClassValidationMixin, ClassProviderMixin): NAME: str DESCRIPTION: str - base_driver: Type[BaseDriver] + base_driver: type[BaseDriver] - MACHINE_SETTINGS: Dict[str, SettingsKeyType] + MACHINE_SETTINGS: dict[str, SettingsKeyType] - MACHINE_STATUS: Type[MachineStatus] + MACHINE_STATUS: type[MachineStatus] default_machine_status: MachineStatus # used by the ClassValidationMixin @@ -194,15 +194,15 @@ class BaseMachineType(ClassValidationMixin, ClassProviderMixin): f"'{self.driver.NAME}' is incompatible with machine type '{self.NAME}'" ) - self.machine_settings: Dict[str, SettingsKeyType] = getattr( + self.machine_settings: dict[str, SettingsKeyType] = getattr( self, 'MACHINE_SETTINGS', {} ) - self.driver_settings: Dict[str, SettingsKeyType] = getattr( + self.driver_settings: dict[str, SettingsKeyType] = getattr( self.driver, 'MACHINE_SETTINGS', {} ) - self.setting_types: List[ - Tuple[Dict[str, SettingsKeyType], MachineSetting.ConfigType] + self.setting_types: list[ + tuple[dict[str, SettingsKeyType], MachineSetting.ConfigType] ] = [ (self.machine_settings, MachineSetting.ConfigType.MACHINE), (self.driver_settings, MachineSetting.ConfigType.DRIVER), @@ -339,11 +339,11 @@ class BaseMachineType(ClassValidationMixin, ClassProviderMixin): Returns: is_valid: Are all required settings defined - missing_settings: Dict[ConfigType, List[str]] of all settings that are missing (empty if is_valid is 'True') + missing_settings: dict[ConfigType, list[str]] of all settings that are missing (empty if is_valid is 'True') """ from machine.models import MachineSetting - missing_settings: Dict[MachineSetting.ConfigType, List[str]] = {} + missing_settings: dict[MachineSetting.ConfigType, list[str]] = {} for settings, config_type in self.setting_types: is_valid, missing = MachineSetting.check_all_settings( settings_definition=settings, diff --git a/InvenTree/machine/registry.py b/InvenTree/machine/registry.py index fbd712fef2..c2d09a6e5b 100644 --- a/InvenTree/machine/registry.py +++ b/InvenTree/machine/registry.py @@ -1,7 +1,7 @@ """Machine registry.""" import logging -from typing import Dict, List, Set, Type, Union +from typing import Union from uuid import UUID from machine.machine_type import BaseDriver, BaseMachineType @@ -17,12 +17,12 @@ class MachineRegistry: Set up all needed references for internal and external states. """ - self.machine_types: Dict[str, Type[BaseMachineType]] = {} - self.drivers: Dict[str, Type[BaseDriver]] = {} - self.driver_instances: Dict[str, BaseDriver] = {} - self.machines: Dict[str, BaseMachineType] = {} + self.machine_types: dict[str, type[BaseMachineType]] = {} + self.drivers: dict[str, type[BaseDriver]] = {} + self.driver_instances: dict[str, BaseDriver] = {} + self.machines: dict[str, BaseMachineType] = {} - self.base_drivers: List[Type[BaseDriver]] = [] + self.base_drivers: list[type[BaseDriver]] = [] self.errors: list[Union[str, Exception]] = [] def handle_error(self, error: Union[Exception, str]): @@ -41,10 +41,10 @@ class MachineRegistry: logger.debug('Collecting machine types') - machine_types: Dict[str, Type[BaseMachineType]] = {} - base_drivers: List[Type[BaseDriver]] = [] + machine_types: dict[str, type[BaseMachineType]] = {} + base_drivers: list[type[BaseDriver]] = [] - discovered_machine_types: Set[Type[BaseMachineType]] = ( + discovered_machine_types: set[type[BaseMachineType]] = ( InvenTree.helpers.inheritors(BaseMachineType) ) for machine_type in discovered_machine_types: @@ -74,9 +74,9 @@ class MachineRegistry: logger.debug('Collecting machine drivers') - drivers: Dict[str, Type[BaseDriver]] = {} + drivers: dict[str, type[BaseDriver]] = {} - discovered_drivers: Set[Type[BaseDriver]] = InvenTree.helpers.inheritors( + discovered_drivers: set[type[BaseDriver]] = InvenTree.helpers.inheritors( BaseDriver ) for driver in discovered_drivers: diff --git a/InvenTree/machine/serializers.py b/InvenTree/machine/serializers.py index 88e87d2d18..e1f75632e3 100644 --- a/InvenTree/machine/serializers.py +++ b/InvenTree/machine/serializers.py @@ -1,6 +1,6 @@ """Serializers for the machine app.""" -from typing import List, Union +from typing import Union from rest_framework import serializers @@ -62,7 +62,7 @@ class MachineConfigSerializer(serializers.ModelSerializer): """Serializer method for the status text field.""" return getattr(obj.machine, 'status_text', '') - def get_errors(self, obj: MachineConfig) -> List[str]: + def get_errors(self, obj: MachineConfig) -> list[str]: """Serializer method for the errors field.""" return [str(err) for err in obj.errors] @@ -165,7 +165,7 @@ class MachineDriverSerializer(BaseMachineClassSerializer): driver_errors = serializers.SerializerMethodField('get_errors') - def get_errors(self, obj) -> List[str]: + def get_errors(self, obj) -> list[str]: """Serializer method for the errors field.""" driver_instance = registry.driver_instances.get(obj.SLUG, None) if driver_instance is None: diff --git a/InvenTree/plugin/base/integration/SettingsMixin.py b/InvenTree/plugin/base/integration/SettingsMixin.py index 7bababa69c..d5a5ec9a5e 100644 --- a/InvenTree/plugin/base/integration/SettingsMixin.py +++ b/InvenTree/plugin/base/integration/SettingsMixin.py @@ -1,7 +1,7 @@ """Plugin mixin class for SettingsMixin.""" import logging -from typing import TYPE_CHECKING, Dict +from typing import TYPE_CHECKING from django.db.utils import OperationalError, ProgrammingError @@ -21,7 +21,7 @@ else: class SettingsMixin: """Mixin that enables global settings for the plugin.""" - SETTINGS: Dict[str, SettingsKeyType] = {} + SETTINGS: dict[str, SettingsKeyType] = {} class MixinMeta: """Meta for mixin.""" diff --git a/InvenTree/plugin/registry.py b/InvenTree/plugin/registry.py index c7188ca365..b51a797b96 100644 --- a/InvenTree/plugin/registry.py +++ b/InvenTree/plugin/registry.py @@ -9,9 +9,10 @@ import importlib import logging import os import time +from collections import OrderedDict from pathlib import Path from threading import Lock -from typing import Any, Dict, List, OrderedDict +from typing import Any from django.apps import apps from django.conf import settings @@ -52,19 +53,19 @@ class PluginsRegistry: Set up all needed references for internal and external states. """ # plugin registry - self.plugins: Dict[str, InvenTreePlugin] = {} # List of active instances - self.plugins_inactive: Dict[ + self.plugins: dict[str, InvenTreePlugin] = {} # List of active instances + self.plugins_inactive: dict[ str, InvenTreePlugin ] = {} # List of inactive instances - self.plugins_full: Dict[ + self.plugins_full: dict[ str, InvenTreePlugin ] = {} # List of all plugin instances # Keep an internal hash of the plugin registry state self.registry_hash = None - self.plugin_modules: List[InvenTreePlugin] = [] # Holds all discovered plugins - self.mixin_modules: Dict[str, Any] = {} # Holds all discovered mixins + self.plugin_modules: list[InvenTreePlugin] = [] # Holds all discovered plugins + self.mixin_modules: dict[str, Any] = {} # Holds all discovered mixins self.errors = {} # Holds discovering errors @@ -682,9 +683,9 @@ class PluginsRegistry: def _clean_registry(self): """Remove all plugins from registry.""" - self.plugins: Dict[str, InvenTreePlugin] = {} - self.plugins_inactive: Dict[str, InvenTreePlugin] = {} - self.plugins_full: Dict[str, InvenTreePlugin] = {} + self.plugins: dict[str, InvenTreePlugin] = {} + self.plugins_inactive: dict[str, InvenTreePlugin] = {} + self.plugins_full: dict[str, InvenTreePlugin] = {} def _update_urls(self): """Due to the order in which plugins are loaded, the patterns in urls.py may be out of date.