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

Proposed by Ricardo Kirkner
Status: Merged
Approved by: Ricardo Kirkner
Approved revision: 112
Merged at revision: 110
Proposed branch: lp:~ricardokirkner/configglue/multi-file-interpolation
Merge into: lp:configglue
Diff against target: 240 lines (+126/-30)
2 files modified
configglue/parser.py (+9/-1)
configglue/tests/test_parser.py (+117/-29)
To merge this branch: bzr merge lp:~ricardokirkner/configglue/multi-file-interpolation
Reviewer Review Type Date Requested Status
Ricardo Kirkner Approve
Natalia Bidart Approve
Review via email: mp+174740@code.launchpad.net

Commit message

allow interpolating with __noschema__ values across included files

To post a comment you must log in.
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Looks good!

review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :

Voting does not meet specified criteria. Required: Approve >= 1, Disapprove == 0, Needs Fixing == 0, Needs Information == 0, Resubmit == 0, Pending == 0. Got: 1 Pending.

Revision history for this message
Ricardo Kirkner (ricardokirkner) wrote :

Rubber stamping

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configglue/parser.py'
2--- configglue/parser.py 2013-07-11 17:01:58 +0000
3+++ configglue/parser.py 2013-07-15 18:06:23 +0000
4@@ -282,7 +282,15 @@
5 fpname)
6 includes = self.get('__main__', 'includes')
7 filenames = [text_type.strip(x) for x in includes]
8- self.read(filenames, already_read=already_read)
9+
10+ # parse included files
11+ sub_parser = self.__class__(self.schema)
12+ sub_parser._basedir = self._basedir
13+ sub_parser._location = self._location
14+ sub_parser.read(filenames)
15+ # update current parser with those values
16+ self._sections.update(sub_parser._sections)
17+
18 self._basedir = old_basedir
19
20 if filenames:
21
22=== modified file 'configglue/tests/test_parser.py'
23--- configglue/tests/test_parser.py 2013-07-11 17:01:58 +0000
24+++ configglue/tests/test_parser.py 2013-07-15 18:06:23 +0000
25@@ -109,6 +109,7 @@
26 """Test parser include files using relative paths."""
27 def setup_config():
28 folder = tempfile.mkdtemp()
29+ self.addCleanup(shutil.rmtree, folder)
30
31 f = codecs.open("%s/first.cfg" % folder, 'w',
32 encoding=CONFIG_FILE_ENCODING)
33@@ -150,16 +151,11 @@
34 # make sure we leave the basedir clean
35 self.assertEqual(parser._basedir, '')
36
37- # silently remove any created files
38- try:
39- shutil.rmtree(folder)
40- except:
41- pass
42-
43 def test_local_override(self):
44 """Test parser override values from included files."""
45 def setup_config():
46 folder = tempfile.mkdtemp()
47+ self.addCleanup(shutil.rmtree, folder)
48
49 f = codecs.open("%s/first.cfg" % folder, 'w',
50 encoding=CONFIG_FILE_ENCODING)
51@@ -190,11 +186,51 @@
52 # make sure we leave the basedir clean
53 self.assertEqual(parser._basedir, '')
54
55- # silently remove any created files
56- try:
57- shutil.rmtree(folder)
58- except:
59- pass
60+ def test_multiple_includes(self):
61+ """Test parser correctly handles multiple included files."""
62+ def setup_config():
63+ folder = tempfile.mkdtemp()
64+ self.addCleanup(shutil.rmtree, folder)
65+
66+ f = codecs.open("%s/first.cfg" % folder, 'w',
67+ encoding=CONFIG_FILE_ENCODING)
68+ f.write("[__main__]\nfoo=1\nbar=1")
69+ f.close()
70+
71+ f = codecs.open("%s/second.cfg" % folder, 'w',
72+ encoding=CONFIG_FILE_ENCODING)
73+ f.write("[__main__]\nfoo=2\nbar=2")
74+ f.close()
75+
76+ f = codecs.open("%s/third.cfg" % folder, 'w',
77+ encoding=CONFIG_FILE_ENCODING)
78+ f.write("[__main__]\nfoo=3\nbar=3")
79+ f.close()
80+
81+ config = textwrap.dedent("""
82+ [__main__]
83+ includes =
84+ {folder}/first.cfg
85+ {folder}/second.cfg
86+ {folder}/third.cfg
87+ foo = 4
88+ """.format(folder=folder))
89+ config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
90+ return config, folder
91+
92+ class MySchema(Schema):
93+ foo = IntOption()
94+ bar = IntOption()
95+
96+ config, folder = setup_config()
97+ expected_values = {'__main__': {'foo': 4, 'bar': 3}}
98+ parser = SchemaConfigParser(MySchema())
99+ # make sure we start on a clean basedir
100+ self.assertEqual(parser._basedir, '')
101+ parser.readfp(config, 'my.cfg')
102+ self.assertEqual(parser.values(), expected_values)
103+ # make sure we leave the basedir clean
104+ self.assertEqual(parser._basedir, '')
105
106
107 class TestInterpolation(unittest.TestCase):
108@@ -266,6 +302,73 @@
109 self.assertRaises(InterpolationMissingOptionError,
110 parser.get, 'foo', 'bar')
111
112+ def test_interpolate_across_includes(self):
113+ """Test interpolation across included files."""
114+ def setup_config():
115+ folder = tempfile.mkdtemp()
116+ self.addCleanup(shutil.rmtree, folder)
117+
118+ f = codecs.open("%s/first.cfg" % folder, 'w',
119+ encoding=CONFIG_FILE_ENCODING)
120+ f.write("[__main__]\nfoo=1\nincludes=second.cfg")
121+ f.close()
122+
123+ f = codecs.open("%s/second.cfg" % folder, 'w',
124+ encoding=CONFIG_FILE_ENCODING)
125+ f.write("[__main__]\nbar=3")
126+ f.close()
127+
128+ config = "[__main__]\nfoo=%%(bar)s\nincludes=%s/first.cfg" % folder
129+ config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
130+ return config, folder
131+
132+ class MySchema(Schema):
133+ foo = IntOption()
134+ bar = IntOption()
135+
136+ config, folder = setup_config()
137+ expected_values = {'__main__': {'foo': 3, 'bar': 3}}
138+ parser = SchemaConfigParser(MySchema())
139+ # make sure we start on a clean basedir
140+ self.assertEqual(parser._basedir, '')
141+ parser.readfp(config, 'my.cfg')
142+ self.assertEqual(parser.values(), expected_values)
143+ # make sure we leave the basedir clean
144+ self.assertEqual(parser._basedir, '')
145+
146+ def test_interpolate_using_noschema(self):
147+ """Test interpolation across included files."""
148+ def setup_config():
149+ folder = tempfile.mkdtemp()
150+ self.addCleanup(shutil.rmtree, folder)
151+
152+ f = codecs.open("%s/first.cfg" % folder, 'w',
153+ encoding=CONFIG_FILE_ENCODING)
154+ f.write("[__noschema__]\nbar=1\n[__main__]\nincludes=second.cfg")
155+ f.close()
156+
157+ f = codecs.open("%s/second.cfg" % folder, 'w',
158+ encoding=CONFIG_FILE_ENCODING)
159+ f.write("[__noschema__]\nbar=3")
160+ f.close()
161+
162+ config = "[__main__]\nfoo=%%(bar)s\nincludes=%s/first.cfg" % folder
163+ config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
164+ return config, folder
165+
166+ class MySchema(Schema):
167+ foo = IntOption()
168+
169+ config, folder = setup_config()
170+ expected_values = {'__main__': {'foo': 1}}
171+ parser = SchemaConfigParser(MySchema())
172+ # make sure we start on a clean basedir
173+ self.assertEqual(parser._basedir, '')
174+ parser.readfp(config, 'my.cfg')
175+ self.assertEqual(parser.values(), expected_values)
176+ # make sure we leave the basedir clean
177+ self.assertEqual(parser._basedir, '')
178+
179 def test_interpolate_invalid_key(self):
180 """Test interpolation of invalid key."""
181 class MySchema(Schema):
182@@ -882,6 +985,7 @@
183 def test_read_multiple_files(self):
184 def setup_config():
185 folder = tempfile.mkdtemp()
186+ self.addCleanup(shutil.rmtree, folder)
187
188 f = codecs.open("%s/first.cfg" % folder, 'w',
189 encoding=CONFIG_FILE_ENCODING)
190@@ -900,12 +1004,6 @@
191 self.parser.read(files)
192 self.assertEqual(self.parser.values(), {'__main__': {'foo': 'bar'}})
193
194- # silently remove any created files
195- try:
196- shutil.rmtree(folder)
197- except:
198- pass
199-
200 def test_read_utf8_encoded_file(self):
201 # create config file
202 fp, filename = tempfile.mkstemp()
203@@ -1053,6 +1151,7 @@
204 """Test parser save config values to original files."""
205 def setup_config():
206 folder = tempfile.mkdtemp()
207+ self.addCleanup(shutil.rmtree, folder)
208
209 f = codecs.open("%s/first.cfg" % folder, 'w',
210 encoding=CONFIG_FILE_ENCODING)
211@@ -1095,15 +1194,10 @@
212 # new value goes into last read config file
213 self.assertTrue('baz = 42' in data)
214
215- # silently remove any created files
216- try:
217- shutil.rmtree(folder)
218- except:
219- pass
220-
221 def test_save_config_last_location_nested_includes(self):
222 def setup_config():
223 folder = tempfile.mkdtemp()
224+ self.addCleanup(shutil.rmtree, folder)
225
226 f = codecs.open("%s/first.cfg" % folder, 'w',
227 encoding=CONFIG_FILE_ENCODING)
228@@ -1151,12 +1245,6 @@
229 # not in the last included config file
230 self.assertTrue('baz = 42' in data)
231
232- # silently remove any created files
233- try:
234- shutil.rmtree(folder)
235- except:
236- pass
237-
238
239 class TestParserIsValid(unittest.TestCase):
240 def setUp(self):

Subscribers

People subscribed via source and target branches