blob: 6c502878025551985c2fbbebe51c3c94e898764c [file] [log] [blame]
Georg Brandl392c6fc2008-05-25 07:25:25 +00001import ConfigParser
Fred Drake8ef67672000-09-27 22:45:25 +00002import StringIO
Fred Drakec6f28912002-10-25 19:40:49 +00003import unittest
Martin v. Löwisa00bcac2006-12-03 12:01:53 +00004import UserDict
Fred Drake8ef67672000-09-27 22:45:25 +00005
Fred Drakec6f28912002-10-25 19:40:49 +00006from test import test_support
Fred Drake3d5f7e82000-12-04 16:30:40 +00007
Fred Drakecc43b562010-02-19 05:24:30 +00008
Martin v. Löwisa00bcac2006-12-03 12:01:53 +00009class SortedDict(UserDict.UserDict):
10 def items(self):
11 result = self.data.items()
12 result.sort()
13 return result
14
15 def keys(self):
16 result = self.data.keys()
17 result.sort()
18 return result
Tim Petersf733abb2007-01-30 03:03:46 +000019
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000020 def values(self):
Georg Brandlcd4a21b2010-02-06 23:34:10 +000021 # XXX never used?
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000022 result = self.items()
Georg Brandlcd4a21b2010-02-06 23:34:10 +000023 return [i[1] for i in result]
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000024
25 def iteritems(self): return iter(self.items())
26 def iterkeys(self): return iter(self.keys())
27 __iter__ = iterkeys
28 def itervalues(self): return iter(self.values())
Fred Drake3d5f7e82000-12-04 16:30:40 +000029
Fred Drakecc43b562010-02-19 05:24:30 +000030
Fred Drakec6f28912002-10-25 19:40:49 +000031class TestCaseBase(unittest.TestCase):
Fred Drakecc43b562010-02-19 05:24:30 +000032 allow_no_value = False
33
Fred Drakec6f28912002-10-25 19:40:49 +000034 def newconfig(self, defaults=None):
35 if defaults is None:
Fred Drakecc43b562010-02-19 05:24:30 +000036 self.cf = self.config_class(allow_no_value=self.allow_no_value)
Fred Drakec6f28912002-10-25 19:40:49 +000037 else:
Fred Drakecc43b562010-02-19 05:24:30 +000038 self.cf = self.config_class(defaults,
39 allow_no_value=self.allow_no_value)
Fred Drakec6f28912002-10-25 19:40:49 +000040 return self.cf
Fred Drake8ef67672000-09-27 22:45:25 +000041
Fred Drakec6f28912002-10-25 19:40:49 +000042 def fromstring(self, string, defaults=None):
43 cf = self.newconfig(defaults)
44 sio = StringIO.StringIO(string)
45 cf.readfp(sio)
46 return cf
Fred Drake8ef67672000-09-27 22:45:25 +000047
Fred Drakec6f28912002-10-25 19:40:49 +000048 def test_basic(self):
Fred Drakecc43b562010-02-19 05:24:30 +000049 config_string = (
Fred Drakec6f28912002-10-25 19:40:49 +000050 "[Foo Bar]\n"
51 "foo=bar\n"
52 "[Spacey Bar]\n"
53 "foo = bar\n"
54 "[Commented Bar]\n"
55 "foo: bar ; comment\n"
56 "[Long Line]\n"
57 "foo: this line is much, much longer than my editor\n"
58 " likes it.\n"
59 "[Section\\with$weird%characters[\t]\n"
60 "[Internationalized Stuff]\n"
61 "foo[bg]: Bulgarian\n"
62 "foo=Default\n"
63 "foo[en]=English\n"
64 "foo[de]=Deutsch\n"
65 "[Spaces]\n"
66 "key with spaces : value\n"
67 "another with spaces = splat!\n"
68 )
Fred Drakecc43b562010-02-19 05:24:30 +000069 if self.allow_no_value:
70 config_string += (
71 "[NoValue]\n"
72 "option-without-value\n"
73 )
74
75 cf = self.fromstring(config_string)
Fred Drakec6f28912002-10-25 19:40:49 +000076 L = cf.sections()
77 L.sort()
Fred Drakecc43b562010-02-19 05:24:30 +000078 E = [r'Commented Bar',
79 r'Foo Bar',
80 r'Internationalized Stuff',
81 r'Long Line',
82 r'Section\with$weird%characters[' '\t',
83 r'Spaces',
84 r'Spacey Bar',
85 ]
86 if self.allow_no_value:
87 E.append(r'NoValue')
88 E.sort()
Fred Drakec6f28912002-10-25 19:40:49 +000089 eq = self.assertEqual
Fred Drakecc43b562010-02-19 05:24:30 +000090 eq(L, E)
Fred Drake8ef67672000-09-27 22:45:25 +000091
Fred Drakec6f28912002-10-25 19:40:49 +000092 # The use of spaces in the section names serves as a
93 # regression test for SourceForge bug #583248:
94 # http://www.python.org/sf/583248
95 eq(cf.get('Foo Bar', 'foo'), 'bar')
96 eq(cf.get('Spacey Bar', 'foo'), 'bar')
97 eq(cf.get('Commented Bar', 'foo'), 'bar')
98 eq(cf.get('Spaces', 'key with spaces'), 'value')
99 eq(cf.get('Spaces', 'another with spaces'), 'splat!')
Fred Drakecc43b562010-02-19 05:24:30 +0000100 if self.allow_no_value:
101 eq(cf.get('NoValue', 'option-without-value'), None)
Fred Drake3d5f7e82000-12-04 16:30:40 +0000102
Ezio Melottiaa980582010-01-23 23:04:36 +0000103 self.assertNotIn('__name__', cf.options("Foo Bar"),
104 '__name__ "option" should not be exposed by the API!')
Fred Drakec6f28912002-10-25 19:40:49 +0000105
106 # Make sure the right things happen for remove_option();
107 # added to include check for SourceForge bug #123324:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000108 self.assertTrue(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000109 "remove_option() failed to report existence of option")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000110 self.assertFalse(cf.has_option('Foo Bar', 'foo'),
Fred Drakec6f28912002-10-25 19:40:49 +0000111 "remove_option() failed to remove option")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000112 self.assertFalse(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000113 "remove_option() failed to report non-existence of option"
Fred Drakec6f28912002-10-25 19:40:49 +0000114 " that was removed")
115
Georg Brandl392c6fc2008-05-25 07:25:25 +0000116 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000117 cf.remove_option, 'No Such Section', 'foo')
118
119 eq(cf.get('Long Line', 'foo'),
Andrew M. Kuchling1bf71172002-03-08 18:10:12 +0000120 'this line is much, much longer than my editor\nlikes it.')
Fred Drake3d5f7e82000-12-04 16:30:40 +0000121
Fred Drakec6f28912002-10-25 19:40:49 +0000122 def test_case_sensitivity(self):
123 cf = self.newconfig()
124 cf.add_section("A")
125 cf.add_section("a")
126 L = cf.sections()
127 L.sort()
128 eq = self.assertEqual
129 eq(L, ["A", "a"])
130 cf.set("a", "B", "value")
131 eq(cf.options("a"), ["b"])
132 eq(cf.get("a", "b"), "value",
Fred Drake3c823aa2001-02-26 21:55:34 +0000133 "could not locate option, expecting case-insensitive option names")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000134 self.assertTrue(cf.has_option("a", "b"))
Fred Drakec6f28912002-10-25 19:40:49 +0000135 cf.set("A", "A-B", "A-B value")
136 for opt in ("a-b", "A-b", "a-B", "A-B"):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000137 self.assertTrue(
Fred Drakec6f28912002-10-25 19:40:49 +0000138 cf.has_option("A", opt),
139 "has_option() returned false for option which should exist")
140 eq(cf.options("A"), ["a-b"])
141 eq(cf.options("a"), ["b"])
142 cf.remove_option("a", "B")
143 eq(cf.options("a"), [])
Fred Drake3c823aa2001-02-26 21:55:34 +0000144
Fred Drakec6f28912002-10-25 19:40:49 +0000145 # SF bug #432369:
146 cf = self.fromstring(
147 "[MySection]\nOption: first line\n\tsecond line\n")
148 eq(cf.options("MySection"), ["option"])
149 eq(cf.get("MySection", "Option"), "first line\nsecond line")
Fred Drakebeb67132001-07-06 17:22:48 +0000150
Fred Drakec6f28912002-10-25 19:40:49 +0000151 # SF bug #561822:
152 cf = self.fromstring("[section]\nnekey=nevalue\n",
153 defaults={"key":"value"})
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000154 self.assertTrue(cf.has_option("section", "Key"))
Fred Drake309db062002-09-27 15:35:23 +0000155
Fred Drake3c823aa2001-02-26 21:55:34 +0000156
David Goodger68a1abd2004-10-03 15:40:25 +0000157 def test_default_case_sensitivity(self):
158 cf = self.newconfig({"foo": "Bar"})
159 self.assertEqual(
160 cf.get("DEFAULT", "Foo"), "Bar",
161 "could not locate option, expecting case-insensitive option names")
162 cf = self.newconfig({"Foo": "Bar"})
163 self.assertEqual(
164 cf.get("DEFAULT", "Foo"), "Bar",
165 "could not locate option, expecting case-insensitive defaults")
166
Fred Drakec6f28912002-10-25 19:40:49 +0000167 def test_parse_errors(self):
168 self.newconfig()
Georg Brandl392c6fc2008-05-25 07:25:25 +0000169 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000170 "[Foo]\n extra-spaces: splat\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000171 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000172 "[Foo]\n extra-spaces= splat\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000173 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000174 "[Foo]\n:value-without-option-name\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000175 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000176 "[Foo]\n=value-without-option-name\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000177 self.parse_error(ConfigParser.MissingSectionHeaderError,
Fred Drakec6f28912002-10-25 19:40:49 +0000178 "No Section!\n")
Fred Drake168bead2001-10-08 17:13:12 +0000179
Fred Drakec6f28912002-10-25 19:40:49 +0000180 def parse_error(self, exc, src):
181 sio = StringIO.StringIO(src)
182 self.assertRaises(exc, self.cf.readfp, sio)
Fred Drake168bead2001-10-08 17:13:12 +0000183
Fred Drakec6f28912002-10-25 19:40:49 +0000184 def test_query_errors(self):
185 cf = self.newconfig()
186 self.assertEqual(cf.sections(), [],
187 "new ConfigParser should have no defined sections")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000188 self.assertFalse(cf.has_section("Foo"),
Fred Drakec6f28912002-10-25 19:40:49 +0000189 "new ConfigParser should have no acknowledged sections")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000190 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000191 cf.options, "Foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000192 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000193 cf.set, "foo", "bar", "value")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000194 self.get_error(ConfigParser.NoSectionError, "foo", "bar")
Fred Drakec6f28912002-10-25 19:40:49 +0000195 cf.add_section("foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000196 self.get_error(ConfigParser.NoOptionError, "foo", "bar")
Fred Drake8ef67672000-09-27 22:45:25 +0000197
Fred Drakec6f28912002-10-25 19:40:49 +0000198 def get_error(self, exc, section, option):
Fred Drake54782192002-12-31 06:57:25 +0000199 try:
200 self.cf.get(section, option)
201 except exc, e:
202 return e
203 else:
204 self.fail("expected exception type %s.%s"
205 % (exc.__module__, exc.__name__))
Fred Drake3af0eb82002-10-25 18:09:24 +0000206
Fred Drakec6f28912002-10-25 19:40:49 +0000207 def test_boolean(self):
208 cf = self.fromstring(
209 "[BOOLTEST]\n"
210 "T1=1\n"
211 "T2=TRUE\n"
212 "T3=True\n"
213 "T4=oN\n"
214 "T5=yes\n"
215 "F1=0\n"
216 "F2=FALSE\n"
217 "F3=False\n"
218 "F4=oFF\n"
219 "F5=nO\n"
220 "E1=2\n"
221 "E2=foo\n"
222 "E3=-1\n"
223 "E4=0.1\n"
224 "E5=FALSE AND MORE"
225 )
226 for x in range(1, 5):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000227 self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x))
228 self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x))
Fred Drakec6f28912002-10-25 19:40:49 +0000229 self.assertRaises(ValueError,
230 cf.getboolean, 'BOOLTEST', 'e%d' % x)
Fred Drake95b96d32001-02-12 17:23:20 +0000231
Fred Drakec6f28912002-10-25 19:40:49 +0000232 def test_weird_errors(self):
233 cf = self.newconfig()
Fred Drake8ef67672000-09-27 22:45:25 +0000234 cf.add_section("Foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000235 self.assertRaises(ConfigParser.DuplicateSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000236 cf.add_section, "Foo")
237
238 def test_write(self):
Fred Drakecc43b562010-02-19 05:24:30 +0000239 config_string = (
Fred Drakec6f28912002-10-25 19:40:49 +0000240 "[Long Line]\n"
241 "foo: this line is much, much longer than my editor\n"
242 " likes it.\n"
243 "[DEFAULT]\n"
244 "foo: another very\n"
Fred Drakecc43b562010-02-19 05:24:30 +0000245 " long line\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000246 )
Fred Drakecc43b562010-02-19 05:24:30 +0000247 if self.allow_no_value:
248 config_string += (
249 "[Valueless]\n"
250 "option-without-value\n"
251 )
252
253 cf = self.fromstring(config_string)
Fred Drakec6f28912002-10-25 19:40:49 +0000254 output = StringIO.StringIO()
255 cf.write(output)
Fred Drakecc43b562010-02-19 05:24:30 +0000256 expect_string = (
Fred Drakec6f28912002-10-25 19:40:49 +0000257 "[DEFAULT]\n"
258 "foo = another very\n"
259 "\tlong line\n"
260 "\n"
261 "[Long Line]\n"
262 "foo = this line is much, much longer than my editor\n"
263 "\tlikes it.\n"
264 "\n"
265 )
Fred Drakecc43b562010-02-19 05:24:30 +0000266 if self.allow_no_value:
267 expect_string += (
268 "[Valueless]\n"
269 "option-without-value\n"
270 "\n"
271 )
272 self.assertEqual(output.getvalue(), expect_string)
Fred Drakec6f28912002-10-25 19:40:49 +0000273
Fred Drakeabc086f2004-05-18 03:29:52 +0000274 def test_set_string_types(self):
275 cf = self.fromstring("[sect]\n"
276 "option1=foo\n")
277 # Check that we don't get an exception when setting values in
278 # an existing section using strings:
279 class mystr(str):
280 pass
281 cf.set("sect", "option1", "splat")
282 cf.set("sect", "option1", mystr("splat"))
283 cf.set("sect", "option2", "splat")
284 cf.set("sect", "option2", mystr("splat"))
285 try:
286 unicode
287 except NameError:
288 pass
289 else:
290 cf.set("sect", "option1", unicode("splat"))
291 cf.set("sect", "option2", unicode("splat"))
292
Fred Drake82903142004-05-18 04:24:02 +0000293 def test_read_returns_file_list(self):
294 file1 = test_support.findfile("cfgparser.1")
295 # check when we pass a mix of readable and non-readable files:
296 cf = self.newconfig()
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000297 parsed_files = cf.read([file1, "nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000298 self.assertEqual(parsed_files, [file1])
299 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
300 # check when we pass only a filename:
301 cf = self.newconfig()
302 parsed_files = cf.read(file1)
303 self.assertEqual(parsed_files, [file1])
304 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
305 # check when we pass only missing files:
306 cf = self.newconfig()
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000307 parsed_files = cf.read(["nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000308 self.assertEqual(parsed_files, [])
309 # check when we pass no files:
310 cf = self.newconfig()
311 parsed_files = cf.read([])
312 self.assertEqual(parsed_files, [])
313
Fred Drakec6f28912002-10-25 19:40:49 +0000314 # shared by subclasses
315 def get_interpolation_config(self):
316 return self.fromstring(
317 "[Foo]\n"
318 "bar=something %(with1)s interpolation (1 step)\n"
319 "bar9=something %(with9)s lots of interpolation (9 steps)\n"
320 "bar10=something %(with10)s lots of interpolation (10 steps)\n"
321 "bar11=something %(with11)s lots of interpolation (11 steps)\n"
322 "with11=%(with10)s\n"
323 "with10=%(with9)s\n"
324 "with9=%(with8)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000325 "with8=%(With7)s\n"
326 "with7=%(WITH6)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000327 "with6=%(with5)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000328 "With5=%(with4)s\n"
329 "WITH4=%(with3)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000330 "with3=%(with2)s\n"
331 "with2=%(with1)s\n"
332 "with1=with\n"
333 "\n"
334 "[Mutual Recursion]\n"
335 "foo=%(bar)s\n"
Fred Drake54782192002-12-31 06:57:25 +0000336 "bar=%(foo)s\n"
337 "\n"
338 "[Interpolation Error]\n"
339 "name=%(reference)s\n",
340 # no definition for 'reference'
Fred Drakec6f28912002-10-25 19:40:49 +0000341 defaults={"getname": "%(__name__)s"})
Fred Drake95b96d32001-02-12 17:23:20 +0000342
Fred Drake98e3b292002-10-25 20:42:44 +0000343 def check_items_config(self, expected):
344 cf = self.fromstring(
345 "[section]\n"
346 "name = value\n"
347 "key: |%(name)s| \n"
348 "getdefault: |%(default)s|\n"
349 "getname: |%(__name__)s|",
350 defaults={"default": "<default>"})
351 L = list(cf.items("section"))
352 L.sort()
353 self.assertEqual(L, expected)
354
Fred Drake8ef67672000-09-27 22:45:25 +0000355
Fred Drakec6f28912002-10-25 19:40:49 +0000356class ConfigParserTestCase(TestCaseBase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000357 config_class = ConfigParser.ConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000358
359 def test_interpolation(self):
360 cf = self.get_interpolation_config()
361 eq = self.assertEqual
362 eq(cf.get("Foo", "getname"), "Foo")
363 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
364 eq(cf.get("Foo", "bar9"),
365 "something with lots of interpolation (9 steps)")
366 eq(cf.get("Foo", "bar10"),
367 "something with lots of interpolation (10 steps)")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000368 self.get_error(ConfigParser.InterpolationDepthError, "Foo", "bar11")
Fred Drake95b96d32001-02-12 17:23:20 +0000369
Fred Drake54782192002-12-31 06:57:25 +0000370 def test_interpolation_missing_value(self):
Fred Drakecc43b562010-02-19 05:24:30 +0000371 self.get_interpolation_config()
Georg Brandl392c6fc2008-05-25 07:25:25 +0000372 e = self.get_error(ConfigParser.InterpolationError,
Fred Drake54782192002-12-31 06:57:25 +0000373 "Interpolation Error", "name")
374 self.assertEqual(e.reference, "reference")
375 self.assertEqual(e.section, "Interpolation Error")
376 self.assertEqual(e.option, "name")
377
Fred Drake98e3b292002-10-25 20:42:44 +0000378 def test_items(self):
379 self.check_items_config([('default', '<default>'),
380 ('getdefault', '|<default>|'),
381 ('getname', '|section|'),
382 ('key', '|value|'),
383 ('name', 'value')])
384
David Goodger1cbf2062004-10-03 15:55:09 +0000385 def test_set_nonstring_types(self):
386 cf = self.newconfig()
387 cf.add_section('non-string')
388 cf.set('non-string', 'int', 1)
389 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%('])
390 cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1,
391 '%(list)': '%(list)'})
392 cf.set('non-string', 'string_with_interpolation', '%(list)s')
393 self.assertEqual(cf.get('non-string', 'int', raw=True), 1)
394 self.assertRaises(TypeError, cf.get, 'non-string', 'int')
395 self.assertEqual(cf.get('non-string', 'list', raw=True),
396 [0, 1, 1, 2, 3, 5, 8, 13, '%('])
397 self.assertRaises(TypeError, cf.get, 'non-string', 'list')
398 self.assertEqual(cf.get('non-string', 'dict', raw=True),
399 {'pi': 3.14159, '%(': 1, '%(list)': '%(list)'})
400 self.assertRaises(TypeError, cf.get, 'non-string', 'dict')
401 self.assertEqual(cf.get('non-string', 'string_with_interpolation',
402 raw=True), '%(list)s')
403 self.assertRaises(ValueError, cf.get, 'non-string',
404 'string_with_interpolation', raw=False)
405
Fred Drake8ef67672000-09-27 22:45:25 +0000406
Fred Drakec6f28912002-10-25 19:40:49 +0000407class RawConfigParserTestCase(TestCaseBase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000408 config_class = ConfigParser.RawConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000409
410 def test_interpolation(self):
411 cf = self.get_interpolation_config()
412 eq = self.assertEqual
413 eq(cf.get("Foo", "getname"), "%(__name__)s")
414 eq(cf.get("Foo", "bar"),
415 "something %(with1)s interpolation (1 step)")
416 eq(cf.get("Foo", "bar9"),
417 "something %(with9)s lots of interpolation (9 steps)")
418 eq(cf.get("Foo", "bar10"),
419 "something %(with10)s lots of interpolation (10 steps)")
420 eq(cf.get("Foo", "bar11"),
421 "something %(with11)s lots of interpolation (11 steps)")
Fred Drake95b96d32001-02-12 17:23:20 +0000422
Fred Drake98e3b292002-10-25 20:42:44 +0000423 def test_items(self):
424 self.check_items_config([('default', '<default>'),
425 ('getdefault', '|%(default)s|'),
426 ('getname', '|%(__name__)s|'),
427 ('key', '|%(name)s|'),
428 ('name', 'value')])
429
David Goodger1cbf2062004-10-03 15:55:09 +0000430 def test_set_nonstring_types(self):
431 cf = self.newconfig()
432 cf.add_section('non-string')
433 cf.set('non-string', 'int', 1)
434 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13])
435 cf.set('non-string', 'dict', {'pi': 3.14159})
436 self.assertEqual(cf.get('non-string', 'int'), 1)
437 self.assertEqual(cf.get('non-string', 'list'),
438 [0, 1, 1, 2, 3, 5, 8, 13])
439 self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159})
Tim Petersab9b32c2004-10-03 18:35:19 +0000440
Fred Drake8ef67672000-09-27 22:45:25 +0000441
Fred Drake0eebd5c2002-10-25 21:52:00 +0000442class SafeConfigParserTestCase(ConfigParserTestCase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000443 config_class = ConfigParser.SafeConfigParser
Fred Drake0eebd5c2002-10-25 21:52:00 +0000444
445 def test_safe_interpolation(self):
446 # See http://www.python.org/sf/511737
447 cf = self.fromstring("[section]\n"
448 "option1=xxx\n"
449 "option2=%(option1)s/xxx\n"
450 "ok=%(option1)s/%%s\n"
451 "not_ok=%(option2)s/%%s")
452 self.assertEqual(cf.get("section", "ok"), "xxx/%s")
453 self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s")
454
Georg Brandl92a6bae2007-03-13 17:43:32 +0000455 def test_set_malformatted_interpolation(self):
456 cf = self.fromstring("[sect]\n"
457 "option1=foo\n")
458
459 self.assertEqual(cf.get('sect', "option1"), "foo")
460
461 self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo")
462 self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%")
463 self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo")
464
465 self.assertEqual(cf.get('sect', "option1"), "foo")
466
Georg Brandl21cf5ee2009-04-12 17:24:11 +0000467 # bug #5741: double percents are *not* malformed
468 cf.set("sect", "option2", "foo%%bar")
469 self.assertEqual(cf.get("sect", "option2"), "foo%bar")
470
David Goodger1cbf2062004-10-03 15:55:09 +0000471 def test_set_nonstring_types(self):
472 cf = self.fromstring("[sect]\n"
473 "option1=foo\n")
474 # Check that we get a TypeError when setting non-string values
475 # in an existing section:
476 self.assertRaises(TypeError, cf.set, "sect", "option1", 1)
477 self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0)
478 self.assertRaises(TypeError, cf.set, "sect", "option1", object())
479 self.assertRaises(TypeError, cf.set, "sect", "option2", 1)
480 self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
481 self.assertRaises(TypeError, cf.set, "sect", "option2", object())
482
Facundo Batistab12f0b52008-02-23 12:46:10 +0000483 def test_add_section_default_1(self):
484 cf = self.newconfig()
485 self.assertRaises(ValueError, cf.add_section, "default")
486
487 def test_add_section_default_2(self):
488 cf = self.newconfig()
489 self.assertRaises(ValueError, cf.add_section, "DEFAULT")
490
Fred Drakecc43b562010-02-19 05:24:30 +0000491
492class SafeConfigParserTestCaseNoValue(SafeConfigParserTestCase):
493 allow_no_value = True
494
495
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000496class SortedTestCase(RawConfigParserTestCase):
497 def newconfig(self, defaults=None):
498 self.cf = self.config_class(defaults=defaults, dict_type=SortedDict)
499 return self.cf
500
501 def test_sorted(self):
502 self.fromstring("[b]\n"
503 "o4=1\n"
504 "o3=2\n"
505 "o2=3\n"
506 "o1=4\n"
507 "[a]\n"
Tim Petersf733abb2007-01-30 03:03:46 +0000508 "k=v\n")
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000509 output = StringIO.StringIO()
510 self.cf.write(output)
511 self.assertEquals(output.getvalue(),
512 "[a]\n"
Tim Petersf733abb2007-01-30 03:03:46 +0000513 "k = v\n\n"
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000514 "[b]\n"
515 "o1 = 4\n"
516 "o2 = 3\n"
517 "o3 = 2\n"
518 "o4 = 1\n\n")
Fred Drake0eebd5c2002-10-25 21:52:00 +0000519
Fred Drakecc43b562010-02-19 05:24:30 +0000520
Fred Drakec6f28912002-10-25 19:40:49 +0000521def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000522 test_support.run_unittest(
523 ConfigParserTestCase,
524 RawConfigParserTestCase,
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000525 SafeConfigParserTestCase,
Fred Drakecc43b562010-02-19 05:24:30 +0000526 SortedTestCase,
527 SafeConfigParserTestCaseNoValue,
528 )
529
Fred Drake3af0eb82002-10-25 18:09:24 +0000530
Fred Drakec6f28912002-10-25 19:40:49 +0000531if __name__ == "__main__":
532 test_main()