blob: 6acab6bb211259e7f5d348dccf30b59dce1ee9c8 [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
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000110 self.assertRaises(configparser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000111 cf.remove_option, 'No Such Section', 'foo')
112
113 eq(cf.get('Long Line', 'foo'),
Andrew M. Kuchling1bf71172002-03-08 18:10:12 +0000114 'this line is much, much longer than my editor\nlikes it.')
Fred Drake3d5f7e82000-12-04 16:30:40 +0000115
Fred Drakec6f28912002-10-25 19:40:49 +0000116 def test_case_sensitivity(self):
117 cf = self.newconfig()
118 cf.add_section("A")
119 cf.add_section("a")
120 L = cf.sections()
121 L.sort()
122 eq = self.assertEqual
123 eq(L, ["A", "a"])
124 cf.set("a", "B", "value")
125 eq(cf.options("a"), ["b"])
126 eq(cf.get("a", "b"), "value",
Fred Drake3c823aa2001-02-26 21:55:34 +0000127 "could not locate option, expecting case-insensitive option names")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000128 self.assertTrue(cf.has_option("a", "b"))
Fred Drakec6f28912002-10-25 19:40:49 +0000129 cf.set("A", "A-B", "A-B value")
130 for opt in ("a-b", "A-b", "a-B", "A-B"):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000131 self.assertTrue(
Fred Drakec6f28912002-10-25 19:40:49 +0000132 cf.has_option("A", opt),
133 "has_option() returned false for option which should exist")
134 eq(cf.options("A"), ["a-b"])
135 eq(cf.options("a"), ["b"])
136 cf.remove_option("a", "B")
137 eq(cf.options("a"), [])
Fred Drake3c823aa2001-02-26 21:55:34 +0000138
Fred Drakec6f28912002-10-25 19:40:49 +0000139 # SF bug #432369:
140 cf = self.fromstring(
141 "[MySection]\nOption: first line\n\tsecond line\n")
142 eq(cf.options("MySection"), ["option"])
143 eq(cf.get("MySection", "Option"), "first line\nsecond line")
Fred Drakebeb67132001-07-06 17:22:48 +0000144
Fred Drakec6f28912002-10-25 19:40:49 +0000145 # SF bug #561822:
146 cf = self.fromstring("[section]\nnekey=nevalue\n",
147 defaults={"key":"value"})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000148 self.assertTrue(cf.has_option("section", "Key"))
Fred Drake309db062002-09-27 15:35:23 +0000149
Fred Drake3c823aa2001-02-26 21:55:34 +0000150
David Goodger68a1abd2004-10-03 15:40:25 +0000151 def test_default_case_sensitivity(self):
152 cf = self.newconfig({"foo": "Bar"})
153 self.assertEqual(
154 cf.get("DEFAULT", "Foo"), "Bar",
155 "could not locate option, expecting case-insensitive option names")
156 cf = self.newconfig({"Foo": "Bar"})
157 self.assertEqual(
158 cf.get("DEFAULT", "Foo"), "Bar",
159 "could not locate option, expecting case-insensitive defaults")
160
Fred Drakec6f28912002-10-25 19:40:49 +0000161 def test_parse_errors(self):
162 self.newconfig()
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000163 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000164 "[Foo]\n extra-spaces: splat\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000165 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000166 "[Foo]\n extra-spaces= splat\n")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000167 self.parse_error(configparser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000168 "[Foo]\n:value-without-option-name\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.MissingSectionHeaderError,
Fred Drakec6f28912002-10-25 19:40:49 +0000172 "No Section!\n")
Fred Drake168bead2001-10-08 17:13:12 +0000173
Fred Drakec6f28912002-10-25 19:40:49 +0000174 def parse_error(self, exc, src):
Guido van Rossum34d19282007-08-09 01:03:29 +0000175 sio = io.StringIO(src)
Fred Drakec6f28912002-10-25 19:40:49 +0000176 self.assertRaises(exc, self.cf.readfp, sio)
Fred Drake168bead2001-10-08 17:13:12 +0000177
Fred Drakec6f28912002-10-25 19:40:49 +0000178 def test_query_errors(self):
179 cf = self.newconfig()
180 self.assertEqual(cf.sections(), [],
181 "new ConfigParser should have no defined sections")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000182 self.assertFalse(cf.has_section("Foo"),
Fred Drakec6f28912002-10-25 19:40:49 +0000183 "new ConfigParser should have no acknowledged sections")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000184 self.assertRaises(configparser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000185 cf.options, "Foo")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000186 self.assertRaises(configparser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000187 cf.set, "foo", "bar", "value")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000188 self.get_error(configparser.NoSectionError, "foo", "bar")
Fred Drakec6f28912002-10-25 19:40:49 +0000189 cf.add_section("foo")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000190 self.get_error(configparser.NoOptionError, "foo", "bar")
Fred Drake8ef67672000-09-27 22:45:25 +0000191
Fred Drakec6f28912002-10-25 19:40:49 +0000192 def get_error(self, exc, section, option):
Fred Drake54782192002-12-31 06:57:25 +0000193 try:
194 self.cf.get(section, option)
Guido van Rossumb940e112007-01-10 16:19:56 +0000195 except exc as e:
Fred Drake54782192002-12-31 06:57:25 +0000196 return e
197 else:
198 self.fail("expected exception type %s.%s"
199 % (exc.__module__, exc.__name__))
Fred Drake3af0eb82002-10-25 18:09:24 +0000200
Fred Drakec6f28912002-10-25 19:40:49 +0000201 def test_boolean(self):
202 cf = self.fromstring(
203 "[BOOLTEST]\n"
204 "T1=1\n"
205 "T2=TRUE\n"
206 "T3=True\n"
207 "T4=oN\n"
208 "T5=yes\n"
209 "F1=0\n"
210 "F2=FALSE\n"
211 "F3=False\n"
212 "F4=oFF\n"
213 "F5=nO\n"
214 "E1=2\n"
215 "E2=foo\n"
216 "E3=-1\n"
217 "E4=0.1\n"
218 "E5=FALSE AND MORE"
219 )
220 for x in range(1, 5):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000221 self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x))
222 self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x))
Fred Drakec6f28912002-10-25 19:40:49 +0000223 self.assertRaises(ValueError,
224 cf.getboolean, 'BOOLTEST', 'e%d' % x)
Fred Drake95b96d32001-02-12 17:23:20 +0000225
Fred Drakec6f28912002-10-25 19:40:49 +0000226 def test_weird_errors(self):
227 cf = self.newconfig()
Fred Drake8ef67672000-09-27 22:45:25 +0000228 cf.add_section("Foo")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000229 self.assertRaises(configparser.DuplicateSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000230 cf.add_section, "Foo")
231
232 def test_write(self):
Fred Drake03c44a32010-02-19 06:08:41 +0000233 config_string = (
Fred Drakec6f28912002-10-25 19:40:49 +0000234 "[Long Line]\n"
235 "foo: this line is much, much longer than my editor\n"
236 " likes it.\n"
237 "[DEFAULT]\n"
238 "foo: another very\n"
Fred Drake03c44a32010-02-19 06:08:41 +0000239 " long line\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000240 )
Fred Drake03c44a32010-02-19 06:08:41 +0000241 if self.allow_no_value:
242 config_string += (
243 "[Valueless]\n"
244 "option-without-value\n"
245 )
246
247 cf = self.fromstring(config_string)
Guido van Rossum34d19282007-08-09 01:03:29 +0000248 output = io.StringIO()
Fred Drakec6f28912002-10-25 19:40:49 +0000249 cf.write(output)
Fred Drake03c44a32010-02-19 06:08:41 +0000250 expect_string = (
Fred Drakec6f28912002-10-25 19:40:49 +0000251 "[DEFAULT]\n"
252 "foo = another very\n"
253 "\tlong line\n"
254 "\n"
255 "[Long Line]\n"
256 "foo = this line is much, much longer than my editor\n"
257 "\tlikes it.\n"
258 "\n"
259 )
Fred Drake03c44a32010-02-19 06:08:41 +0000260 if self.allow_no_value:
261 expect_string += (
262 "[Valueless]\n"
263 "option-without-value\n"
264 "\n"
265 )
266 self.assertEqual(output.getvalue(), expect_string)
Fred Drakec6f28912002-10-25 19:40:49 +0000267
Fred Drakeabc086f2004-05-18 03:29:52 +0000268 def test_set_string_types(self):
269 cf = self.fromstring("[sect]\n"
270 "option1=foo\n")
271 # Check that we don't get an exception when setting values in
272 # an existing section using strings:
273 class mystr(str):
274 pass
275 cf.set("sect", "option1", "splat")
276 cf.set("sect", "option1", mystr("splat"))
277 cf.set("sect", "option2", "splat")
278 cf.set("sect", "option2", mystr("splat"))
Walter Dörwald5de48bd2007-06-11 21:38:39 +0000279 cf.set("sect", "option1", "splat")
280 cf.set("sect", "option2", "splat")
Fred Drakeabc086f2004-05-18 03:29:52 +0000281
Fred Drake82903142004-05-18 04:24:02 +0000282 def test_read_returns_file_list(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000283 file1 = support.findfile("cfgparser.1")
Fred Drake82903142004-05-18 04:24:02 +0000284 # check when we pass a mix of readable and non-readable files:
285 cf = self.newconfig()
Mark Dickinson934896d2009-02-21 20:59:32 +0000286 parsed_files = cf.read([file1, "nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000287 self.assertEqual(parsed_files, [file1])
288 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
289 # check when we pass only a filename:
290 cf = self.newconfig()
291 parsed_files = cf.read(file1)
292 self.assertEqual(parsed_files, [file1])
293 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
294 # check when we pass only missing files:
295 cf = self.newconfig()
Mark Dickinson934896d2009-02-21 20:59:32 +0000296 parsed_files = cf.read(["nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000297 self.assertEqual(parsed_files, [])
298 # check when we pass no files:
299 cf = self.newconfig()
300 parsed_files = cf.read([])
301 self.assertEqual(parsed_files, [])
302
Fred Drakec6f28912002-10-25 19:40:49 +0000303 # shared by subclasses
304 def get_interpolation_config(self):
305 return self.fromstring(
306 "[Foo]\n"
307 "bar=something %(with1)s interpolation (1 step)\n"
308 "bar9=something %(with9)s lots of interpolation (9 steps)\n"
309 "bar10=something %(with10)s lots of interpolation (10 steps)\n"
310 "bar11=something %(with11)s lots of interpolation (11 steps)\n"
311 "with11=%(with10)s\n"
312 "with10=%(with9)s\n"
313 "with9=%(with8)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000314 "with8=%(With7)s\n"
315 "with7=%(WITH6)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000316 "with6=%(with5)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000317 "With5=%(with4)s\n"
318 "WITH4=%(with3)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000319 "with3=%(with2)s\n"
320 "with2=%(with1)s\n"
321 "with1=with\n"
322 "\n"
323 "[Mutual Recursion]\n"
324 "foo=%(bar)s\n"
Fred Drake54782192002-12-31 06:57:25 +0000325 "bar=%(foo)s\n"
326 "\n"
327 "[Interpolation Error]\n"
328 "name=%(reference)s\n",
329 # no definition for 'reference'
Fred Drakec6f28912002-10-25 19:40:49 +0000330 defaults={"getname": "%(__name__)s"})
Fred Drake95b96d32001-02-12 17:23:20 +0000331
Fred Drake98e3b292002-10-25 20:42:44 +0000332 def check_items_config(self, expected):
333 cf = self.fromstring(
334 "[section]\n"
335 "name = value\n"
336 "key: |%(name)s| \n"
337 "getdefault: |%(default)s|\n"
338 "getname: |%(__name__)s|",
339 defaults={"default": "<default>"})
340 L = list(cf.items("section"))
341 L.sort()
342 self.assertEqual(L, expected)
343
Fred Drake8ef67672000-09-27 22:45:25 +0000344
Fred Drakec6f28912002-10-25 19:40:49 +0000345class ConfigParserTestCase(TestCaseBase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000346 config_class = configparser.ConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000347
348 def test_interpolation(self):
349 cf = self.get_interpolation_config()
350 eq = self.assertEqual
351 eq(cf.get("Foo", "getname"), "Foo")
352 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
353 eq(cf.get("Foo", "bar9"),
354 "something with lots of interpolation (9 steps)")
355 eq(cf.get("Foo", "bar10"),
356 "something with lots of interpolation (10 steps)")
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000357 self.get_error(configparser.InterpolationDepthError, "Foo", "bar11")
Fred Drake95b96d32001-02-12 17:23:20 +0000358
Fred Drake54782192002-12-31 06:57:25 +0000359 def test_interpolation_missing_value(self):
Fred Drake03c44a32010-02-19 06:08:41 +0000360 self.get_interpolation_config()
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000361 e = self.get_error(configparser.InterpolationError,
Fred Drake54782192002-12-31 06:57:25 +0000362 "Interpolation Error", "name")
363 self.assertEqual(e.reference, "reference")
364 self.assertEqual(e.section, "Interpolation Error")
365 self.assertEqual(e.option, "name")
366
Fred Drake98e3b292002-10-25 20:42:44 +0000367 def test_items(self):
368 self.check_items_config([('default', '<default>'),
369 ('getdefault', '|<default>|'),
370 ('getname', '|section|'),
371 ('key', '|value|'),
372 ('name', 'value')])
373
David Goodger1cbf2062004-10-03 15:55:09 +0000374 def test_set_nonstring_types(self):
375 cf = self.newconfig()
376 cf.add_section('non-string')
377 cf.set('non-string', 'int', 1)
378 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%('])
379 cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1,
380 '%(list)': '%(list)'})
381 cf.set('non-string', 'string_with_interpolation', '%(list)s')
382 self.assertEqual(cf.get('non-string', 'int', raw=True), 1)
383 self.assertRaises(TypeError, cf.get, 'non-string', 'int')
384 self.assertEqual(cf.get('non-string', 'list', raw=True),
385 [0, 1, 1, 2, 3, 5, 8, 13, '%('])
386 self.assertRaises(TypeError, cf.get, 'non-string', 'list')
387 self.assertEqual(cf.get('non-string', 'dict', raw=True),
388 {'pi': 3.14159, '%(': 1, '%(list)': '%(list)'})
389 self.assertRaises(TypeError, cf.get, 'non-string', 'dict')
390 self.assertEqual(cf.get('non-string', 'string_with_interpolation',
391 raw=True), '%(list)s')
392 self.assertRaises(ValueError, cf.get, 'non-string',
393 'string_with_interpolation', raw=False)
394
Fred Drake8ef67672000-09-27 22:45:25 +0000395
Fred Drakec6f28912002-10-25 19:40:49 +0000396class RawConfigParserTestCase(TestCaseBase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000397 config_class = configparser.RawConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000398
399 def test_interpolation(self):
400 cf = self.get_interpolation_config()
401 eq = self.assertEqual
402 eq(cf.get("Foo", "getname"), "%(__name__)s")
403 eq(cf.get("Foo", "bar"),
404 "something %(with1)s interpolation (1 step)")
405 eq(cf.get("Foo", "bar9"),
406 "something %(with9)s lots of interpolation (9 steps)")
407 eq(cf.get("Foo", "bar10"),
408 "something %(with10)s lots of interpolation (10 steps)")
409 eq(cf.get("Foo", "bar11"),
410 "something %(with11)s lots of interpolation (11 steps)")
Fred Drake95b96d32001-02-12 17:23:20 +0000411
Fred Drake98e3b292002-10-25 20:42:44 +0000412 def test_items(self):
413 self.check_items_config([('default', '<default>'),
414 ('getdefault', '|%(default)s|'),
415 ('getname', '|%(__name__)s|'),
416 ('key', '|%(name)s|'),
417 ('name', 'value')])
418
David Goodger1cbf2062004-10-03 15:55:09 +0000419 def test_set_nonstring_types(self):
420 cf = self.newconfig()
421 cf.add_section('non-string')
422 cf.set('non-string', 'int', 1)
423 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13])
424 cf.set('non-string', 'dict', {'pi': 3.14159})
425 self.assertEqual(cf.get('non-string', 'int'), 1)
426 self.assertEqual(cf.get('non-string', 'list'),
427 [0, 1, 1, 2, 3, 5, 8, 13])
428 self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159})
Tim Petersab9b32c2004-10-03 18:35:19 +0000429
Fred Drake8ef67672000-09-27 22:45:25 +0000430
Fred Drake0eebd5c2002-10-25 21:52:00 +0000431class SafeConfigParserTestCase(ConfigParserTestCase):
Alexandre Vassalotti1d1eaa42008-05-14 22:59:42 +0000432 config_class = configparser.SafeConfigParser
Fred Drake0eebd5c2002-10-25 21:52:00 +0000433
434 def test_safe_interpolation(self):
435 # See http://www.python.org/sf/511737
436 cf = self.fromstring("[section]\n"
437 "option1=xxx\n"
438 "option2=%(option1)s/xxx\n"
439 "ok=%(option1)s/%%s\n"
440 "not_ok=%(option2)s/%%s")
441 self.assertEqual(cf.get("section", "ok"), "xxx/%s")
442 self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s")
443
Guido van Rossumd8faa362007-04-27 19:54:29 +0000444 def test_set_malformatted_interpolation(self):
445 cf = self.fromstring("[sect]\n"
446 "option1=foo\n")
447
448 self.assertEqual(cf.get('sect', "option1"), "foo")
449
450 self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo")
451 self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%")
452 self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo")
453
454 self.assertEqual(cf.get('sect', "option1"), "foo")
455
Georg Brandl1f9fa312009-04-27 16:42:58 +0000456 # bug #5741: double percents are *not* malformed
457 cf.set("sect", "option2", "foo%%bar")
458 self.assertEqual(cf.get("sect", "option2"), "foo%bar")
459
David Goodger1cbf2062004-10-03 15:55:09 +0000460 def test_set_nonstring_types(self):
461 cf = self.fromstring("[sect]\n"
462 "option1=foo\n")
463 # Check that we get a TypeError when setting non-string values
464 # in an existing section:
465 self.assertRaises(TypeError, cf.set, "sect", "option1", 1)
466 self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0)
467 self.assertRaises(TypeError, cf.set, "sect", "option1", object())
468 self.assertRaises(TypeError, cf.set, "sect", "option2", 1)
469 self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
470 self.assertRaises(TypeError, cf.set, "sect", "option2", object())
471
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000472 def test_add_section_default_1(self):
473 cf = self.newconfig()
474 self.assertRaises(ValueError, cf.add_section, "default")
475
476 def test_add_section_default_2(self):
477 cf = self.newconfig()
478 self.assertRaises(ValueError, cf.add_section, "DEFAULT")
479
Fred Drake03c44a32010-02-19 06:08:41 +0000480
481class SafeConfigParserTestCaseNoValue(SafeConfigParserTestCase):
482 allow_no_value = True
483
484
Thomas Wouters89f507f2006-12-13 04:49:30 +0000485class SortedTestCase(RawConfigParserTestCase):
486 def newconfig(self, defaults=None):
487 self.cf = self.config_class(defaults=defaults, dict_type=SortedDict)
488 return self.cf
489
490 def test_sorted(self):
491 self.fromstring("[b]\n"
492 "o4=1\n"
493 "o3=2\n"
494 "o2=3\n"
495 "o1=4\n"
496 "[a]\n"
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000497 "k=v\n")
Guido van Rossum34d19282007-08-09 01:03:29 +0000498 output = io.StringIO()
Thomas Wouters89f507f2006-12-13 04:49:30 +0000499 self.cf.write(output)
500 self.assertEquals(output.getvalue(),
501 "[a]\n"
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000502 "k = v\n\n"
Thomas Wouters89f507f2006-12-13 04:49:30 +0000503 "[b]\n"
504 "o1 = 4\n"
505 "o2 = 3\n"
506 "o3 = 2\n"
507 "o4 = 1\n\n")
Fred Drake0eebd5c2002-10-25 21:52:00 +0000508
Fred Drake03c44a32010-02-19 06:08:41 +0000509
Fred Drakec6f28912002-10-25 19:40:49 +0000510def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000511 support.run_unittest(
Walter Dörwald21d3a322003-05-01 17:45:56 +0000512 ConfigParserTestCase,
513 RawConfigParserTestCase,
Thomas Wouters89f507f2006-12-13 04:49:30 +0000514 SafeConfigParserTestCase,
Fred Drake03c44a32010-02-19 06:08:41 +0000515 SortedTestCase,
516 SafeConfigParserTestCaseNoValue,
517 )
518
Fred Drake3af0eb82002-10-25 18:09:24 +0000519
Fred Drakec6f28912002-10-25 19:40:49 +0000520if __name__ == "__main__":
521 test_main()