diff --git a/cfitall/config.py b/cfitall/config.py index 0e08472..106487e 100644 --- a/cfitall/config.py +++ b/cfitall/config.py @@ -1,4 +1,5 @@ from decimal import Decimal +import logging import json import re import os @@ -7,8 +8,12 @@ from cfitall import utils +logger = logging.getLogger(__name__) + + class ConfigManager(object): - def __init__(self, name, env_prefix=None, env_path_sep='__', env_value_split=True, env_bool=True, defaults={}): + def __init__(self, name, env_prefix=None, env_path_sep='__', env_value_split=True, + env_value_split_space=False, env_bool=True, defaults={}): """ The configuration registry holds configuration data from different sources and reconciles it for retrieval. @@ -16,7 +21,8 @@ def __init__(self, name, env_prefix=None, env_path_sep='__', env_value_split=Tru :param str name: name of registry (cannot contain env_separator string) :param str env_prefix: prefix for environment variables (defaults to uppercase name) :param str env_path_sep: string for separating config hierarchies in env vars (default '__') - :param bool env_value_split: split env var values into python string (on comma) + :param bool env_value_split: split env var values into python list (on comma) + :param bool env_value_split_space: split env var values into python list (on whitespace) :param bool env_bool: convert 'true' and 'false' strings in env vars to python bools :param dict defaults: dictionary of default configuration settings """ @@ -26,6 +32,7 @@ def __init__(self, name, env_prefix=None, env_path_sep='__', env_value_split=Tru self.values = {'super': {}, 'cli': {}, 'cfgfile': {}, 'defaults': defaults} self.env_path_sep = env_path_sep self.env_value_split = env_value_split + self.env_value_split_space = env_value_split_space self.env_bool = env_bool if env_prefix: self.env_prefix = env_prefix.upper() @@ -211,9 +218,7 @@ def _read_environment(self): for key, value in os.environ.items(): if key.startswith(prefix): key = key.replace(prefix, '', 1).lower() - if isinstance(value, str) and self.env_value_split: - if re.match(r'.*,(.*,)*.*', value): - value = value.split(',') + value = self._split_value(value) if self.env_bool: if type(value) == str and value.lower() == 'true': value = True @@ -237,3 +242,16 @@ def _merge_configs(self): config = utils.merge_dicts(self._read_environment(), config) config = utils.merge_dicts(self.values['super'], config) return config + + def _split_value(self, value): + """ + For now, env_value_split_space always overrides env_value_split; + this may change in a future release. + """ + if self.env_value_split and not self.env_value_split_space: + if re.match(r'.*,(.*,)*.*', value): + return value.split(',') + elif self.env_value_split_space: + if re.match(r'.*\s+(.*\s+)*.*', value): + return re.split(r'\s+', value) + return value diff --git a/cfitall/tests/test_config.py b/cfitall/tests/test_config.py index dd714f9..a45a999 100644 --- a/cfitall/tests/test_config.py +++ b/cfitall/tests/test_config.py @@ -71,6 +71,16 @@ def test_comma_list(self): cf.env_value_split = False self.assertEqual(cf.get('test.list'), 'hello,world,melting') + def test_space_list(self): + cf = ConfigManager('cfitall') + cf.set_default('test.list.withspaces', ['flenderson, toby', 'martin, angela']) + self.assertEqual(cf.get('test.list.withcommas'), ['flenderson, toby', 'martin, angela']) + os.environ['CFITALL__TEST__LIST'] = 'hello world melting antarctica broadway' + cf.env_value_split_space = True + self.assertEqual(cf.get('test.list'), ['hello', 'world', 'melting', 'antarctica', 'broadway']) + cf.env_value_split_space = False + self.assertEqual(cf.get('test.list'), 'hello world melting antarctica broadway') + def test_different_keys_same_value(self): cf = ConfigManager('cfitall') cf.set_default('test.string', 'hello, world')