blob: 5494bfcf547754f356a615cd5dafec0705b1d10d [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):
Fred Drake03c44a32010-02-19 06:08:41 +00009
Thomas Wouters89f507f2006-12-13 04:49:30 +000010 def items(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +000011 return sorted(self.data.items())
Thomas Wouters89f507f2006-12-13 04:49:30 +000012
13 def keys(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +000014 return sorted(self.data.keys())
Thomas Wouters9fe394c2007-02-05 01:24:16 +000015
Thomas Wouters89f507f2006-12-13 04:49:30 +000016 def values(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +000017 return [i[1] for i in self.items()]
Thomas Wouters89f507f2006-12-13 04:49:30 +000018
19 def iteritems(self): return iter(self.items())
20 def iterkeys(self): return iter(self.keys())
21 __iter__ = iterkeys
22 def itervalues(self): return iter(self.values())
Fred Drake3d5f7e82000-12-04 16:30:40 +000023
Fred Drake03c44a32010-02-19 06:08:41 +000024
Fred Drakec6f28912002-10-25 19:40:49 +000025class TestCaseBase(unittest.TestCase):
Fred Drake03c44a32010-02-19 06:08:41 +000026 allow_no_value = False
27
Fred Drakec6f28912002-10-25 19:40:49 +000028 def newconfig(self, defaults=None):
29 if defaults is None:
Fred Drake03c44a32010-02-19 06:08:41 +000030 self.cf = self.config_class(allow_no_value=self.allow_no_value)
Fred Drakec6f28912002-10-25 19:40:49 +000031 else:
Fred Drake03c44a32010-02-19 06:08:41 +000032 self.cf = self.config_class(defaults,
33 allow_no_value=self.allow_no_value)
Fred Drakec6f28912002-10-25 19:40:49 +000034 return self.cf
Fred Drake8ef67672000-09-27 22:45:25 +000035
Fred Drakec6f28912002-10-25 19:40:49 +000036 def fromstring(self, string, defaults=None):
37 cf = self.newconfig(defaults)
Guido van Rossum34d19282007-08-09 01:03:29 +000038 sio = io.StringIO(string)
Fred Drakec6f28912002-10-25 19:40:49 +000039 cf.readfp(sio)
40 return cf
Fred Drake8ef67672000-09-27 22:45:25 +000041
Fred Drakec6f28912002-10-25 19:40:49 +000042 def test_basic(self):
Fred Drake03c44a32010-02-19 06:08:41 +000043 config_string = (
Fred Drakec6f28912002-10-25 19:40:49 +000044 "[Foo Bar]\n"
45 "foo=bar\n"
46 "[Spacey Bar]\n"
47 "foo = bar\n"
48 "[Commented Bar]\n"
49 "foo: bar ; comment\n"
50 "[Long Line]\n"
51 "foo: this line is much, much longer than my editor\n"
52 " likes it.\n"
53 "[Section\\with$weird%characters[\t]\n"
54 "[Internationalized Stuff]\n"
55 "foo[bg]: Bulgarian\n"
56 "foo=Default\n"
57 "foo[en]=English\n"
58 "foo[de]=Deutsch\n"
59 "[Spaces]\n"
60 "key with spaces : value\n"
61 "another with spaces = splat!\n"
62 )
Fred Drake03c44a32010-02-19 06:08:41 +000063 if self.allow_no_value:
64 config_string += (
65 "[NoValue]\n"
66 "option-without-value\n"
67 )
68
69 cf = self.fromstring(config_string)
Fred Drakec6f28912002-10-25 19:40:49 +000070 L = cf.sections()
71 L.sort()
Fred Drake03c44a32010-02-19 06:08:41 +000072 E = [r'Commented Bar',
73 r'Foo Bar',
74 r'Internationalized Stuff',
75 r'Long Line',
76 r'Section\with$weird%characters[' '\t',
77 r'Spaces',
78 r'Spacey Bar',
79 ]
80 if self.allow_no_value:
81 E.append(r'NoValue')
82 E.sort()
Fred Drakec6f28912002-10-25 19:40:49 +000083 eq = self.assertEqual
Fred Drake03c44a32010-02-19 06:08:41 +000084 eq(L, E)
Fred Drake8ef67672000-09-27 22:45:25 +000085
Fred Drakec6f28912002-10-25 19:40:49 +000086 # The use of spaces in the section names serves as a
87 # regression test for SourceForge bug #583248:
88 # http://www.python.org/sf/583248
89 eq(cf.get('Foo Bar', 'foo'), 'bar')
90 eq(cf.get('Spacey Bar', 'foo'), 'bar')
91 eq(cf.get('Commented Bar', 'foo'), 'bar')
92 eq(cf.get('Spaces', 'key with spaces'), 'value')
93 eq(cf.get('Spaces', 'another with spaces'), 'splat!')
Fred Drake03c44a32010-02-19 06:08:41 +000094 if self.allow_no_value:
95 eq(cf.get('NoValue', 'option-without-value'), None)
Fred Drake3d5f7e82000-12-04 16:30:40 +000096
Ezio Melottib58e0bd2010-01-23 15:40:09 +000097 self.assertNotIn('__name__', cf.options("Foo Bar"),
98 '__name__ "option" should not be exposed by the API!')
Fred Drakec6f28912002-10-25 19:40:49 +000099
100 # Make sure the right things happen for remove_option();
101 # added to include check for SourceForge bug #123324:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000102 self.assertTrue(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson934896d2009-02-21 20:59:32 +0000103 "remove_option() failed to report existence of option")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000104 self.assertFalse(cf.has_option('Foo Bar', 'foo'),
Fred Drakec6f28912002-10-25 19:40:49 +0000105 "remove_option() failed to remove option")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000106 self.assertFalse(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson934896d2009-02-21 20:59:32 +0000107 "remove_option() failed to report non-existence of option"
Fred Drakec6f28912002-10-25 19:40:49 +0000108 " that was removed")
109
Michael Foordbd6c0792010-07-25 23:09:25 +0000110 with self.assertRaises(configparser.NoSectionError) as cm:
111 cf.remove_option('No Such Section', 'foo')
112 self.assertEqual(cm.exception.args, ('No Such Section',))
Fred Drakec6f28912002-10-25 19:40:49 +0000113
114 eq(cf.get('Long Line', 'foo'),
Andrew M. Kuchling1bf71172002-03-08 18:10:12 +0000115 'this line is much, much longer than my editor\nlikes it.')
Fred Drake3d5f7e82000-12-04 16:30:40 +0000116
Fred Drakec6f28912002-10-25 19:40:49 +0000117 def test_case_sensitivity(self):
118 cf = self.newconfig()
119 cf.add_section("A")
120 cf.add_section("a")
121 L = cf.sections()
122 L.sort()
123 eq = self.assertEqual
124 eq(L, ["A", "a"])
125 cf.set("a", "B", "value")
126 eq(cf.options("a"), ["b"])
127 eq(cf.get("a", "b"), "value",
Fred Drake3c823aa2001-02-26 21:55:34 +0000128 "could not locate option, expecting case-insensitive option names")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000129 self.assertTrue(cf.has_option("a", "b"))
Fred Drakec6f28912002-10-25 19:40:49 +0000130 cf.set("A", "A-B", "A-B value")
131 for opt in ("a-b", "A-b", "a-B", "A-B"):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000132 self.assertTrue(
Fred Drakec6f28912002-10-25 19:40:49 +0000133 cf.has_option("A", opt),
134 "has_option() returned false for option which should exist")
135 eq(cf.options("A"), ["a-b"])
136 eq(cf.options("a"), ["b"])
137 cf.remove_option("a", "B")
138 eq(cf.options("a"), [])
Fred Drake3c823aa2001-02-26 21:55:34 +0000139
Fred Drakec6f28912002-10-25 19:40:49 +0000140 # SF bug #432369:
141 cf = self.fromstring(
142 "[MySection]\nOption: first line\n\tsecond line\n")
143 eq(cf.options("MySection"), ["option"])
144 eq(cf.get("MySection", "Option"), "first line\nsecond line")
Fred Drakebeb67132001-07-06 17:22:48 +0000145
Fred Drakec6f28912002-10-25 19:40:49 +0000146 # SF bug #561822:
147 cf = self.fromstring("[section]\nnekey=nevalue\n",
148 defaults={"key":"value"})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000149 self.assertTrue(cf.has_option("section", "Key"))
Fred Drake309db062002-09-27 15:35:23 +0000150
Fred Drake3c823aa2001-02-26 21:55:34 +0000151
David Goodger68a1abd2004-10-03 15:40:25 +0000152 def test_default_case_sensitivity(self):
153 cf = self.newconfig({"foo": "Bar"})
154 self.assertEqual(
155 cf.get("DEFAULT", "Foo"), "Bar",
156 "could not locate option, expecting case-insensitive option names")
157 cf = self.newconfig({"Foo": "Bar"})
158 self.assertEqual(
159 cf.get("DEFAULT", "Foo"), "Bar",
160 "could not locate option, expecting case-insensitive defaults")
161
Fred Drakec6f28912002-10-25 19:40:49 +0000162 def test_parse_errors(self):
163 self.newconfig()
Michael Foordbd6c0792010-07-25 23:09:25 +0000164 e = self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000165 "[Foo]\n extra-spaces: splat\n")
Michael Foordbd6c0792010-07-25 23:09:25 +0000166 self.assertEqual(e.args, ('<???>',))
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000167 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000168 "[Foo]\n extra-spaces= splat\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000169 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000170 "[Foo]\n:value-without-option-name\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000171 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000172 "[Foo]\n=value-without-option-name\n")
Michael Foordbd6c0792010-07-25 23:09:25 +0000173 e = self.parse_error(configparser.MissingSectionHeaderError,
Fred Drakec6f28912002-10-25 19:40:49 +0000174 "No Section!\n")
Michael Foordbd6c0792010-07-25 23:09:25 +0000175 self.assertEqual(e.args, ('<???>', 1, "No Section!\n"))
Fred Drake168bead2001-10-08 17:13:12 +0000176
Fred Drakec6f28912002-10-25 19:40:49 +0000177 def parse_error(self, exc, src):
Guido van Rossum34d19282007-08-09 01:03:29 +0000178 sio = io.StringIO(src)
Michael Foordbd6c0792010-07-25 23:09:25 +0000179 with self.assertRaises(exc) as cm:
180 self.cf.readfp(sio)
181 return cm.exception
Fred Drake168bead2001-10-08 17:13:12 +0000182
Fred Drakec6f28912002-10-25 19:40:49 +0000183 def test_query_errors(self):
184 cf = self.newconfig()
185 self.assertEqual(cf.sections(), [],
186 "new ConfigParser should have no defined sections")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000187 self.assertFalse(cf.has_section("Foo"),
Fred Drakec6f28912002-10-25 19:40:49 +0000188 "new ConfigParser should have no acknowledged sections")
Michael Foordbd6c0792010-07-25 23:09:25 +0000189 with self.assertRaises(configparser.NoSectionError) as cm:
190 cf.options("Foo")
191 with self.assertRaises(configparser.NoSectionError) as cm:
192 cf.set("foo", "bar", "value")
193 e = self.get_error(configparser.NoSectionError, "foo", "bar")
194 self.assertEqual(e.args, ("foo",))
Fred Drakec6f28912002-10-25 19:40:49 +0000195 cf.add_section("foo")
Michael Foordbd6c0792010-07-25 23:09:25 +0000196 e = self.get_error(configparser.NoOptionError, "foo", "bar")
197 self.assertEqual(e.args, ("bar", "foo"))
Fred Drake8ef67672000-09-27 22:45:25 +0000198
Fred Drakec6f28912002-10-25 19:40:49 +0000199 def get_error(self, exc, section, option):
Fred Drake54782192002-12-31 06:57:25 +0000200 try:
201 self.cf.get(section, option)
Guido van Rossumb940e112007-01-10 16:19:56 +0000202 except exc as e:
Fred Drake54782192002-12-31 06:57:25 +0000203 return e
204 else:
205 self.fail("expected exception type %s.%s"
206 % (exc.__module__, exc.__name__))
Fred Drake3af0eb82002-10-25 18:09:24 +0000207
Fred Drakec6f28912002-10-25 19:40:49 +0000208 def test_boolean(self):
209 cf = self.fromstring(
210 "[BOOLTEST]\n"
211 "T1=1\n"
212 "T2=TRUE\n"
213 "T3=True\n"
214 "T4=oN\n"
215 "T5=yes\n"
216 "F1=0\n"
217 "F2=FALSE\n"
218 "F3=False\n"
219 "F4=oFF\n"
220 "F5=nO\n"
221 "E1=2\n"
222 "E2=foo\n"
223 "E3=-1\n"
224 "E4=0.1\n"
225 "E5=FALSE AND MORE"
226 )
227 for x in range(1, 5):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000228 self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x))
229 self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x))
Fred Drakec6f28912002-10-25 19:40:49 +0000230 self.assertRaises(ValueError,
231 cf.getboolean, 'BOOLTEST', 'e%d' % x)
Fred Drake95b96d32001-02-12 17:23:20 +0000232
Fred Drakec6f28912002-10-25 19:40:49 +0000233 def test_weird_errors(self):
234 cf = self.newconfig()
Fred Drake8ef67672000-09-27 22:45:25 +0000235 cf.add_section("Foo")
Michael Foordbd6c0792010-07-25 23:09:25 +0000236 with self.assertRaises(configparser.DuplicateSectionError) as cm:
237 cf.add_section("Foo")
238 self.assertEqual(cm.exception.args, ("Foo",))
Fred Drakec6f28912002-10-25 19:40:49 +0000239
240 def test_write(self):
Fred Drake03c44a32010-02-19 06:08:41 +0000241 config_string = (
Fred Drakec6f28912002-10-25 19:40:49 +0000242 "[Long Line]\n"
243 "foo: this line is much, much longer than my editor\n"
244 " likes it.\n"
245 "[DEFAULT]\n"
246 "foo: another very\n"
Fred Drake03c44a32010-02-19 06:08:41 +0000247 " long line\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000248 )
Fred Drake03c44a32010-02-19 06:08:41 +0000249 if self.allow_no_value:
250 config_string += (
251 "[Valueless]\n"
252 "option-without-value\n"
253 )
254
255 cf = self.fromstring(config_string)
Guido van Rossum34d19282007-08-09 01:03:29 +0000256 output = io.StringIO()
Fred Drakec6f28912002-10-25 19:40:49 +0000257 cf.write(output)
Fred Drake03c44a32010-02-19 06:08:41 +0000258 expect_string = (
Fred Drakec6f28912002-10-25 19:40:49 +0000259 "[DEFAULT]\n"
260 "foo = another very\n"
261 "\tlong line\n"
262 "\n"
263 "[Long Line]\n"
264 "foo = this line is much, much longer than my editor\n"
265 "\tlikes it.\n"
266 "\n"
267 )
Fred Drake03c44a32010-02-19 06:08:41 +0000268 if self.allow_no_value:
269 expect_string += (
270 "[Valueless]\n"
271 "option-without-value\n"
272 "\n"
273 )
274 self.assertEqual(output.getvalue(), expect_string)
Fred Drakec6f28912002-10-25 19:40:49 +0000275
Fred Drakeabc086f2004-05-18 03:29:52 +0000276 def test_set_string_types(self):
277 cf = self.fromstring("[sect]\n"
278 "option1=foo\n")
279 # Check that we don't get an exception when setting values in
280 # an existing section using strings:
281 class mystr(str):
282 pass
283 cf.set("sect", "option1", "splat")
284 cf.set("sect", "option1", mystr("splat"))
285 cf.set("sect", "option2", "splat")
286 cf.set("sect", "option2", mystr("splat"))
Walter Dörwald5de48bd2007-06-11 21:38:39 +0000287 cf.set("sect", "option1", "splat")
288 cf.set("sect", "option2", "splat")
Fred Drakeabc086f2004-05-18 03:29:52 +0000289
Fred Drake82903142004-05-18 04:24:02 +0000290 def test_read_returns_file_list(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000291 file1 = support.findfile("cfgparser.1")
Fred Drake82903142004-05-18 04:24:02 +0000292 # check when we pass a mix of readable and non-readable files:
293 cf = self.newconfig()
Mark Dickinson934896d2009-02-21 20:59:32 +0000294 parsed_files = cf.read([file1, "nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000295 self.assertEqual(parsed_files, [file1])
296 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
297 # check when we pass only a filename:
298 cf = self.newconfig()
299 parsed_files = cf.read(file1)
300 self.assertEqual(parsed_files, [file1])
301 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
302 # check when we pass only missing files:
303 cf = self.newconfig()
Mark Dickinson934896d2009-02-21 20:59:32 +0000304 parsed_files = cf.read(["nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000305 self.assertEqual(parsed_files, [])
306 # check when we pass no files:
307 cf = self.newconfig()
308 parsed_files = cf.read([])
309 self.assertEqual(parsed_files, [])
310
Fred Drakec6f28912002-10-25 19:40:49 +0000311 # shared by subclasses
312 def get_interpolation_config(self):
313 return self.fromstring(
314 "[Foo]\n"
315 "bar=something %(with1)s interpolation (1 step)\n"
316 "bar9=something %(with9)s lots of interpolation (9 steps)\n"
317 "bar10=something %(with10)s lots of interpolation (10 steps)\n"
318 "bar11=something %(with11)s lots of interpolation (11 steps)\n"
319 "with11=%(with10)s\n"
320 "with10=%(with9)s\n"
321 "with9=%(with8)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000322 "with8=%(With7)s\n"
323 "with7=%(WITH6)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000324 "with6=%(with5)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000325 "With5=%(with4)s\n"
326 "WITH4=%(with3)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000327 "with3=%(with2)s\n"
328 "with2=%(with1)s\n"
329 "with1=with\n"
330 "\n"
331 "[Mutual Recursion]\n"
332 "foo=%(bar)s\n"
Fred Drake54782192002-12-31 06:57:25 +0000333 "bar=%(foo)s\n"
334 "\n"
335 "[Interpolation Error]\n"
336 "name=%(reference)s\n",
337 # no definition for 'reference'
Fred Drakec6f28912002-10-25 19:40:49 +0000338 defaults={"getname": "%(__name__)s"})
Fred Drake95b96d32001-02-12 17:23:20 +0000339
Fred Drake98e3b292002-10-25 20:42:44 +0000340 def check_items_config(self, expected):
341 cf = self.fromstring(
342 "[section]\n"
343 "name = value\n"
344 "key: |%(name)s| \n"
345 "getdefault: |%(default)s|\n"
346 "getname: |%(__name__)s|",
347 defaults={"default": "<default>"})
348 L = list(cf.items("section"))
349 L.sort()
350 self.assertEqual(L, expected)
351
Fred Drake8ef67672000-09-27 22:45:25 +0000352
Fred Drakec6f28912002-10-25 19:40:49 +0000353class ConfigParserTestCase(TestCaseBase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000354 config_class = configparser.ConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000355
356 def test_interpolation(self):
Michael Foordbd6c0792010-07-25 23:09:25 +0000357 rawval = {
358 configparser.ConfigParser: "something %(with11)s "\
359 "lots of interpolation (11 steps)",
360 configparser.SafeConfigParser: "%(with1)s",
361 }
Fred Drakec6f28912002-10-25 19:40:49 +0000362 cf = self.get_interpolation_config()
363 eq = self.assertEqual
364 eq(cf.get("Foo", "getname"), "Foo")
365 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
366 eq(cf.get("Foo", "bar9"),
367 "something with lots of interpolation (9 steps)")
368 eq(cf.get("Foo", "bar10"),
369 "something with lots of interpolation (10 steps)")
Michael Foordbd6c0792010-07-25 23:09:25 +0000370 e = self.get_error(configparser.InterpolationDepthError, "Foo", "bar11")
371 self.assertEqual(e.args, ("bar11", "Foo", rawval[self.config_class]))
Fred Drake95b96d32001-02-12 17:23:20 +0000372
Fred Drake54782192002-12-31 06:57:25 +0000373 def test_interpolation_missing_value(self):
Michael Foordbd6c0792010-07-25 23:09:25 +0000374 rawval = {
375 configparser.ConfigParser: '%(reference)s',
376 configparser.SafeConfigParser: '',
377 }
Fred Drake03c44a32010-02-19 06:08:41 +0000378 self.get_interpolation_config()
Michael Foordbd6c0792010-07-25 23:09:25 +0000379 e = self.get_error(configparser.InterpolationMissingOptionError,
Fred Drake54782192002-12-31 06:57:25 +0000380 "Interpolation Error", "name")
381 self.assertEqual(e.reference, "reference")
382 self.assertEqual(e.section, "Interpolation Error")
383 self.assertEqual(e.option, "name")
Michael Foordbd6c0792010-07-25 23:09:25 +0000384 self.assertEqual(e.args, ('name', 'Interpolation Error',
385 rawval[self.config_class], 'reference'))
Fred Drake54782192002-12-31 06:57:25 +0000386
Fred Drake98e3b292002-10-25 20:42:44 +0000387 def test_items(self):
388 self.check_items_config([('default', '<default>'),
389 ('getdefault', '|<default>|'),
390 ('getname', '|section|'),
391 ('key', '|value|'),
392 ('name', 'value')])
393
David Goodger1cbf2062004-10-03 15:55:09 +0000394 def test_set_nonstring_types(self):
395 cf = self.newconfig()
396 cf.add_section('non-string')
397 cf.set('non-string', 'int', 1)
398 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%('])
399 cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1,
400 '%(list)': '%(list)'})
401 cf.set('non-string', 'string_with_interpolation', '%(list)s')
402 self.assertEqual(cf.get('non-string', 'int', raw=True), 1)
403 self.assertRaises(TypeError, cf.get, 'non-string', 'int')
404 self.assertEqual(cf.get('non-string', 'list', raw=True),
405 [0, 1, 1, 2, 3, 5, 8, 13, '%('])
406 self.assertRaises(TypeError, cf.get, 'non-string', 'list')
407 self.assertEqual(cf.get('non-string', 'dict', raw=True),
408 {'pi': 3.14159, '%(': 1, '%(list)': '%(list)'})
409 self.assertRaises(TypeError, cf.get, 'non-string', 'dict')
410 self.assertEqual(cf.get('non-string', 'string_with_interpolation',
411 raw=True), '%(list)s')
412 self.assertRaises(ValueError, cf.get, 'non-string',
413 'string_with_interpolation', raw=False)
414
Fred Drake8ef67672000-09-27 22:45:25 +0000415
Fred Drakec6f28912002-10-25 19:40:49 +0000416class RawConfigParserTestCase(TestCaseBase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000417 config_class = configparser.RawConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000418
419 def test_interpolation(self):
420 cf = self.get_interpolation_config()
421 eq = self.assertEqual
422 eq(cf.get("Foo", "getname"), "%(__name__)s")
423 eq(cf.get("Foo", "bar"),
424 "something %(with1)s interpolation (1 step)")
425 eq(cf.get("Foo", "bar9"),
426 "something %(with9)s lots of interpolation (9 steps)")
427 eq(cf.get("Foo", "bar10"),
428 "something %(with10)s lots of interpolation (10 steps)")
429 eq(cf.get("Foo", "bar11"),
430 "something %(with11)s lots of interpolation (11 steps)")
Fred Drake95b96d32001-02-12 17:23:20 +0000431
Fred Drake98e3b292002-10-25 20:42:44 +0000432 def test_items(self):
433 self.check_items_config([('default', '<default>'),
434 ('getdefault', '|%(default)s|'),
435 ('getname', '|%(__name__)s|'),
436 ('key', '|%(name)s|'),
437 ('name', 'value')])
438
David Goodger1cbf2062004-10-03 15:55:09 +0000439 def test_set_nonstring_types(self):
440 cf = self.newconfig()
441 cf.add_section('non-string')
442 cf.set('non-string', 'int', 1)
443 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13])
444 cf.set('non-string', 'dict', {'pi': 3.14159})
445 self.assertEqual(cf.get('non-string', 'int'), 1)
446 self.assertEqual(cf.get('non-string', 'list'),
447 [0, 1, 1, 2, 3, 5, 8, 13])
448 self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159})
Tim Petersab9b32c2004-10-03 18:35:19 +0000449
Fred Drake8ef67672000-09-27 22:45:25 +0000450
Fred Drake0eebd5c2002-10-25 21:52:00 +0000451class SafeConfigParserTestCase(ConfigParserTestCase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000452 config_class = configparser.SafeConfigParser
Fred Drake0eebd5c2002-10-25 21:52:00 +0000453
454 def test_safe_interpolation(self):
455 # See http://www.python.org/sf/511737
456 cf = self.fromstring("[section]\n"
457 "option1=xxx\n"
458 "option2=%(option1)s/xxx\n"
459 "ok=%(option1)s/%%s\n"
460 "not_ok=%(option2)s/%%s")
461 self.assertEqual(cf.get("section", "ok"), "xxx/%s")
462 self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s")
463
Guido van Rossumd8faa362007-04-27 19:54:29 +0000464 def test_set_malformatted_interpolation(self):
465 cf = self.fromstring("[sect]\n"
466 "option1=foo\n")
467
468 self.assertEqual(cf.get('sect', "option1"), "foo")
469
470 self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo")
471 self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%")
472 self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo")
473
474 self.assertEqual(cf.get('sect', "option1"), "foo")
475
Georg Brandl1f9fa312009-04-27 16:42:58 +0000476 # bug #5741: double percents are *not* malformed
477 cf.set("sect", "option2", "foo%%bar")
478 self.assertEqual(cf.get("sect", "option2"), "foo%bar")
479
David Goodger1cbf2062004-10-03 15:55:09 +0000480 def test_set_nonstring_types(self):
481 cf = self.fromstring("[sect]\n"
482 "option1=foo\n")
483 # Check that we get a TypeError when setting non-string values
484 # in an existing section:
485 self.assertRaises(TypeError, cf.set, "sect", "option1", 1)
486 self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0)
487 self.assertRaises(TypeError, cf.set, "sect", "option1", object())
488 self.assertRaises(TypeError, cf.set, "sect", "option2", 1)
489 self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
490 self.assertRaises(TypeError, cf.set, "sect", "option2", object())
491
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000492 def test_add_section_default_1(self):
493 cf = self.newconfig()
494 self.assertRaises(ValueError, cf.add_section, "default")
495
496 def test_add_section_default_2(self):
497 cf = self.newconfig()
498 self.assertRaises(ValueError, cf.add_section, "DEFAULT")
499
Fred Drake03c44a32010-02-19 06:08:41 +0000500
501class SafeConfigParserTestCaseNoValue(SafeConfigParserTestCase):
502 allow_no_value = True
503
504
Thomas Wouters89f507f2006-12-13 04:49:30 +0000505class SortedTestCase(RawConfigParserTestCase):
506 def newconfig(self, defaults=None):
507 self.cf = self.config_class(defaults=defaults, dict_type=SortedDict)
508 return self.cf
509
510 def test_sorted(self):
511 self.fromstring("[b]\n"
512 "o4=1\n"
513 "o3=2\n"
514 "o2=3\n"
515 "o1=4\n"
516 "[a]\n"
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000517 "k=v\n")
Guido van Rossum34d19282007-08-09 01:03:29 +0000518 output = io.StringIO()
Thomas Wouters89f507f2006-12-13 04:49:30 +0000519 self.cf.write(output)
520 self.assertEquals(output.getvalue(),
521 "[a]\n"
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000522 "k = v\n\n"
Thomas Wouters89f507f2006-12-13 04:49:30 +0000523 "[b]\n"
524 "o1 = 4\n"
525 "o2 = 3\n"
526 "o3 = 2\n"
527 "o4 = 1\n\n")
Fred Drake0eebd5c2002-10-25 21:52:00 +0000528
Fred Drake03c44a32010-02-19 06:08:41 +0000529
Fred Drakec6f28912002-10-25 19:40:49 +0000530def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000531 support.run_unittest(
Walter Dörwald21d3a322003-05-01 17:45:56 +0000532 ConfigParserTestCase,
533 RawConfigParserTestCase,
Thomas Wouters89f507f2006-12-13 04:49:30 +0000534 SafeConfigParserTestCase,
Fred Drake03c44a32010-02-19 06:08:41 +0000535 SortedTestCase,
536 SafeConfigParserTestCaseNoValue,
537 )
538
Fred Drake3af0eb82002-10-25 18:09:24 +0000539
Fred Drakec6f28912002-10-25 19:40:49 +0000540if __name__ == "__main__":
541 test_main()