From 5ff7468bfcf635f1dafb41e285199b815259636a Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 14 Feb 2023 22:26:46 +1100 Subject: [PATCH] Allow currency list to be specified from environment variables (#4344) - Add option to get_setting in config.py to allow list casting (cherry picked from commit 49019d8b5b570fb426ad062d5acfc32df7a4d2ee) --- InvenTree/InvenTree/config.py | 27 ++++++++++++++++++++++++++- InvenTree/InvenTree/settings.py | 18 +++++++++++------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/InvenTree/InvenTree/config.py b/InvenTree/InvenTree/config.py index 892e5751c4..703b0097da 100644 --- a/InvenTree/InvenTree/config.py +++ b/InvenTree/InvenTree/config.py @@ -13,6 +13,25 @@ CONFIG_DATA = None CONFIG_LOOKUPS = {} +def to_list(value, delimiter=','): + """Take a configuration setting and make sure it is a list. + + For example, we might have a configuration setting taken from the .config file, + which is already a list. + + However, the same setting may be specified via an environment variable, + using a comma delimited string! + """ + + if type(value) in [list, tuple]: + return value + + # Otherwise, force string value + value = str(value) + + return [x.strip() for x in value.split(delimiter)] + + def is_true(x): """Shortcut function to determine if a value "looks" like a boolean""" return str(x).strip().lower() in ['1', 'y', 'yes', 't', 'true', 'on'] @@ -101,7 +120,12 @@ def get_setting(env_var=None, config_key=None, default_value=None, typecast=None """ def try_typecasting(value, source: str): """Attempt to typecast the value""" - if typecast is not None: + + # Force 'list' of strings + if typecast is list: + value = to_list(value) + + elif typecast is not None: # Try to typecast the value try: val = typecast(value) @@ -109,6 +133,7 @@ def get_setting(env_var=None, config_key=None, default_value=None, typecast=None return val except Exception as error: logger.error(f"Failed to typecast '{env_var}' with value '{value}' to type '{typecast}' with error {error}") + set_metadata(source) return value diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index e773a1d378..68174f019a 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -103,7 +103,8 @@ MEDIA_ROOT = config.get_media_dir() # List of allowed hosts (default = allow all) ALLOWED_HOSTS = get_setting( config_key='allowed_hosts', - default_value=['*'] + default_value=['*'], + typecast=list, ) # Cross Origin Resource Sharing (CORS) options @@ -119,7 +120,8 @@ CORS_ORIGIN_ALLOW_ALL = get_boolean_setting( CORS_ORIGIN_WHITELIST = get_setting( config_key='cors.whitelist', - default_value=[] + default_value=[], + typecast=list, ) # Needed for the parts importer, directly impacts the maximum parts that can be uploaded @@ -736,9 +738,11 @@ if get_boolean_setting('TEST_TRANSLATIONS', default_value=False): # pragma: no django.conf.locale.LANG_INFO = LANG_INFO # Currencies available for use -CURRENCIES = get_setting('INVENTREE_CURRENCIES', 'currencies', [ - 'AUD', 'CAD', 'CNY', 'EUR', 'GBP', 'JPY', 'NZD', 'USD', -]) +CURRENCIES = get_setting( + 'INVENTREE_CURRENCIES', 'currencies', + ['AUD', 'CAD', 'CNY', 'EUR', 'GBP', 'JPY', 'NZD', 'USD'], + typecast=list, +) # Maximum number of decimal places for currency rendering CURRENCY_DECIMAL_PLACES = 6 @@ -746,7 +750,7 @@ CURRENCY_DECIMAL_PLACES = 6 # Check that each provided currency is supported for currency in CURRENCIES: if currency not in moneyed.CURRENCIES: # pragma: no cover - print(f"Currency code '{currency}' is not supported") + logger.error(f"Currency code '{currency}' is not supported") sys.exit(1) # Custom currency exchange backend @@ -795,7 +799,7 @@ IMPORT_EXPORT_USE_TRANSACTIONS = True SITE_ID = 1 # Load the allauth social backends -SOCIAL_BACKENDS = get_setting('INVENTREE_SOCIAL_BACKENDS', 'social_backends', []) +SOCIAL_BACKENDS = get_setting('INVENTREE_SOCIAL_BACKENDS', 'social_backends', [], typecast=list) for app in SOCIAL_BACKENDS: INSTALLED_APPS.append(app) # pragma: no cover