diff options
-rw-r--r-- | doc/releases/1.4.0pre2.txt | 5 | ||||
-rw-r--r-- | src/lib/Bcfg2/DBSettings.py | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Options/Types.py | 27 | ||||
-rw-r--r-- | testsuite/Testsrc/Testlib/TestOptions/TestTypes.py | 20 |
4 files changed, 23 insertions, 33 deletions
diff --git a/doc/releases/1.4.0pre2.txt b/doc/releases/1.4.0pre2.txt index a5c10777a..195f81df0 100644 --- a/doc/releases/1.4.0pre2.txt +++ b/doc/releases/1.4.0pre2.txt @@ -31,6 +31,11 @@ backwards-incompatible user-facing changes This fixes potentially long client runs when comparing files that have diverged significantly. +* The database options in the config (options and reporting_options in database + section) now have to be literal python dictionaries. + + This allows to set arbitrary options with nested settings. + Thanks ------ diff --git a/src/lib/Bcfg2/DBSettings.py b/src/lib/Bcfg2/DBSettings.py index 5a83c25c3..1c8c34978 100644 --- a/src/lib/Bcfg2/DBSettings.py +++ b/src/lib/Bcfg2/DBSettings.py @@ -229,7 +229,7 @@ class _OptionContainer(object): dest='db_schema', default='public'), Bcfg2.Options.Option( cf=('database', 'options'), help='Database options', - dest='db_opts', type=Bcfg2.Options.Types.comma_dict, + dest='db_opts', type=Bcfg2.Options.Types.literal_dict, default=dict()), # reporting database options Bcfg2.Options.Option( @@ -258,7 +258,7 @@ class _OptionContainer(object): Bcfg2.Options.Option( cf=('database', 'reporting_options'), help='Reporting database options', dest='reporting_db_opts', - type=Bcfg2.Options.Types.comma_dict, default=dict()), + type=Bcfg2.Options.Types.literal_dict, default=dict()), # Django options Bcfg2.Options.Option( cf=('reporting', 'time_zone'), help='Django timezone'), diff --git a/src/lib/Bcfg2/Options/Types.py b/src/lib/Bcfg2/Options/Types.py index ac099e135..ad2e04f10 100644 --- a/src/lib/Bcfg2/Options/Types.py +++ b/src/lib/Bcfg2/Options/Types.py @@ -5,6 +5,7 @@ import os import re import pwd import grp +from Bcfg2.Compat import literal_eval _COMMA_SPLIT_RE = re.compile(r'\s*,\s*') @@ -32,28 +33,10 @@ def colon_list(value): return value.split(':') -def comma_dict(value): - """ Split an option string on commas, optionally surrounded by - whitespace, and split the resulting items again on equals signs, - returning a dict """ - result = dict() - if value: - items = comma_list(value) - for item in items: - if '=' in item: - key, value = item.split(r'=', 1) - if value in ["true", "yes", "on"]: - result[key] = True - elif value in ["false", "no", "off"]: - result[key] = False - else: - try: - result[key] = int(value) - except ValueError: - result[key] = value - else: - result[item] = True - return result +def literal_dict(value): + """ literally evaluate the option in order to allow for arbitrarily nested + dictionaries """ + return literal_eval(value) def anchored_regex_list(value): diff --git a/testsuite/Testsrc/Testlib/TestOptions/TestTypes.py b/testsuite/Testsrc/Testlib/TestOptions/TestTypes.py index 404d67fdc..0b67db38a 100644 --- a/testsuite/Testsrc/Testlib/TestOptions/TestTypes.py +++ b/testsuite/Testsrc/Testlib/TestOptions/TestTypes.py @@ -46,21 +46,23 @@ class TestOptionTypes(Bcfg2TestCase): self.assertItemsEqual(self._test_options(["--test", "one:two three"]), ["one", "two three"]) - def test_comma_dict(self): - """parse comma-dict values.""" - self.options = [Option("--test", type=Types.comma_dict)] + def test_literal_dict(self): + """parse literal-dict values.""" + self.options = [Option("--test", type=Types.literal_dict)] expected = { "one": True, "two": 2, "three": "three", - "four": False} + "four": False, + "five": { + "a": 1, + "b": 2 + }} self.assertDictEqual( self._test_options(["--test", - "one=yes, two=2 , three=three,four=no"]), - expected) - - self.assertDictEqual( - self._test_options(["--test", "one,two=2,three=three,four=off"]), + '''{ "one": True, "two": 2, + "three": "three", "four": False, + "five": { "a": 1, "b": 2 }}''']), expected) def test_anchored_regex_list(self): |