← Back to team overview

configglue team mailing list archive

[Merge] lp:~ricardokirkner/configglue/multi-file-interpolation into lp:configglue

 

Ricardo Kirkner has proposed merging lp:~ricardokirkner/configglue/multi-file-interpolation into lp:configglue.

Commit message:
allow interpolating with __noschema__ values across included files

Requested reviews:
  Configglue developers (configglue)
Related bugs:
  Bug #1076679 in configglue: "included files override in wrong order"
  https://bugs.launchpad.net/configglue/+bug/1076679

For more details, see:
https://code.launchpad.net/~ricardokirkner/configglue/multi-file-interpolation/+merge/174740
-- 
https://code.launchpad.net/~ricardokirkner/configglue/multi-file-interpolation/+merge/174740
Your team Configglue developers is requested to review the proposed merge of lp:~ricardokirkner/configglue/multi-file-interpolation into lp:configglue.
=== modified file 'configglue/parser.py'
--- configglue/parser.py	2013-07-11 17:01:58 +0000
+++ configglue/parser.py	2013-07-15 12:29:24 +0000
@@ -282,7 +282,15 @@
                 fpname)
             includes = self.get('__main__', 'includes')
             filenames = [text_type.strip(x) for x in includes]
-            self.read(filenames, already_read=already_read)
+
+            # parse included files
+            sub_parser = self.__class__(self.schema)
+            sub_parser._basedir = self._basedir
+            sub_parser._location = self._location
+            sub_parser.read(filenames)
+            # update current parser with those values
+            self._sections.update(sub_parser._sections)
+
             self._basedir = old_basedir
 
             if filenames:

=== modified file 'configglue/tests/test_parser.py'
--- configglue/tests/test_parser.py	2013-07-11 17:01:58 +0000
+++ configglue/tests/test_parser.py	2013-07-15 12:29:24 +0000
@@ -196,6 +196,57 @@
         except:
             pass
 
+    def test_multiple_includes(self):
+        """Test parser correctly handles multiple included files."""
+        def setup_config():
+            folder = tempfile.mkdtemp()
+
+            f = codecs.open("%s/first.cfg" % folder, 'w',
+                            encoding=CONFIG_FILE_ENCODING)
+            f.write("[__main__]\nfoo=1\nbar=1")
+            f.close()
+
+            f = codecs.open("%s/second.cfg" % folder, 'w',
+                            encoding=CONFIG_FILE_ENCODING)
+            f.write("[__main__]\nfoo=2\nbar=2")
+            f.close()
+
+            f = codecs.open("%s/third.cfg" % folder, 'w',
+                            encoding=CONFIG_FILE_ENCODING)
+            f.write("[__main__]\nfoo=3\nbar=3")
+            f.close()
+
+            config = textwrap.dedent("""
+                [__main__]
+                includes =
+                    {folder}/first.cfg
+                    {folder}/second.cfg
+                    {folder}/third.cfg
+                foo = 4
+                """.format(folder=folder))
+            config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
+            return config, folder
+
+        class MySchema(Schema):
+            foo = IntOption()
+            bar = IntOption()
+
+        config, folder = setup_config()
+        expected_values = {'__main__': {'foo': 4, 'bar': 3}}
+        parser = SchemaConfigParser(MySchema())
+        # make sure we start on a clean basedir
+        self.assertEqual(parser._basedir, '')
+        parser.readfp(config, 'my.cfg')
+        self.assertEqual(parser.values(), expected_values)
+        # make sure we leave the basedir clean
+        self.assertEqual(parser._basedir, '')
+
+        # silently remove any created files
+        try:
+            shutil.rmtree(folder)
+        except:
+            pass
+
 
 class TestInterpolation(unittest.TestCase):
     """Test basic interpolation."""
@@ -266,6 +317,83 @@
         self.assertRaises(InterpolationMissingOptionError,
             parser.get, 'foo', 'bar')
 
+    def test_interpolate_across_includes(self):
+        """Test interpolation across included files."""
+        def setup_config():
+            folder = tempfile.mkdtemp()
+
+            f = codecs.open("%s/first.cfg" % folder, 'w',
+                            encoding=CONFIG_FILE_ENCODING)
+            f.write("[__main__]\nfoo=1\nincludes=second.cfg")
+            f.close()
+
+            f = codecs.open("%s/second.cfg" % folder, 'w',
+                            encoding=CONFIG_FILE_ENCODING)
+            f.write("[__main__]\nbar=3")
+            f.close()
+
+            config = "[__main__]\nfoo=%%(bar)s\nincludes=%s/first.cfg" % folder
+            config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
+            return config, folder
+
+        class MySchema(Schema):
+            foo = IntOption()
+            bar = IntOption()
+
+        config, folder = setup_config()
+        expected_values = {'__main__': {'foo': 3, 'bar': 3}}
+        parser = SchemaConfigParser(MySchema())
+        # make sure we start on a clean basedir
+        self.assertEqual(parser._basedir, '')
+        parser.readfp(config, 'my.cfg')
+        self.assertEqual(parser.values(), expected_values)
+        # make sure we leave the basedir clean
+        self.assertEqual(parser._basedir, '')
+
+        # silently remove any created files
+        try:
+            shutil.rmtree(folder)
+        except:
+            pass
+
+    def test_interpolate_using_noschema(self):
+        """Test interpolation across included files."""
+        def setup_config():
+            folder = tempfile.mkdtemp()
+
+            f = codecs.open("%s/first.cfg" % folder, 'w',
+                            encoding=CONFIG_FILE_ENCODING)
+            f.write("[__noschema__]\nbar=1\n[__main__]\nincludes=second.cfg")
+            f.close()
+
+            f = codecs.open("%s/second.cfg" % folder, 'w',
+                            encoding=CONFIG_FILE_ENCODING)
+            f.write("[__noschema__]\nbar=3")
+            f.close()
+
+            config = "[__main__]\nfoo=%%(bar)s\nincludes=%s/first.cfg" % folder
+            config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
+            return config, folder
+
+        class MySchema(Schema):
+            foo = IntOption()
+
+        config, folder = setup_config()
+        expected_values = {'__main__': {'foo': 1}}
+        parser = SchemaConfigParser(MySchema())
+        # make sure we start on a clean basedir
+        self.assertEqual(parser._basedir, '')
+        parser.readfp(config, 'my.cfg')
+        self.assertEqual(parser.values(), expected_values)
+        # make sure we leave the basedir clean
+        self.assertEqual(parser._basedir, '')
+
+        # silently remove any created files
+        try:
+            shutil.rmtree(folder)
+        except:
+            pass
+
     def test_interpolate_invalid_key(self):
         """Test interpolation of invalid key."""
         class MySchema(Schema):


Follow ups