blob: a3d26400b24ea09c0ffb73548a28c943965c27b1 [file] [log] [blame]
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +00001import configparser
Guido van Rossum34d19282007-08-09 01:03:29 +00002import io
Fred Drakec6f28912002-10-25 19:40:49 +00003import unittest
Raymond Hettingerf80680d2008-02-06 00:07:11 +00004import collections
Fred Drake8ef67672000-09-27 22:45:25 +00005
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Fred Drake3d5f7e82000-12-04 16:30:40 +00007
Raymond Hettingerf80680d2008-02-06 00:07:11 +00008class SortedDict(collections.UserDict):
Thomas Wouters89f507f2006-12-13 04:49:30 +00009 def items(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +000010 return sorted(self.data.items())
Thomas Wouters89f507f2006-12-13 04:49:30 +000011
12 def keys(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +000013 return sorted(self.data.keys())
Thomas Wouters9fe394c2007-02-05 01:24:16 +000014
Thomas Wouters89f507f2006-12-13 04:49:30 +000015 def values(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +000016 return [i[1] for i in self.items()]
Thomas Wouters89f507f2006-12-13 04:49:30 +000017
18 def iteritems(self): return iter(self.items())
19 def iterkeys(self): return iter(self.keys())
20 __iter__ = iterkeys
21 def itervalues(self): return iter(self.values())
Fred Drake3d5f7e82000-12-04 16:30:40 +000022
Fred Drakec6f28912002-10-25 19:40:49 +000023class TestCaseBase(unittest.TestCase):
24 def newconfig(self, defaults=None):
25 if defaults is None:
26 self.cf = self.config_class()
27 else:
28 self.cf = self.config_class(defaults)
29 return self.cf
Fred Drake8ef67672000-09-27 22:45:25 +000030
Fred Drakec6f28912002-10-25 19:40:49 +000031 def fromstring(self, string, defaults=None):
32 cf = self.newconfig(defaults)
Guido van Rossum34d19282007-08-09 01:03:29 +000033 sio = io.StringIO(string)
Fred Drakec6f28912002-10-25 19:40:49 +000034 cf.readfp(sio)
35 return cf
Fred Drake8ef67672000-09-27 22:45:25 +000036
Fred Drakec6f28912002-10-25 19:40:49 +000037 def test_basic(self):
38 cf = self.fromstring(
39 "[Foo Bar]\n"
40 "foo=bar\n"
41 "[Spacey Bar]\n"
42 "foo = bar\n"
43 "[Commented Bar]\n"
44 "foo: bar ; comment\n"
45 "[Long Line]\n"
46 "foo: this line is much, much longer than my editor\n"
47 " likes it.\n"
48 "[Section\\with$weird%characters[\t]\n"
49 "[Internationalized Stuff]\n"
50 "foo[bg]: Bulgarian\n"
51 "foo=Default\n"
52 "foo[en]=English\n"
53 "foo[de]=Deutsch\n"
54 "[Spaces]\n"
55 "key with spaces : value\n"
56 "another with spaces = splat!\n"
57 )
58 L = cf.sections()
59 L.sort()
60 eq = self.assertEqual
61 eq(L, [r'Commented Bar',
62 r'Foo Bar',
63 r'Internationalized Stuff',
64 r'Long Line',
65 r'Section\with$weird%characters[' '\t',
66 r'Spaces',
67 r'Spacey Bar',
68 ])
Fred Drake8ef67672000-09-27 22:45:25 +000069
Fred Drakec6f28912002-10-25 19:40:49 +000070 # The use of spaces in the section names serves as a
71 # regression test for SourceForge bug #583248:
72 # http://www.python.org/sf/583248
73 eq(cf.get('Foo Bar', 'foo'), 'bar')
74 eq(cf.get('Spacey Bar', 'foo'), 'bar')
75 eq(cf.get('Commented Bar', 'foo'), 'bar')
76 eq(cf.get('Spaces', 'key with spaces'), 'value')
77 eq(cf.get('Spaces', 'another with spaces'), 'splat!')
Fred Drake3d5f7e82000-12-04 16:30:40 +000078
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000079 self.assertFalse('__name__' in cf.options("Foo Bar"),
Fred Drakec6f28912002-10-25 19:40:49 +000080 '__name__ "option" should not be exposed by the API!')
81
82 # Make sure the right things happen for remove_option();
83 # added to include check for SourceForge bug #123324:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000084 self.assertTrue(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson934896d2009-02-21 20:59:32 +000085 "remove_option() failed to report existence of option")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000086 self.assertFalse(cf.has_option('Foo Bar', 'foo'),
Fred Drakec6f28912002-10-25 19:40:49 +000087 "remove_option() failed to remove option")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000088 self.assertFalse(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson934896d2009-02-21 20:59:32 +000089 "remove_option() failed to report non-existence of option"
Fred Drakec6f28912002-10-25 19:40:49 +000090 " that was removed")
91
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +000092 self.assertRaises(configparser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +000093 cf.remove_option, 'No Such Section', 'foo')
94
95 eq(cf.get('Long Line', 'foo'),
Andrew M. Kuchling1bf71172002-03-08 18:10:12 +000096 'this line is much, much longer than my editor\nlikes it.')
Fred Drake3d5f7e82000-12-04 16:30:40 +000097
Fred Drakec6f28912002-10-25 19:40:49 +000098 def test_case_sensitivity(self):
99 cf = self.newconfig()
100 cf.add_section("A")
101 cf.add_section("a")
102 L = cf.sections()
103 L.sort()
104 eq = self.assertEqual
105 eq(L, ["A", "a"])
106 cf.set("a", "B", "value")
107 eq(cf.options("a"), ["b"])
108 eq(cf.get("a", "b"), "value",
Fred Drake3c823aa2001-02-26 21:55:34 +0000109 "could not locate option, expecting case-insensitive option names")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000110 self.assertTrue(cf.has_option("a", "b"))
Fred Drakec6f28912002-10-25 19:40:49 +0000111 cf.set("A", "A-B", "A-B value")
112 for opt in ("a-b", "A-b", "a-B", "A-B"):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000113 self.assertTrue(
Fred Drakec6f28912002-10-25 19:40:49 +0000114 cf.has_option("A", opt),
115 "has_option() returned false for option which should exist")
116 eq(cf.options("A"), ["a-b"])
117 eq(cf.options("a"), ["b"])
118 cf.remove_option("a", "B")
119 eq(cf.options("a"), [])
Fred Drake3c823aa2001-02-26 21:55:34 +0000120
Fred Drakec6f28912002-10-25 19:40:49 +0000121 # SF bug #432369:
122 cf = self.fromstring(
123 "[MySection]\nOption: first line\n\tsecond line\n")
124 eq(cf.options("MySection"), ["option"])
125 eq(cf.get("MySection", "Option"), "first line\nsecond line")
Fred Drakebeb67132001-07-06 17:22:48 +0000126
Fred Drakec6f28912002-10-25 19:40:49 +0000127 # SF bug #561822:
128 cf = self.fromstring("[section]\nnekey=nevalue\n",
129 defaults={"key":"value"})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000130 self.assertTrue(cf.has_option("section", "Key"))
Fred Drake309db062002-09-27 15:35:23 +0000131
Fred Drake3c823aa2001-02-26 21:55:34 +0000132
David Goodger68a1abd2004-10-03 15:40:25 +0000133 def test_default_case_sensitivity(self):
134 cf = self.newconfig({"foo": "Bar"})
135 self.assertEqual(
136 cf.get("DEFAULT", "Foo"), "Bar",
137 "could not locate option, expecting case-insensitive option names")
138 cf = self.newconfig({"Foo": "Bar"})
139 self.assertEqual(
140 cf.get("DEFAULT", "Foo"), "Bar",
141 "could not locate option, expecting case-insensitive defaults")
142
Fred Drakec6f28912002-10-25 19:40:49 +0000143 def test_parse_errors(self):
144 self.newconfig()
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000145 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000146 "[Foo]\n extra-spaces: splat\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000147 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000148 "[Foo]\n extra-spaces= splat\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000149 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000150 "[Foo]\noption-without-value\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000151 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000152 "[Foo]\n:value-without-option-name\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000153 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000154 "[Foo]\n=value-without-option-name\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000155 self.parse_error(configparser.MissingSectionHeaderError,
Fred Drakec6f28912002-10-25 19:40:49 +0000156 "No Section!\n")
Fred Drake168bead2001-10-08 17:13:12 +0000157
Fred Drakec6f28912002-10-25 19:40:49 +0000158 def parse_error(self, exc, src):
Guido van Rossum34d19282007-08-09 01:03:29 +0000159 sio = io.StringIO(src)
Fred Drakec6f28912002-10-25 19:40:49 +0000160 self.assertRaises(exc, self.cf.readfp, sio)
Fred Drake168bead2001-10-08 17:13:12 +0000161
Fred Drakec6f28912002-10-25 19:40:49 +0000162 def test_query_errors(self):
163 cf = self.newconfig()
164 self.assertEqual(cf.sections(), [],
165 "new ConfigParser should have no defined sections")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000166 self.assertFalse(cf.has_section("Foo"),
Fred Drakec6f28912002-10-25 19:40:49 +0000167 "new ConfigParser should have no acknowledged sections")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000168 self.assertRaises(configparser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000169 cf.options, "Foo")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000170 self.assertRaises(configparser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000171 cf.set, "foo", "bar", "value")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000172 self.get_error(configparser.NoSectionError, "foo", "bar")
Fred Drakec6f28912002-10-25 19:40:49 +0000173 cf.add_section("foo")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000174 self.get_error(configparser.NoOptionError, "foo", "bar")
Fred Drake8ef67672000-09-27 22:45:25 +0000175
Fred Drakec6f28912002-10-25 19:40:49 +0000176 def get_error(self, exc, section, option):
Fred Drake54782192002-12-31 06:57:25 +0000177 try:
178 self.cf.get(section, option)
Guido van Rossumb940e112007-01-10 16:19:56 +0000179 except exc as e:
Fred Drake54782192002-12-31 06:57:25 +0000180 return e
181 else:
182 self.fail("expected exception type %s.%s"
183 % (exc.__module__, exc.__name__))
Fred Drake3af0eb82002-10-25 18:09:24 +0000184
Fred Drakec6f28912002-10-25 19:40:49 +0000185 def test_boolean(self):
186 cf = self.fromstring(
187 "[BOOLTEST]\n"
188 "T1=1\n"
189 "T2=TRUE\n"
190 "T3=True\n"
191 "T4=oN\n"
192 "T5=yes\n"
193 "F1=0\n"
194 "F2=FALSE\n"
195 "F3=False\n"
196 "F4=oFF\n"
197 "F5=nO\n"
198 "E1=2\n"
199 "E2=foo\n"
200 "E3=-1\n"
201 "E4=0.1\n"
202 "E5=FALSE AND MORE"
203 )
204 for x in range(1, 5):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000205 self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x))
206 self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x))
Fred Drakec6f28912002-10-25 19:40:49 +0000207 self.assertRaises(ValueError,
208 cf.getboolean, 'BOOLTEST', 'e%d' % x)
Fred Drake95b96d32001-02-12 17:23:20 +0000209
Fred Drakec6f28912002-10-25 19:40:49 +0000210 def test_weird_errors(self):
211 cf = self.newconfig()
Fred Drake8ef67672000-09-27 22:45:25 +0000212 cf.add_section("Foo")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000213 self.assertRaises(configparser.DuplicateSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000214 cf.add_section, "Foo")
215
216 def test_write(self):
217 cf = self.fromstring(
218 "[Long Line]\n"
219 "foo: this line is much, much longer than my editor\n"
220 " likes it.\n"
221 "[DEFAULT]\n"
222 "foo: another very\n"
223 " long line"
224 )
Guido van Rossum34d19282007-08-09 01:03:29 +0000225 output = io.StringIO()
Fred Drakec6f28912002-10-25 19:40:49 +0000226 cf.write(output)
227 self.assertEqual(
228 output.getvalue(),
229 "[DEFAULT]\n"
230 "foo = another very\n"
231 "\tlong line\n"
232 "\n"
233 "[Long Line]\n"
234 "foo = this line is much, much longer than my editor\n"
235 "\tlikes it.\n"
236 "\n"
237 )
238
Fred Drakeabc086f2004-05-18 03:29:52 +0000239 def test_set_string_types(self):
240 cf = self.fromstring("[sect]\n"
241 "option1=foo\n")
242 # Check that we don't get an exception when setting values in
243 # an existing section using strings:
244 class mystr(str):
245 pass
246 cf.set("sect", "option1", "splat")
247 cf.set("sect", "option1", mystr("splat"))
248 cf.set("sect", "option2", "splat")
249 cf.set("sect", "option2", mystr("splat"))
Walter Dörwald5de48bd2007-06-11 21:38:39 +0000250 cf.set("sect", "option1", "splat")
251 cf.set("sect", "option2", "splat")
Fred Drakeabc086f2004-05-18 03:29:52 +0000252
Fred Drake82903142004-05-18 04:24:02 +0000253 def test_read_returns_file_list(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000254 file1 = support.findfile("cfgparser.1")
Fred Drake82903142004-05-18 04:24:02 +0000255 # check when we pass a mix of readable and non-readable files:
256 cf = self.newconfig()
Mark Dickinson934896d2009-02-21 20:59:32 +0000257 parsed_files = cf.read([file1, "nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000258 self.assertEqual(parsed_files, [file1])
259 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
260 # check when we pass only a filename:
261 cf = self.newconfig()
262 parsed_files = cf.read(file1)
263 self.assertEqual(parsed_files, [file1])
264 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
265 # check when we pass only missing files:
266 cf = self.newconfig()
Mark Dickinson934896d2009-02-21 20:59:32 +0000267 parsed_files = cf.read(["nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000268 self.assertEqual(parsed_files, [])
269 # check when we pass no files:
270 cf = self.newconfig()
271 parsed_files = cf.read([])
272 self.assertEqual(parsed_files, [])
273
Fred Drakec6f28912002-10-25 19:40:49 +0000274 # shared by subclasses
275 def get_interpolation_config(self):
276 return self.fromstring(
277 "[Foo]\n"
278 "bar=something %(with1)s interpolation (1 step)\n"
279 "bar9=something %(with9)s lots of interpolation (9 steps)\n"
280 "bar10=something %(with10)s lots of interpolation (10 steps)\n"
281 "bar11=something %(with11)s lots of interpolation (11 steps)\n"
282 "with11=%(with10)s\n"
283 "with10=%(with9)s\n"
284 "with9=%(with8)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000285 "with8=%(With7)s\n"
286 "with7=%(WITH6)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000287 "with6=%(with5)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000288 "With5=%(with4)s\n"
289 "WITH4=%(with3)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000290 "with3=%(with2)s\n"
291 "with2=%(with1)s\n"
292 "with1=with\n"
293 "\n"
294 "[Mutual Recursion]\n"
295 "foo=%(bar)s\n"
Fred Drake54782192002-12-31 06:57:25 +0000296 "bar=%(foo)s\n"
297 "\n"
298 "[Interpolation Error]\n"
299 "name=%(reference)s\n",
300 # no definition for 'reference'
Fred Drakec6f28912002-10-25 19:40:49 +0000301 defaults={"getname": "%(__name__)s"})
Fred Drake95b96d32001-02-12 17:23:20 +0000302
Fred Drake98e3b292002-10-25 20:42:44 +0000303 def check_items_config(self, expected):
304 cf = self.fromstring(
305 "[section]\n"
306 "name = value\n"
307 "key: |%(name)s| \n"
308 "getdefault: |%(default)s|\n"
309 "getname: |%(__name__)s|",
310 defaults={"default": "<default>"})
311 L = list(cf.items("section"))
312 L.sort()
313 self.assertEqual(L, expected)
314
Fred Drake8ef67672000-09-27 22:45:25 +0000315
Fred Drakec6f28912002-10-25 19:40:49 +0000316class ConfigParserTestCase(TestCaseBase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000317 config_class = configparser.ConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000318
319 def test_interpolation(self):
320 cf = self.get_interpolation_config()
321 eq = self.assertEqual
322 eq(cf.get("Foo", "getname"), "Foo")
323 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
324 eq(cf.get("Foo", "bar9"),
325 "something with lots of interpolation (9 steps)")
326 eq(cf.get("Foo", "bar10"),
327 "something with lots of interpolation (10 steps)")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000328 self.get_error(configparser.InterpolationDepthError, "Foo", "bar11")
Fred Drake95b96d32001-02-12 17:23:20 +0000329
Fred Drake54782192002-12-31 06:57:25 +0000330 def test_interpolation_missing_value(self):
331 cf = self.get_interpolation_config()
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000332 e = self.get_error(configparser.InterpolationError,
Fred Drake54782192002-12-31 06:57:25 +0000333 "Interpolation Error", "name")
334 self.assertEqual(e.reference, "reference")
335 self.assertEqual(e.section, "Interpolation Error")
336 self.assertEqual(e.option, "name")
337
Fred Drake98e3b292002-10-25 20:42:44 +0000338 def test_items(self):
339 self.check_items_config([('default', '<default>'),
340 ('getdefault', '|<default>|'),
341 ('getname', '|section|'),
342 ('key', '|value|'),
343 ('name', 'value')])
344
David Goodger1cbf2062004-10-03 15:55:09 +0000345 def test_set_nonstring_types(self):
346 cf = self.newconfig()
347 cf.add_section('non-string')
348 cf.set('non-string', 'int', 1)
349 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%('])
350 cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1,
351 '%(list)': '%(list)'})
352 cf.set('non-string', 'string_with_interpolation', '%(list)s')
353 self.assertEqual(cf.get('non-string', 'int', raw=True), 1)
354 self.assertRaises(TypeError, cf.get, 'non-string', 'int')
355 self.assertEqual(cf.get('non-string', 'list', raw=True),
356 [0, 1, 1, 2, 3, 5, 8, 13, '%('])
357 self.assertRaises(TypeError, cf.get, 'non-string', 'list')
358 self.assertEqual(cf.get('non-string', 'dict', raw=True),
359 {'pi': 3.14159, '%(': 1, '%(list)': '%(list)'})
360 self.assertRaises(TypeError, cf.get, 'non-string', 'dict')
361 self.assertEqual(cf.get('non-string', 'string_with_interpolation',
362 raw=True), '%(list)s')
363 self.assertRaises(ValueError, cf.get, 'non-string',
364 'string_with_interpolation', raw=False)
365
Fred Drake8ef67672000-09-27 22:45:25 +0000366
Fred Drakec6f28912002-10-25 19:40:49 +0000367class RawConfigParserTestCase(TestCaseBase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000368 config_class = configparser.RawConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000369
370 def test_interpolation(self):
371 cf = self.get_interpolation_config()
372 eq = self.assertEqual
373 eq(cf.get("Foo", "getname"), "%(__name__)s")
374 eq(cf.get("Foo", "bar"),
375 "something %(with1)s interpolation (1 step)")
376 eq(cf.get("Foo", "bar9"),
377 "something %(with9)s lots of interpolation (9 steps)")
378 eq(cf.get("Foo", "bar10"),
379 "something %(with10)s lots of interpolation (10 steps)")
380 eq(cf.get("Foo", "bar11"),
381 "something %(with11)s lots of interpolation (11 steps)")
Fred Drake95b96d32001-02-12 17:23:20 +0000382
Fred Drake98e3b292002-10-25 20:42:44 +0000383 def test_items(self):
384 self.check_items_config([('default', '<default>'),
385 ('getdefault', '|%(default)s|'),
386 ('getname', '|%(__name__)s|'),
387 ('key', '|%(name)s|'),
388 ('name', 'value')])
389
David Goodger1cbf2062004-10-03 15:55:09 +0000390 def test_set_nonstring_types(self):
391 cf = self.newconfig()
392 cf.add_section('non-string')
393 cf.set('non-string', 'int', 1)
394 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13])
395 cf.set('non-string', 'dict', {'pi': 3.14159})
396 self.assertEqual(cf.get('non-string', 'int'), 1)
397 self.assertEqual(cf.get('non-string', 'list'),
398 [0, 1, 1, 2, 3, 5, 8, 13])
399 self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159})
Tim Petersab9b32c2004-10-03 18:35:19 +0000400
Fred Drake8ef67672000-09-27 22:45:25 +0000401
Fred Drake0eebd5c2002-10-25 21:52:00 +0000402class SafeConfigParserTestCase(ConfigParserTestCase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000403 config_class = configparser.SafeConfigParser
Fred Drake0eebd5c2002-10-25 21:52:00 +0000404
405 def test_safe_interpolation(self):
406 # See http://www.python.org/sf/511737
407 cf = self.fromstring("[section]\n"
408 "option1=xxx\n"
409 "option2=%(option1)s/xxx\n"
410 "ok=%(option1)s/%%s\n"
411 "not_ok=%(option2)s/%%s")
412 self.assertEqual(cf.get("section", "ok"), "xxx/%s")
413 self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s")
414
Guido van Rossumd8faa362007-04-27 19:54:29 +0000415 def test_set_malformatted_interpolation(self):
416 cf = self.fromstring("[sect]\n"
417 "option1=foo\n")
418
419 self.assertEqual(cf.get('sect', "option1"), "foo")
420
421 self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo")
422 self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%")
423 self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo")
424
425 self.assertEqual(cf.get('sect', "option1"), "foo")
426
Georg Brandl1f9fa312009-04-27 16:42:58 +0000427 # bug #5741: double percents are *not* malformed
428 cf.set("sect", "option2", "foo%%bar")
429 self.assertEqual(cf.get("sect", "option2"), "foo%bar")
430
David Goodger1cbf2062004-10-03 15:55:09 +0000431 def test_set_nonstring_types(self):
432 cf = self.fromstring("[sect]\n"
433 "option1=foo\n")
434 # Check that we get a TypeError when setting non-string values
435 # in an existing section:
436 self.assertRaises(TypeError, cf.set, "sect", "option1", 1)
437 self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0)
438 self.assertRaises(TypeError, cf.set, "sect", "option1", object())
439 self.assertRaises(TypeError, cf.set, "sect", "option2", 1)
440 self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
441 self.assertRaises(TypeError, cf.set, "sect", "option2", object())
442
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000443 def test_add_section_default_1(self):
444 cf = self.newconfig()
445 self.assertRaises(ValueError, cf.add_section, "default")
446
447 def test_add_section_default_2(self):
448 cf = self.newconfig()
449 self.assertRaises(ValueError, cf.add_section, "DEFAULT")
450
Thomas Wouters89f507f2006-12-13 04:49:30 +0000451class SortedTestCase(RawConfigParserTestCase):
452 def newconfig(self, defaults=None):
453 self.cf = self.config_class(defaults=defaults, dict_type=SortedDict)
454 return self.cf
455
456 def test_sorted(self):
457 self.fromstring("[b]\n"
458 "o4=1\n"
459 "o3=2\n"
460 "o2=3\n"
461 "o1=4\n"
462 "[a]\n"
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000463 "k=v\n")
Guido van Rossum34d19282007-08-09 01:03:29 +0000464 output = io.StringIO()
Thomas Wouters89f507f2006-12-13 04:49:30 +0000465 self.cf.write(output)
466 self.assertEquals(output.getvalue(),
467 "[a]\n"
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000468 "k = v\n\n"
Thomas Wouters89f507f2006-12-13 04:49:30 +0000469 "[b]\n"
470 "o1 = 4\n"
471 "o2 = 3\n"
472 "o3 = 2\n"
473 "o4 = 1\n\n")
Fred Drake0eebd5c2002-10-25 21:52:00 +0000474
Fred Drakec6f28912002-10-25 19:40:49 +0000475def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000476 support.run_unittest(
Walter Dörwald21d3a322003-05-01 17:45:56 +0000477 ConfigParserTestCase,
478 RawConfigParserTestCase,
Thomas Wouters89f507f2006-12-13 04:49:30 +0000479 SafeConfigParserTestCase,
480 SortedTestCase
Walter Dörwald21d3a322003-05-01 17:45:56 +0000481 )
Fred Drake3af0eb82002-10-25 18:09:24 +0000482
Fred Drakec6f28912002-10-25 19:40:49 +0000483if __name__ == "__main__":
484 test_main()