blob: fdd3c0c1c459169797fc056b091e7b5dbc4feaec [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
Martin v. Löwisa00bcac2006-12-03 12:01:53 +00008class SortedDict(UserDict.UserDict):
9 def items(self):
10 result = self.data.items()
11 result.sort()
12 return result
13
14 def keys(self):
15 result = self.data.keys()
16 result.sort()
17 return result
Tim Petersf733abb2007-01-30 03:03:46 +000018
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000019 def values(self):
Georg Brandlcd4a21b2010-02-06 23:34:10 +000020 # XXX never used?
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000021 result = self.items()
Georg Brandlcd4a21b2010-02-06 23:34:10 +000022 return [i[1] for i in result]
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000023
24 def iteritems(self): return iter(self.items())
25 def iterkeys(self): return iter(self.keys())
26 __iter__ = iterkeys
27 def itervalues(self): return iter(self.values())
Fred Drake3d5f7e82000-12-04 16:30:40 +000028
Fred Drakec6f28912002-10-25 19:40:49 +000029class TestCaseBase(unittest.TestCase):
30 def newconfig(self, defaults=None):
31 if defaults is None:
32 self.cf = self.config_class()
33 else:
34 self.cf = self.config_class(defaults)
35 return self.cf
Fred Drake8ef67672000-09-27 22:45:25 +000036
Fred Drakec6f28912002-10-25 19:40:49 +000037 def fromstring(self, string, defaults=None):
38 cf = self.newconfig(defaults)
39 sio = StringIO.StringIO(string)
40 cf.readfp(sio)
41 return cf
Fred Drake8ef67672000-09-27 22:45:25 +000042
Fred Drakec6f28912002-10-25 19:40:49 +000043 def test_basic(self):
44 cf = self.fromstring(
45 "[Foo Bar]\n"
46 "foo=bar\n"
47 "[Spacey Bar]\n"
48 "foo = bar\n"
49 "[Commented Bar]\n"
50 "foo: bar ; comment\n"
51 "[Long Line]\n"
52 "foo: this line is much, much longer than my editor\n"
53 " likes it.\n"
54 "[Section\\with$weird%characters[\t]\n"
55 "[Internationalized Stuff]\n"
56 "foo[bg]: Bulgarian\n"
57 "foo=Default\n"
58 "foo[en]=English\n"
59 "foo[de]=Deutsch\n"
60 "[Spaces]\n"
61 "key with spaces : value\n"
62 "another with spaces = splat!\n"
63 )
64 L = cf.sections()
65 L.sort()
66 eq = self.assertEqual
67 eq(L, [r'Commented Bar',
68 r'Foo Bar',
69 r'Internationalized Stuff',
70 r'Long Line',
71 r'Section\with$weird%characters[' '\t',
72 r'Spaces',
73 r'Spacey Bar',
74 ])
Fred Drake8ef67672000-09-27 22:45:25 +000075
Fred Drakec6f28912002-10-25 19:40:49 +000076 # The use of spaces in the section names serves as a
77 # regression test for SourceForge bug #583248:
78 # http://www.python.org/sf/583248
79 eq(cf.get('Foo Bar', 'foo'), 'bar')
80 eq(cf.get('Spacey Bar', 'foo'), 'bar')
81 eq(cf.get('Commented Bar', 'foo'), 'bar')
82 eq(cf.get('Spaces', 'key with spaces'), 'value')
83 eq(cf.get('Spaces', 'another with spaces'), 'splat!')
Fred Drake3d5f7e82000-12-04 16:30:40 +000084
Ezio Melottiaa980582010-01-23 23:04:36 +000085 self.assertNotIn('__name__', cf.options("Foo Bar"),
86 '__name__ "option" should not be exposed by the API!')
Fred Drakec6f28912002-10-25 19:40:49 +000087
88 # Make sure the right things happen for remove_option();
89 # added to include check for SourceForge bug #123324:
Benjamin Peterson5c8da862009-06-30 22:57:08 +000090 self.assertTrue(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson3e4caeb2009-02-21 20:27:01 +000091 "remove_option() failed to report existence of option")
Benjamin Peterson5c8da862009-06-30 22:57:08 +000092 self.assertFalse(cf.has_option('Foo Bar', 'foo'),
Fred Drakec6f28912002-10-25 19:40:49 +000093 "remove_option() failed to remove option")
Benjamin Peterson5c8da862009-06-30 22:57:08 +000094 self.assertFalse(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson3e4caeb2009-02-21 20:27:01 +000095 "remove_option() failed to report non-existence of option"
Fred Drakec6f28912002-10-25 19:40:49 +000096 " that was removed")
97
Georg Brandl392c6fc2008-05-25 07:25:25 +000098 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +000099 cf.remove_option, 'No Such Section', 'foo')
100
101 eq(cf.get('Long Line', 'foo'),
Andrew M. Kuchling1bf71172002-03-08 18:10:12 +0000102 'this line is much, much longer than my editor\nlikes it.')
Fred Drake3d5f7e82000-12-04 16:30:40 +0000103
Fred Drakec6f28912002-10-25 19:40:49 +0000104 def test_case_sensitivity(self):
105 cf = self.newconfig()
106 cf.add_section("A")
107 cf.add_section("a")
108 L = cf.sections()
109 L.sort()
110 eq = self.assertEqual
111 eq(L, ["A", "a"])
112 cf.set("a", "B", "value")
113 eq(cf.options("a"), ["b"])
114 eq(cf.get("a", "b"), "value",
Fred Drake3c823aa2001-02-26 21:55:34 +0000115 "could not locate option, expecting case-insensitive option names")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000116 self.assertTrue(cf.has_option("a", "b"))
Fred Drakec6f28912002-10-25 19:40:49 +0000117 cf.set("A", "A-B", "A-B value")
118 for opt in ("a-b", "A-b", "a-B", "A-B"):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000119 self.assertTrue(
Fred Drakec6f28912002-10-25 19:40:49 +0000120 cf.has_option("A", opt),
121 "has_option() returned false for option which should exist")
122 eq(cf.options("A"), ["a-b"])
123 eq(cf.options("a"), ["b"])
124 cf.remove_option("a", "B")
125 eq(cf.options("a"), [])
Fred Drake3c823aa2001-02-26 21:55:34 +0000126
Fred Drakec6f28912002-10-25 19:40:49 +0000127 # SF bug #432369:
128 cf = self.fromstring(
129 "[MySection]\nOption: first line\n\tsecond line\n")
130 eq(cf.options("MySection"), ["option"])
131 eq(cf.get("MySection", "Option"), "first line\nsecond line")
Fred Drakebeb67132001-07-06 17:22:48 +0000132
Fred Drakec6f28912002-10-25 19:40:49 +0000133 # SF bug #561822:
134 cf = self.fromstring("[section]\nnekey=nevalue\n",
135 defaults={"key":"value"})
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000136 self.assertTrue(cf.has_option("section", "Key"))
Fred Drake309db062002-09-27 15:35:23 +0000137
Fred Drake3c823aa2001-02-26 21:55:34 +0000138
David Goodger68a1abd2004-10-03 15:40:25 +0000139 def test_default_case_sensitivity(self):
140 cf = self.newconfig({"foo": "Bar"})
141 self.assertEqual(
142 cf.get("DEFAULT", "Foo"), "Bar",
143 "could not locate option, expecting case-insensitive option names")
144 cf = self.newconfig({"Foo": "Bar"})
145 self.assertEqual(
146 cf.get("DEFAULT", "Foo"), "Bar",
147 "could not locate option, expecting case-insensitive defaults")
148
Fred Drakec6f28912002-10-25 19:40:49 +0000149 def test_parse_errors(self):
150 self.newconfig()
Georg Brandl392c6fc2008-05-25 07:25:25 +0000151 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000152 "[Foo]\n extra-spaces: splat\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000153 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000154 "[Foo]\n extra-spaces= splat\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000155 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000156 "[Foo]\noption-without-value\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000157 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000158 "[Foo]\n:value-without-option-name\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000159 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000160 "[Foo]\n=value-without-option-name\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000161 self.parse_error(ConfigParser.MissingSectionHeaderError,
Fred Drakec6f28912002-10-25 19:40:49 +0000162 "No Section!\n")
Fred Drake168bead2001-10-08 17:13:12 +0000163
Fred Drakec6f28912002-10-25 19:40:49 +0000164 def parse_error(self, exc, src):
165 sio = StringIO.StringIO(src)
166 self.assertRaises(exc, self.cf.readfp, sio)
Fred Drake168bead2001-10-08 17:13:12 +0000167
Fred Drakec6f28912002-10-25 19:40:49 +0000168 def test_query_errors(self):
169 cf = self.newconfig()
170 self.assertEqual(cf.sections(), [],
171 "new ConfigParser should have no defined sections")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000172 self.assertFalse(cf.has_section("Foo"),
Fred Drakec6f28912002-10-25 19:40:49 +0000173 "new ConfigParser should have no acknowledged sections")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000174 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000175 cf.options, "Foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000176 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000177 cf.set, "foo", "bar", "value")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000178 self.get_error(ConfigParser.NoSectionError, "foo", "bar")
Fred Drakec6f28912002-10-25 19:40:49 +0000179 cf.add_section("foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000180 self.get_error(ConfigParser.NoOptionError, "foo", "bar")
Fred Drake8ef67672000-09-27 22:45:25 +0000181
Fred Drakec6f28912002-10-25 19:40:49 +0000182 def get_error(self, exc, section, option):
Fred Drake54782192002-12-31 06:57:25 +0000183 try:
184 self.cf.get(section, option)
185 except exc, e:
186 return e
187 else:
188 self.fail("expected exception type %s.%s"
189 % (exc.__module__, exc.__name__))
Fred Drake3af0eb82002-10-25 18:09:24 +0000190
Fred Drakec6f28912002-10-25 19:40:49 +0000191 def test_boolean(self):
192 cf = self.fromstring(
193 "[BOOLTEST]\n"
194 "T1=1\n"
195 "T2=TRUE\n"
196 "T3=True\n"
197 "T4=oN\n"
198 "T5=yes\n"
199 "F1=0\n"
200 "F2=FALSE\n"
201 "F3=False\n"
202 "F4=oFF\n"
203 "F5=nO\n"
204 "E1=2\n"
205 "E2=foo\n"
206 "E3=-1\n"
207 "E4=0.1\n"
208 "E5=FALSE AND MORE"
209 )
210 for x in range(1, 5):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000211 self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x))
212 self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x))
Fred Drakec6f28912002-10-25 19:40:49 +0000213 self.assertRaises(ValueError,
214 cf.getboolean, 'BOOLTEST', 'e%d' % x)
Fred Drake95b96d32001-02-12 17:23:20 +0000215
Fred Drakec6f28912002-10-25 19:40:49 +0000216 def test_weird_errors(self):
217 cf = self.newconfig()
Fred Drake8ef67672000-09-27 22:45:25 +0000218 cf.add_section("Foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000219 self.assertRaises(ConfigParser.DuplicateSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000220 cf.add_section, "Foo")
221
222 def test_write(self):
223 cf = self.fromstring(
224 "[Long Line]\n"
225 "foo: this line is much, much longer than my editor\n"
226 " likes it.\n"
227 "[DEFAULT]\n"
228 "foo: another very\n"
229 " long line"
230 )
231 output = StringIO.StringIO()
232 cf.write(output)
233 self.assertEqual(
234 output.getvalue(),
235 "[DEFAULT]\n"
236 "foo = another very\n"
237 "\tlong line\n"
238 "\n"
239 "[Long Line]\n"
240 "foo = this line is much, much longer than my editor\n"
241 "\tlikes it.\n"
242 "\n"
243 )
244
Fred Drakeabc086f2004-05-18 03:29:52 +0000245 def test_set_string_types(self):
246 cf = self.fromstring("[sect]\n"
247 "option1=foo\n")
248 # Check that we don't get an exception when setting values in
249 # an existing section using strings:
250 class mystr(str):
251 pass
252 cf.set("sect", "option1", "splat")
253 cf.set("sect", "option1", mystr("splat"))
254 cf.set("sect", "option2", "splat")
255 cf.set("sect", "option2", mystr("splat"))
256 try:
257 unicode
258 except NameError:
259 pass
260 else:
261 cf.set("sect", "option1", unicode("splat"))
262 cf.set("sect", "option2", unicode("splat"))
263
Fred Drake82903142004-05-18 04:24:02 +0000264 def test_read_returns_file_list(self):
265 file1 = test_support.findfile("cfgparser.1")
266 # check when we pass a mix of readable and non-readable files:
267 cf = self.newconfig()
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000268 parsed_files = cf.read([file1, "nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000269 self.assertEqual(parsed_files, [file1])
270 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
271 # check when we pass only a filename:
272 cf = self.newconfig()
273 parsed_files = cf.read(file1)
274 self.assertEqual(parsed_files, [file1])
275 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
276 # check when we pass only missing files:
277 cf = self.newconfig()
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000278 parsed_files = cf.read(["nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000279 self.assertEqual(parsed_files, [])
280 # check when we pass no files:
281 cf = self.newconfig()
282 parsed_files = cf.read([])
283 self.assertEqual(parsed_files, [])
284
Fred Drakec6f28912002-10-25 19:40:49 +0000285 # shared by subclasses
286 def get_interpolation_config(self):
287 return self.fromstring(
288 "[Foo]\n"
289 "bar=something %(with1)s interpolation (1 step)\n"
290 "bar9=something %(with9)s lots of interpolation (9 steps)\n"
291 "bar10=something %(with10)s lots of interpolation (10 steps)\n"
292 "bar11=something %(with11)s lots of interpolation (11 steps)\n"
293 "with11=%(with10)s\n"
294 "with10=%(with9)s\n"
295 "with9=%(with8)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000296 "with8=%(With7)s\n"
297 "with7=%(WITH6)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000298 "with6=%(with5)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000299 "With5=%(with4)s\n"
300 "WITH4=%(with3)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000301 "with3=%(with2)s\n"
302 "with2=%(with1)s\n"
303 "with1=with\n"
304 "\n"
305 "[Mutual Recursion]\n"
306 "foo=%(bar)s\n"
Fred Drake54782192002-12-31 06:57:25 +0000307 "bar=%(foo)s\n"
308 "\n"
309 "[Interpolation Error]\n"
310 "name=%(reference)s\n",
311 # no definition for 'reference'
Fred Drakec6f28912002-10-25 19:40:49 +0000312 defaults={"getname": "%(__name__)s"})
Fred Drake95b96d32001-02-12 17:23:20 +0000313
Fred Drake98e3b292002-10-25 20:42:44 +0000314 def check_items_config(self, expected):
315 cf = self.fromstring(
316 "[section]\n"
317 "name = value\n"
318 "key: |%(name)s| \n"
319 "getdefault: |%(default)s|\n"
320 "getname: |%(__name__)s|",
321 defaults={"default": "<default>"})
322 L = list(cf.items("section"))
323 L.sort()
324 self.assertEqual(L, expected)
325
Fred Drake8ef67672000-09-27 22:45:25 +0000326
Fred Drakec6f28912002-10-25 19:40:49 +0000327class ConfigParserTestCase(TestCaseBase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000328 config_class = ConfigParser.ConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000329
330 def test_interpolation(self):
331 cf = self.get_interpolation_config()
332 eq = self.assertEqual
333 eq(cf.get("Foo", "getname"), "Foo")
334 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
335 eq(cf.get("Foo", "bar9"),
336 "something with lots of interpolation (9 steps)")
337 eq(cf.get("Foo", "bar10"),
338 "something with lots of interpolation (10 steps)")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000339 self.get_error(ConfigParser.InterpolationDepthError, "Foo", "bar11")
Fred Drake95b96d32001-02-12 17:23:20 +0000340
Fred Drake54782192002-12-31 06:57:25 +0000341 def test_interpolation_missing_value(self):
342 cf = self.get_interpolation_config()
Georg Brandl392c6fc2008-05-25 07:25:25 +0000343 e = self.get_error(ConfigParser.InterpolationError,
Fred Drake54782192002-12-31 06:57:25 +0000344 "Interpolation Error", "name")
345 self.assertEqual(e.reference, "reference")
346 self.assertEqual(e.section, "Interpolation Error")
347 self.assertEqual(e.option, "name")
348
Fred Drake98e3b292002-10-25 20:42:44 +0000349 def test_items(self):
350 self.check_items_config([('default', '<default>'),
351 ('getdefault', '|<default>|'),
352 ('getname', '|section|'),
353 ('key', '|value|'),
354 ('name', 'value')])
355
David Goodger1cbf2062004-10-03 15:55:09 +0000356 def test_set_nonstring_types(self):
357 cf = self.newconfig()
358 cf.add_section('non-string')
359 cf.set('non-string', 'int', 1)
360 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%('])
361 cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1,
362 '%(list)': '%(list)'})
363 cf.set('non-string', 'string_with_interpolation', '%(list)s')
364 self.assertEqual(cf.get('non-string', 'int', raw=True), 1)
365 self.assertRaises(TypeError, cf.get, 'non-string', 'int')
366 self.assertEqual(cf.get('non-string', 'list', raw=True),
367 [0, 1, 1, 2, 3, 5, 8, 13, '%('])
368 self.assertRaises(TypeError, cf.get, 'non-string', 'list')
369 self.assertEqual(cf.get('non-string', 'dict', raw=True),
370 {'pi': 3.14159, '%(': 1, '%(list)': '%(list)'})
371 self.assertRaises(TypeError, cf.get, 'non-string', 'dict')
372 self.assertEqual(cf.get('non-string', 'string_with_interpolation',
373 raw=True), '%(list)s')
374 self.assertRaises(ValueError, cf.get, 'non-string',
375 'string_with_interpolation', raw=False)
376
Fred Drake8ef67672000-09-27 22:45:25 +0000377
Fred Drakec6f28912002-10-25 19:40:49 +0000378class RawConfigParserTestCase(TestCaseBase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000379 config_class = ConfigParser.RawConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000380
381 def test_interpolation(self):
382 cf = self.get_interpolation_config()
383 eq = self.assertEqual
384 eq(cf.get("Foo", "getname"), "%(__name__)s")
385 eq(cf.get("Foo", "bar"),
386 "something %(with1)s interpolation (1 step)")
387 eq(cf.get("Foo", "bar9"),
388 "something %(with9)s lots of interpolation (9 steps)")
389 eq(cf.get("Foo", "bar10"),
390 "something %(with10)s lots of interpolation (10 steps)")
391 eq(cf.get("Foo", "bar11"),
392 "something %(with11)s lots of interpolation (11 steps)")
Fred Drake95b96d32001-02-12 17:23:20 +0000393
Fred Drake98e3b292002-10-25 20:42:44 +0000394 def test_items(self):
395 self.check_items_config([('default', '<default>'),
396 ('getdefault', '|%(default)s|'),
397 ('getname', '|%(__name__)s|'),
398 ('key', '|%(name)s|'),
399 ('name', 'value')])
400
David Goodger1cbf2062004-10-03 15:55:09 +0000401 def test_set_nonstring_types(self):
402 cf = self.newconfig()
403 cf.add_section('non-string')
404 cf.set('non-string', 'int', 1)
405 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13])
406 cf.set('non-string', 'dict', {'pi': 3.14159})
407 self.assertEqual(cf.get('non-string', 'int'), 1)
408 self.assertEqual(cf.get('non-string', 'list'),
409 [0, 1, 1, 2, 3, 5, 8, 13])
410 self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159})
Tim Petersab9b32c2004-10-03 18:35:19 +0000411
Fred Drake8ef67672000-09-27 22:45:25 +0000412
Fred Drake0eebd5c2002-10-25 21:52:00 +0000413class SafeConfigParserTestCase(ConfigParserTestCase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000414 config_class = ConfigParser.SafeConfigParser
Fred Drake0eebd5c2002-10-25 21:52:00 +0000415
416 def test_safe_interpolation(self):
417 # See http://www.python.org/sf/511737
418 cf = self.fromstring("[section]\n"
419 "option1=xxx\n"
420 "option2=%(option1)s/xxx\n"
421 "ok=%(option1)s/%%s\n"
422 "not_ok=%(option2)s/%%s")
423 self.assertEqual(cf.get("section", "ok"), "xxx/%s")
424 self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s")
425
Georg Brandl92a6bae2007-03-13 17:43:32 +0000426 def test_set_malformatted_interpolation(self):
427 cf = self.fromstring("[sect]\n"
428 "option1=foo\n")
429
430 self.assertEqual(cf.get('sect', "option1"), "foo")
431
432 self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo")
433 self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%")
434 self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo")
435
436 self.assertEqual(cf.get('sect', "option1"), "foo")
437
Georg Brandl21cf5ee2009-04-12 17:24:11 +0000438 # bug #5741: double percents are *not* malformed
439 cf.set("sect", "option2", "foo%%bar")
440 self.assertEqual(cf.get("sect", "option2"), "foo%bar")
441
David Goodger1cbf2062004-10-03 15:55:09 +0000442 def test_set_nonstring_types(self):
443 cf = self.fromstring("[sect]\n"
444 "option1=foo\n")
445 # Check that we get a TypeError when setting non-string values
446 # in an existing section:
447 self.assertRaises(TypeError, cf.set, "sect", "option1", 1)
448 self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0)
449 self.assertRaises(TypeError, cf.set, "sect", "option1", object())
450 self.assertRaises(TypeError, cf.set, "sect", "option2", 1)
451 self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
452 self.assertRaises(TypeError, cf.set, "sect", "option2", object())
453
Facundo Batistab12f0b52008-02-23 12:46:10 +0000454 def test_add_section_default_1(self):
455 cf = self.newconfig()
456 self.assertRaises(ValueError, cf.add_section, "default")
457
458 def test_add_section_default_2(self):
459 cf = self.newconfig()
460 self.assertRaises(ValueError, cf.add_section, "DEFAULT")
461
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000462class SortedTestCase(RawConfigParserTestCase):
463 def newconfig(self, defaults=None):
464 self.cf = self.config_class(defaults=defaults, dict_type=SortedDict)
465 return self.cf
466
467 def test_sorted(self):
468 self.fromstring("[b]\n"
469 "o4=1\n"
470 "o3=2\n"
471 "o2=3\n"
472 "o1=4\n"
473 "[a]\n"
Tim Petersf733abb2007-01-30 03:03:46 +0000474 "k=v\n")
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000475 output = StringIO.StringIO()
476 self.cf.write(output)
477 self.assertEquals(output.getvalue(),
478 "[a]\n"
Tim Petersf733abb2007-01-30 03:03:46 +0000479 "k = v\n\n"
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000480 "[b]\n"
481 "o1 = 4\n"
482 "o2 = 3\n"
483 "o3 = 2\n"
484 "o4 = 1\n\n")
Fred Drake0eebd5c2002-10-25 21:52:00 +0000485
Fred Drakec6f28912002-10-25 19:40:49 +0000486def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000487 test_support.run_unittest(
488 ConfigParserTestCase,
489 RawConfigParserTestCase,
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000490 SafeConfigParserTestCase,
491 SortedTestCase
Walter Dörwald21d3a322003-05-01 17:45:56 +0000492 )
Fred Drake3af0eb82002-10-25 18:09:24 +0000493
Fred Drakec6f28912002-10-25 19:40:49 +0000494if __name__ == "__main__":
495 test_main()