← Back to team overview

configglue team mailing list archive

[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