Skip to content

Commit

Permalink
improve support for booleans in environment vars
Browse files Browse the repository at this point in the history
  • Loading branch information
wryfi committed Aug 12, 2019
1 parent ba3c173 commit 5da2c32
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGES
=======

v1.0.0
------

* add license
* add AUTHORS and ChangeLog per pbr
* update README
* add json and yaml convenience methods
* more work removing string > list conversions
Expand Down
14 changes: 12 additions & 2 deletions cfitall/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@


class ConfigManager(object):
def __init__(self, name, env_prefix=None, env_path_sep='__', env_value_split=True, defaults={}):
def __init__(self, name, env_prefix=None, env_path_sep='__', env_value_split=True, env_bool=True, defaults={}):
"""
The configuration registry holds configuration data from different sources
and reconciles it for retrieval.
: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: if True, then environment variable values are split on commas into a list
:param bool env_value_split: split env var values into python string (on comma)
:param bool env_bool: convert 'true' and 'false' strings in env vars to python bools
:param dict defaults: dictionary of default configuration settings
"""
self.name = name
Expand All @@ -25,6 +26,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_bool = env_bool
if env_prefix:
self.env_prefix = env_prefix.upper()
else:
Expand Down Expand Up @@ -212,6 +214,14 @@ def _read_environment(self):
if isinstance(value, str) and self.env_value_split:
if re.match(r'.*,(.*,)*.*', value):
value = value.split(',')
if self.env_bool:
if type(value) == str and value.lower() == 'true':
value = True
if type(value) == str and value.lower() == 'false':
value = False
if type(value) == list:
value = [True if type(val) == str and val.lower() == 'true' else val for val in value]
value = [False if type(val) == str and val.lower() == 'false' else val for val in value]
output[key] = value
return utils.expand_flattened_dict(output, separator=self.env_path_sep)

Expand Down
28 changes: 25 additions & 3 deletions cfitall/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ def setUp(self):

def tearDown(self):
super().tearDown()
del os.environ['CFITALL__GLOBAL__NAME']
del os.environ['CFITALL__GLOBAL__PATH']
del os.environ['CFITALL__FOO__BANG']
for key, value in os.environ.items():
if key.startswith('CFITALL'):
del os.environ[key]

def test_create_object(self):
_cf = ConfigManager('cfitall')
Expand Down Expand Up @@ -49,6 +49,28 @@ def test_config_order(self):
cf.set('global.authors', ['dwight schrute', 'pam beesly'])
self.assertEqual(cf.get('global.authors', list), ['dwight schrute', 'pam beesly'])

def test_env_bool(self):
cf = ConfigManager('cfitall')
os.environ['CFITALL__TEST__BOOLEAN__TRUE'] = 'true'
os.environ['CFITALL__TEST__BOOLEAN__FALSE'] = 'False'
os.environ['CFITALL__TEST__BOOLEAN__LIST'] = 'true,false,True,this,False,is,nice'
self.assertEqual(cf.get('test.boolean.true'), True)
self.assertEqual(cf.get('test.boolean.false'), False)
self.assertEqual(cf.get('test.boolean.list'), [True, False, True, 'this', False, 'is', 'nice'])
cf.env_bool = False
self.assertEqual(cf.get('test.boolean.true'), 'true')
self.assertEqual(cf.get('test.boolean.false'), 'False')
self.assertEqual(cf.get('test.boolean.list'), ['true', 'false', 'True', 'this', 'False', 'is', 'nice'])

def test_comma_list(self):
cf = ConfigManager('cfitall')
cf.set_default('test.list.withcommas', ['flenderson, toby', 'martin, angela'])
self.assertEqual(cf.get('test.list.withcommas'), ['flenderson, toby', 'martin, angela'])
os.environ['CFITALL__TEST__LIST'] = 'hello,world,melting'
self.assertEqual(cf.get('test.list'), ['hello', 'world', 'melting'])
cf.env_value_split = False
self.assertEqual(cf.get('test.list'), 'hello,world,melting')


if __name__ == '__main__':
unittest.main()

0 comments on commit 5da2c32

Please sign in to comment.