configglue team mailing list archive
-
configglue team
-
Mailing list archive
-
Message #00340
[Merge] lp:~ricardokirkner/configglue/list-json into lp:configglue
Ricardo Kirkner has proposed merging lp:~ricardokirkner/configglue/list-json into lp:configglue.
Requested reviews:
Configglue developers (configglue)
For more details, see:
https://code.launchpad.net/~ricardokirkner/configglue/list-json/+merge/69888
add support to ListOption to parse json
--
https://code.launchpad.net/~ricardokirkner/configglue/list-json/+merge/69888
Your team Configglue developers is requested to review the proposed merge of lp:~ricardokirkner/configglue/list-json into lp:configglue.
=== modified file 'configglue/parser.py'
--- configglue/parser.py 2011-07-29 22:31:43 +0000
+++ configglue/parser.py 2011-07-30 14:37:24 +0000
@@ -94,15 +94,7 @@
valid = False
# remove sections to skip from config sections
config_sections.difference_update(skip_sections)
- # test2: no missing schema sections
- unmatched_sections = (
- schema_sections - magic_sections - config_sections)
- if unmatched_sections:
- error_msg = "Sections in schema are missing from configuration: %s"
- error_value = ', '.join(unmatched_sections)
- errors.append(error_msg % error_value)
- valid = False
- # test3: no extra sections that are not implicit sections
+ # test2: no extra sections that are not implicit sections
unmatched_sections = (
config_sections - magic_sections - schema_sections)
if unmatched_sections:
=== modified file 'configglue/schema.py'
--- configglue/schema.py 2011-07-29 22:22:32 +0000
+++ configglue/schema.py 2011-07-30 14:37:24 +0000
@@ -409,7 +409,7 @@
def __init__(self, name='', item=None, raw=False, default=NO_DEFAULT,
fatal=False, help='', action='store', remove_duplicates=False,
- short_name=''):
+ short_name='', parse_json=True):
super(ListOption, self).__init__(name=name, raw=raw,
default=default, fatal=fatal, help=help, action=action,
short_name=short_name)
@@ -419,6 +419,7 @@
self.require_parser = item.require_parser
self.raw = raw or item.raw
self.remove_duplicates = remove_duplicates
+ self.parse_json = parse_json
def __eq__(self, other):
equal = super(ListOption, self).__eq__(other)
@@ -447,18 +448,36 @@
else:
value = self.item.parse(value, raw=raw)
return value
- items = [_parse_item(x) for x in value.split('\n') if len(x)]
+
+ is_json = self.parse_json
+ if self.parse_json:
+ try:
+ parsed = json.loads(value)
+ if not isinstance(parsed, list):
+ is_json = False
+ except:
+ is_json = False
+
+ if not is_json:
+ parsed = [_parse_item(x) for x in value.split('\n') if len(x)]
+
if self.remove_duplicates:
filtered_items = []
- for item in items:
+ for item in parsed:
if not item in filtered_items:
filtered_items.append(item)
- items = filtered_items
- return items
+ parsed = filtered_items
+ return parsed
def validate(self, value):
return isinstance(value, list)
+ def to_string(self, value):
+ if self.parse_json:
+ return json.dumps(value)
+ else:
+ return super(ListOption, self).to_string(value)
+
class StringOption(Option):
"""A Option that is parsed into a string.
=== modified file 'configglue/tests/test_parser.py'
--- configglue/tests/test_parser.py 2011-07-29 22:25:27 +0000
+++ configglue/tests/test_parser.py 2011-07-30 14:37:24 +0000
@@ -1373,6 +1373,24 @@
self.assertTrue(parser.is_valid())
+ def test_missing_schema_sections(self):
+ class MySchema(Schema):
+ class foo(Section):
+ bar = IntOption()
+
+ class bar(Section):
+ baz = BoolOption()
+
+ config = StringIO(textwrap.dedent("""
+ [foo]
+ bar = 3
+ """))
+ parser = SchemaConfigParser(MySchema())
+ parser.readfp(config)
+ parser.parse_all()
+
+ self.assertTrue(parser.is_valid())
+
if __name__ == '__main__':
unittest.main()
=== modified file 'configglue/tests/test_schema.py'
--- configglue/tests/test_schema.py 2011-07-29 22:22:32 +0000
+++ configglue/tests/test_schema.py 2011-07-30 14:37:24 +0000
@@ -493,6 +493,58 @@
parser.readfp(config)
self.assertEqual(parser.values(), expected_values)
+ def test_parse_no_json(self):
+ class MySchema(Schema):
+ foo = self.cls(item=IntOption(), parse_json=False)
+
+ config = StringIO("[__main__]\nfoo = 42\n 43\n 44")
+ expected_values = {'__main__': {'foo': [42, 43, 44]}}
+ schema = MySchema()
+ parser = SchemaConfigParser(schema)
+ parser.readfp(config)
+ self.assertEqual(parser.values(), expected_values)
+
+ def test_parse_no_json_with_json(self):
+ class MySchema(Schema):
+ foo = self.cls(item=IntOption(), parse_json=False)
+
+ config = StringIO("[__main__]\nfoo = [42, 43, 44]")
+ schema = MySchema()
+ parser = SchemaConfigParser(schema)
+ parser.readfp(config)
+ self.assertRaises(ValueError, parser.values)
+
+ def test_parse_json(self):
+ class MySchema(Schema):
+ foo = self.cls(item=IntOption())
+
+ config = StringIO("[__main__]\nfoo = [42, 43, 44]")
+ expected_values = {'__main__': {'foo': [42, 43, 44]}}
+ schema = MySchema()
+ parser = SchemaConfigParser(schema)
+ parser.readfp(config)
+ self.assertEqual(parser.values(), expected_values)
+
+ def test_parse_invalid_json(self):
+ class MySchema(Schema):
+ foo = self.cls(item=IntOption())
+
+ config = StringIO('[__main__]\nfoo = 1, 2, 3')
+ schema = MySchema()
+ parser = SchemaConfigParser(schema)
+ parser.readfp(config)
+ self.assertRaises(ValueError, parser.values)
+
+ def test_parse_non_list_json(self):
+ class MySchema(Schema):
+ foo = self.cls(item=IntOption())
+
+ config = StringIO('[__main__]\nfoo = {"foo": "bar"}')
+ schema = MySchema()
+ parser = SchemaConfigParser(schema)
+ parser.readfp(config)
+ self.assertRaises(ValueError, parser.values)
+
def test_parse_bool_lines(self):
"""Test ListOption parse a list of booleans."""
class MySchema(Schema):
@@ -600,6 +652,17 @@
self.assertNotEqual(option1, option6)
self.assertNotEqual(option1, option7)
+ def test_to_string_when_json(self):
+ option = ListOption()
+ result = option.to_string(['1', '2', '3'])
+ self.assertEqual(result, '["1", "2", "3"]')
+ self.assertNotEqual(result, "['1', '2', '3']")
+
+ def test_to_string_when_no_json(self):
+ option = ListOption(parse_json=False)
+ result = option.to_string(['1', '2', '3'])
+ self.assertEqual(result, "['1', '2', '3']")
+
class TestTupleOption(unittest.TestCase):
cls = TupleOption
Follow ups