diff --git a/pyproject.toml b/pyproject.toml index 9ce50f3710..63a0fd5a6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -109,12 +109,13 @@ unresolved-reference="ignore" # 21 # see https://github.com/astral-sh/ty/issues unresolved-attribute="ignore" # 505 # need Plugin Mixin typing call-non-callable="ignore" # 8 ## invalid-assignment="ignore" # 17 # need to wait for better django field stubs -invalid-method-override="ignore" # 99 +# invalid-method-override="ignore" # 99 invalid-return-type="ignore" # 22 ## -possibly-missing-attribute="ignore" # 25 # https://github.com/astral-sh/ty/issues/164 +# possibly-missing-attribute="ignore" # 25 # https://github.com/astral-sh/ty/issues/164 unknown-argument="ignore" # 3 # need to wait for better django field stubs invalid-argument-type="ignore" # 49 no-matching-overload="ignore" # 3 # need to wait for betterdjango field stubs +possibly-unbound-attribute="ignore" # 21 [tool.coverage.run] source = ["src/backend/InvenTree", "InvenTree"] diff --git a/src/backend/InvenTree/InvenTree/config.py b/src/backend/InvenTree/InvenTree/config.py index a4947de545..aa54bb6014 100644 --- a/src/backend/InvenTree/InvenTree/config.py +++ b/src/backend/InvenTree/InvenTree/config.py @@ -9,7 +9,7 @@ import shutil import string import sys from pathlib import Path -from typing import Optional +from typing import Any, Optional logger = logging.getLogger('inventree') CONFIG_DATA = None @@ -254,6 +254,24 @@ def do_typecast(value, type, var_name=None): return value +def get_config_value(config_key: str) -> Optional[Any]: + """Helper function to retrieve a configuration value from the config file.""" + cfg_data = load_config_data() + + result = None + + # Hack to allow 'path traversal' in configuration file + for key in config_key.strip().split('.'): + if type(cfg_data) is not dict or key not in cfg_data: + result = None + break + + result = cfg_data[key] + cfg_data = cfg_data[key] + + return result + + def get_setting(env_var=None, config_key=None, default_value=None, typecast=None): """Helper function for retrieving a configuration setting value. @@ -291,18 +309,7 @@ def get_setting(env_var=None, config_key=None, default_value=None, typecast=None # Next, try to load from configuration file if config_key is not None: - cfg_data = load_config_data() - - result = None - - # Hack to allow 'path traversal' in configuration file - for key in config_key.strip().split('.'): - if type(cfg_data) is not dict or key not in cfg_data: - result = None - break - - result = cfg_data[key] - cfg_data = cfg_data[key] + result = get_config_value(config_key) if result is not None: set_metadata('yaml') diff --git a/src/backend/InvenTree/InvenTree/setting/db_backend.py b/src/backend/InvenTree/InvenTree/setting/db_backend.py index d97d12cc91..03e9f12cff 100644 --- a/src/backend/InvenTree/InvenTree/setting/db_backend.py +++ b/src/backend/InvenTree/InvenTree/setting/db_backend.py @@ -4,27 +4,38 @@ from pathlib import Path import structlog -from InvenTree.config import get_boolean_setting, get_setting +from InvenTree.config import get_boolean_setting, get_config_value, get_setting logger = structlog.get_logger('inventree') def get_db_backend(): """Return the database backend configuration.""" + # For the core database configuration values, we test for UPPERCASE configuration values as a backup, + # due to legacy reasons (original config files were uppercase, + # but we moved to lowercase for consistency with other settings. + db_config = { 'ENGINE': get_setting( 'INVENTREE_DB_ENGINE', 'database.engine', '', typecast=str - ), - 'NAME': get_setting('INVENTREE_DB_NAME', 'database.name', '', typecast=str), - 'USER': get_setting('INVENTREE_DB_USER', 'database.user', '', typecast=str), + ) + or get_config_value('database.ENGINE'), + 'NAME': get_setting('INVENTREE_DB_NAME', 'database.name', '', typecast=str) + or get_config_value('database.NAME'), + 'USER': get_setting('INVENTREE_DB_USER', 'database.user', '', typecast=str) + or get_config_value('database.USER'), 'PASSWORD': get_setting( 'INVENTREE_DB_PASSWORD', 'database.password', '', typecast=str - ), - 'HOST': get_setting('INVENTREE_DB_HOST', 'database.host', '', typecast=str), - 'PORT': get_setting('INVENTREE_DB_PORT', 'database.port', '', typecast=str), + ) + or get_config_value('database.PASSWORD'), + 'HOST': get_setting('INVENTREE_DB_HOST', 'database.host', '', typecast=str) + or get_config_value('database.HOST'), + 'PORT': get_setting('INVENTREE_DB_PORT', 'database.port', '', typecast=str) + or get_config_value('database.PORT'), 'OPTIONS': get_setting( 'INVENTREE_DB_OPTIONS', 'database.options', {}, typecast=dict ) + or get_config_value('database.OPTIONS') or {}, } diff --git a/src/backend/InvenTree/config_template.yaml b/src/backend/InvenTree/config_template.yaml index ab5f232127..4b790e7c17 100644 --- a/src/backend/InvenTree/config_template.yaml +++ b/src/backend/InvenTree/config_template.yaml @@ -18,15 +18,15 @@ # TO MAINTAINERS: Do not change database strings database: # --- Available options: --- - # ENGINE: Database engine. Selection from: + # engine: Database engine. Selection from: # - mysql # - postgresql # - sqlite3 - # NAME: Database name - # USER: Database username (if required) - # PASSWORD: Database password (if required) - # HOST: Database host address (if required) - # PORT: Database host port (if required) + # name: Database name + # user: Database username (if required) + # password: Database password (if required) + # host: Database host address (if required) + # port: Database host port (if required) # Base URL for the InvenTree server (or use the environment variable INVENTREE_SITE_URL) # site_url: 'http://localhost:8000' diff --git a/src/backend/InvenTree/plugin/plugin.py b/src/backend/InvenTree/plugin/plugin.py index 9019951c11..1e9518cc99 100644 --- a/src/backend/InvenTree/plugin/plugin.py +++ b/src/backend/InvenTree/plugin/plugin.py @@ -5,7 +5,6 @@ import json import re import warnings from datetime import datetime -from distutils.sysconfig import get_python_lib from importlib.metadata import PackageNotFoundError, metadata from pathlib import Path from typing import Optional @@ -528,6 +527,8 @@ class InvenTreePlugin(VersionMixin, MixinBase, MetaBase): @mark_final def is_editable(cls): """Returns if the current part is editable.""" + from distutils.sysconfig import get_python_lib + pkg_name = cls.__name__.split('.')[0] dist_info = list(Path(get_python_lib()).glob(f'{pkg_name}-*.dist-info')) return bool(len(dist_info) == 1)