blob: 22a314d779bf82d9580d4db13461b6a59a3664a9 [file] [log] [blame]
Georg Brandl392c6fc2008-05-25 07:25:25 +00001import ConfigParser
Fred Drake8ef67672000-09-27 22:45:25 +00002import StringIO
Brian Curtine4334b42010-07-26 02:30:15 +00003import os
Fred Drakec6f28912002-10-25 19:40:49 +00004import unittest
Martin v. Löwisa00bcac2006-12-03 12:01:53 +00005import UserDict
Fred Drake8ef67672000-09-27 22:45:25 +00006
Fred Drakec6f28912002-10-25 19:40:49 +00007from test import test_support
Fred Drake3d5f7e82000-12-04 16:30:40 +00008
Fred Drakecc43b562010-02-19 05:24:30 +00009
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000010class SortedDict(UserDict.UserDict):
11 def items(self):
12 result = self.data.items()
13 result.sort()
14 return result
15
16 def keys(self):
17 result = self.data.keys()
18 result.sort()
19 return result
Tim Petersf733abb2007-01-30 03:03:46 +000020
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000021 def values(self):
Georg Brandlcd4a21b2010-02-06 23:34:10 +000022 # XXX never used?
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000023 result = self.items()
Georg Brandlcd4a21b2010-02-06 23:34:10 +000024 return [i[1] for i in result]
Martin v. Löwisa00bcac2006-12-03 12:01:53 +000025
26 def iteritems(self): return iter(self.items())
27 def iterkeys(self): return iter(self.keys())
28 __iter__ = iterkeys
29 def itervalues(self): return iter(self.values())
Fred Drake3d5f7e82000-12-04 16:30:40 +000030
Fred Drakecc43b562010-02-19 05:24:30 +000031
Fred Drakec6f28912002-10-25 19:40:49 +000032class TestCaseBase(unittest.TestCase):
Fred Drakecc43b562010-02-19 05:24:30 +000033 allow_no_value = False
34
Fred Drakec6f28912002-10-25 19:40:49 +000035 def newconfig(self, defaults=None):
36 if defaults is None:
Fred Drakecc43b562010-02-19 05:24:30 +000037 self.cf = self.config_class(allow_no_value=self.allow_no_value)
Fred Drakec6f28912002-10-25 19:40:49 +000038 else:
Fred Drakecc43b562010-02-19 05:24:30 +000039 self.cf = self.config_class(defaults,
40 allow_no_value=self.allow_no_value)
Fred Drakec6f28912002-10-25 19:40:49 +000041 return self.cf
Fred Drake8ef67672000-09-27 22:45:25 +000042
Fred Drakec6f28912002-10-25 19:40:49 +000043 def fromstring(self, string, defaults=None):
44 cf = self.newconfig(defaults)
45 sio = StringIO.StringIO(string)
46 cf.readfp(sio)
47 return cf
Fred Drake8ef67672000-09-27 22:45:25 +000048
Fred Drakec6f28912002-10-25 19:40:49 +000049 def test_basic(self):
Fred Drakecc43b562010-02-19 05:24:30 +000050 config_string = (
Fred Drakec6f28912002-10-25 19:40:49 +000051 "[Foo Bar]\n"
52 "foo=bar\n"
53 "[Spacey Bar]\n"
54 "foo = bar\n"
55 "[Commented Bar]\n"
56 "foo: bar ; comment\n"
57 "[Long Line]\n"
58 "foo: this line is much, much longer than my editor\n"
59 " likes it.\n"
60 "[Section\\with$weird%characters[\t]\n"
61 "[Internationalized Stuff]\n"
62 "foo[bg]: Bulgarian\n"
63 "foo=Default\n"
64 "foo[en]=English\n"
65 "foo[de]=Deutsch\n"
66 "[Spaces]\n"
67 "key with spaces : value\n"
68 "another with spaces = splat!\n"
69 )
Fred Drakecc43b562010-02-19 05:24:30 +000070 if self.allow_no_value:
71 config_string += (
72 "[NoValue]\n"
73 "option-without-value\n"
74 )
75
76 cf = self.fromstring(config_string)
Fred Drakec6f28912002-10-25 19:40:49 +000077 L = cf.sections()
78 L.sort()
Fred Drakecc43b562010-02-19 05:24:30 +000079 E = [r'Commented Bar',
80 r'Foo Bar',
81 r'Internationalized Stuff',
82 r'Long Line',
83 r'Section\with$weird%characters[' '\t',
84 r'Spaces',
85 r'Spacey Bar',
86 ]
87 if self.allow_no_value:
88 E.append(r'NoValue')
89 E.sort()
Fred Drakec6f28912002-10-25 19:40:49 +000090 eq = self.assertEqual
Fred Drakecc43b562010-02-19 05:24:30 +000091 eq(L, E)
Fred Drake8ef67672000-09-27 22:45:25 +000092
Fred Drakec6f28912002-10-25 19:40:49 +000093 # The use of spaces in the section names serves as a
94 # regression test for SourceForge bug #583248:
95 # http://www.python.org/sf/583248
96 eq(cf.get('Foo Bar', 'foo'), 'bar')
97 eq(cf.get('Spacey Bar', 'foo'), 'bar')
98 eq(cf.get('Commented Bar', 'foo'), 'bar')
99 eq(cf.get('Spaces', 'key with spaces'), 'value')
100 eq(cf.get('Spaces', 'another with spaces'), 'splat!')
Fred Drakecc43b562010-02-19 05:24:30 +0000101 if self.allow_no_value:
102 eq(cf.get('NoValue', 'option-without-value'), None)
Fred Drake3d5f7e82000-12-04 16:30:40 +0000103
Ezio Melottiaa980582010-01-23 23:04:36 +0000104 self.assertNotIn('__name__', cf.options("Foo Bar"),
105 '__name__ "option" should not be exposed by the API!')
Fred Drakec6f28912002-10-25 19:40:49 +0000106
107 # Make sure the right things happen for remove_option();
108 # added to include check for SourceForge bug #123324:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000109 self.assertTrue(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000110 "remove_option() failed to report existence of option")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000111 self.assertFalse(cf.has_option('Foo Bar', 'foo'),
Fred Drakec6f28912002-10-25 19:40:49 +0000112 "remove_option() failed to remove option")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000113 self.assertFalse(cf.remove_option('Foo Bar', 'foo'),
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000114 "remove_option() failed to report non-existence of option"
Fred Drakec6f28912002-10-25 19:40:49 +0000115 " that was removed")
116
Georg Brandl392c6fc2008-05-25 07:25:25 +0000117 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000118 cf.remove_option, 'No Such Section', 'foo')
119
120 eq(cf.get('Long Line', 'foo'),
Andrew M. Kuchling1bf71172002-03-08 18:10:12 +0000121 'this line is much, much longer than my editor\nlikes it.')
Fred Drake3d5f7e82000-12-04 16:30:40 +0000122
Fred Drakec6f28912002-10-25 19:40:49 +0000123 def test_case_sensitivity(self):
124 cf = self.newconfig()
125 cf.add_section("A")
126 cf.add_section("a")
127 L = cf.sections()
128 L.sort()
129 eq = self.assertEqual
130 eq(L, ["A", "a"])
131 cf.set("a", "B", "value")
132 eq(cf.options("a"), ["b"])
133 eq(cf.get("a", "b"), "value",
Fred Drake3c823aa2001-02-26 21:55:34 +0000134 "could not locate option, expecting case-insensitive option names")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000135 self.assertTrue(cf.has_option("a", "b"))
Fred Drakec6f28912002-10-25 19:40:49 +0000136 cf.set("A", "A-B", "A-B value")
137 for opt in ("a-b", "A-b", "a-B", "A-B"):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000138 self.assertTrue(
Fred Drakec6f28912002-10-25 19:40:49 +0000139 cf.has_option("A", opt),
140 "has_option() returned false for option which should exist")
141 eq(cf.options("A"), ["a-b"])
142 eq(cf.options("a"), ["b"])
143 cf.remove_option("a", "B")
144 eq(cf.options("a"), [])
Fred Drake3c823aa2001-02-26 21:55:34 +0000145
Fred Drakec6f28912002-10-25 19:40:49 +0000146 # SF bug #432369:
147 cf = self.fromstring(
148 "[MySection]\nOption: first line\n\tsecond line\n")
149 eq(cf.options("MySection"), ["option"])
150 eq(cf.get("MySection", "Option"), "first line\nsecond line")
Fred Drakebeb67132001-07-06 17:22:48 +0000151
Fred Drakec6f28912002-10-25 19:40:49 +0000152 # SF bug #561822:
153 cf = self.fromstring("[section]\nnekey=nevalue\n",
154 defaults={"key":"value"})
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000155 self.assertTrue(cf.has_option("section", "Key"))
Fred Drake309db062002-09-27 15:35:23 +0000156
Fred Drake3c823aa2001-02-26 21:55:34 +0000157
David Goodger68a1abd2004-10-03 15:40:25 +0000158 def test_default_case_sensitivity(self):
159 cf = self.newconfig({"foo": "Bar"})
160 self.assertEqual(
161 cf.get("DEFAULT", "Foo"), "Bar",
162 "could not locate option, expecting case-insensitive option names")
163 cf = self.newconfig({"Foo": "Bar"})
164 self.assertEqual(
165 cf.get("DEFAULT", "Foo"), "Bar",
166 "could not locate option, expecting case-insensitive defaults")
167
Fred Drakec6f28912002-10-25 19:40:49 +0000168 def test_parse_errors(self):
169 self.newconfig()
Georg Brandl392c6fc2008-05-25 07:25:25 +0000170 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000171 "[Foo]\n extra-spaces: splat\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000172 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000173 "[Foo]\n extra-spaces= splat\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000174 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000175 "[Foo]\n:value-without-option-name\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000176 self.parse_error(ConfigParser.ParsingError,
Fred Drakec6f28912002-10-25 19:40:49 +0000177 "[Foo]\n=value-without-option-name\n")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000178 self.parse_error(ConfigParser.MissingSectionHeaderError,
Fred Drakec6f28912002-10-25 19:40:49 +0000179 "No Section!\n")
Fred Drake168bead2001-10-08 17:13:12 +0000180
Fred Drakec6f28912002-10-25 19:40:49 +0000181 def parse_error(self, exc, src):
182 sio = StringIO.StringIO(src)
183 self.assertRaises(exc, self.cf.readfp, sio)
Fred Drake168bead2001-10-08 17:13:12 +0000184
Fred Drakec6f28912002-10-25 19:40:49 +0000185 def test_query_errors(self):
186 cf = self.newconfig()
187 self.assertEqual(cf.sections(), [],
188 "new ConfigParser should have no defined sections")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000189 self.assertFalse(cf.has_section("Foo"),
Brian Curtine4334b42010-07-26 02:30:15 +0000190 "new ConfigParser should have no acknowledged "
191 "sections")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000192 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000193 cf.options, "Foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000194 self.assertRaises(ConfigParser.NoSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000195 cf.set, "foo", "bar", "value")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000196 self.get_error(ConfigParser.NoSectionError, "foo", "bar")
Fred Drakec6f28912002-10-25 19:40:49 +0000197 cf.add_section("foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000198 self.get_error(ConfigParser.NoOptionError, "foo", "bar")
Fred Drake8ef67672000-09-27 22:45:25 +0000199
Fred Drakec6f28912002-10-25 19:40:49 +0000200 def get_error(self, exc, section, option):
Fred Drake54782192002-12-31 06:57:25 +0000201 try:
202 self.cf.get(section, option)
203 except exc, e:
204 return e
205 else:
206 self.fail("expected exception type %s.%s"
207 % (exc.__module__, exc.__name__))
Fred Drake3af0eb82002-10-25 18:09:24 +0000208
Fred Drakec6f28912002-10-25 19:40:49 +0000209 def test_boolean(self):
210 cf = self.fromstring(
211 "[BOOLTEST]\n"
212 "T1=1\n"
213 "T2=TRUE\n"
214 "T3=True\n"
215 "T4=oN\n"
216 "T5=yes\n"
217 "F1=0\n"
218 "F2=FALSE\n"
219 "F3=False\n"
220 "F4=oFF\n"
221 "F5=nO\n"
222 "E1=2\n"
223 "E2=foo\n"
224 "E3=-1\n"
225 "E4=0.1\n"
226 "E5=FALSE AND MORE"
227 )
228 for x in range(1, 5):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000229 self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x))
230 self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x))
Fred Drakec6f28912002-10-25 19:40:49 +0000231 self.assertRaises(ValueError,
232 cf.getboolean, 'BOOLTEST', 'e%d' % x)
Fred Drake95b96d32001-02-12 17:23:20 +0000233
Fred Drakec6f28912002-10-25 19:40:49 +0000234 def test_weird_errors(self):
235 cf = self.newconfig()
Fred Drake8ef67672000-09-27 22:45:25 +0000236 cf.add_section("Foo")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000237 self.assertRaises(ConfigParser.DuplicateSectionError,
Fred Drakec6f28912002-10-25 19:40:49 +0000238 cf.add_section, "Foo")
239
240 def test_write(self):
Fred Drakecc43b562010-02-19 05:24:30 +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 Drakecc43b562010-02-19 05:24:30 +0000247 " long line\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000248 )
Fred Drakecc43b562010-02-19 05:24:30 +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)
Fred Drakec6f28912002-10-25 19:40:49 +0000256 output = StringIO.StringIO()
257 cf.write(output)
Fred Drakecc43b562010-02-19 05:24:30 +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 Drakecc43b562010-02-19 05:24:30 +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"))
287 try:
288 unicode
289 except NameError:
290 pass
291 else:
292 cf.set("sect", "option1", unicode("splat"))
293 cf.set("sect", "option2", unicode("splat"))
294
Fred Drake82903142004-05-18 04:24:02 +0000295 def test_read_returns_file_list(self):
296 file1 = test_support.findfile("cfgparser.1")
297 # check when we pass a mix of readable and non-readable files:
298 cf = self.newconfig()
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000299 parsed_files = cf.read([file1, "nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000300 self.assertEqual(parsed_files, [file1])
301 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
302 # check when we pass only a filename:
303 cf = self.newconfig()
304 parsed_files = cf.read(file1)
305 self.assertEqual(parsed_files, [file1])
306 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
307 # check when we pass only missing files:
308 cf = self.newconfig()
Mark Dickinson3e4caeb2009-02-21 20:27:01 +0000309 parsed_files = cf.read(["nonexistent-file"])
Fred Drake82903142004-05-18 04:24:02 +0000310 self.assertEqual(parsed_files, [])
311 # check when we pass no files:
312 cf = self.newconfig()
313 parsed_files = cf.read([])
314 self.assertEqual(parsed_files, [])
315
Fred Drakec6f28912002-10-25 19:40:49 +0000316 # shared by subclasses
317 def get_interpolation_config(self):
318 return self.fromstring(
319 "[Foo]\n"
320 "bar=something %(with1)s interpolation (1 step)\n"
321 "bar9=something %(with9)s lots of interpolation (9 steps)\n"
322 "bar10=something %(with10)s lots of interpolation (10 steps)\n"
323 "bar11=something %(with11)s lots of interpolation (11 steps)\n"
324 "with11=%(with10)s\n"
325 "with10=%(with9)s\n"
326 "with9=%(with8)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000327 "with8=%(With7)s\n"
328 "with7=%(WITH6)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000329 "with6=%(with5)s\n"
Fred Drakebc12b012004-05-18 02:25:51 +0000330 "With5=%(with4)s\n"
331 "WITH4=%(with3)s\n"
Fred Drakec6f28912002-10-25 19:40:49 +0000332 "with3=%(with2)s\n"
333 "with2=%(with1)s\n"
334 "with1=with\n"
335 "\n"
336 "[Mutual Recursion]\n"
337 "foo=%(bar)s\n"
Fred Drake54782192002-12-31 06:57:25 +0000338 "bar=%(foo)s\n"
339 "\n"
340 "[Interpolation Error]\n"
341 "name=%(reference)s\n",
342 # no definition for 'reference'
Fred Drakec6f28912002-10-25 19:40:49 +0000343 defaults={"getname": "%(__name__)s"})
Fred Drake95b96d32001-02-12 17:23:20 +0000344
Fred Drake98e3b292002-10-25 20:42:44 +0000345 def check_items_config(self, expected):
346 cf = self.fromstring(
347 "[section]\n"
348 "name = value\n"
349 "key: |%(name)s| \n"
350 "getdefault: |%(default)s|\n"
351 "getname: |%(__name__)s|",
352 defaults={"default": "<default>"})
353 L = list(cf.items("section"))
354 L.sort()
355 self.assertEqual(L, expected)
356
Fred Drake8ef67672000-09-27 22:45:25 +0000357
Fred Drakec6f28912002-10-25 19:40:49 +0000358class ConfigParserTestCase(TestCaseBase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000359 config_class = ConfigParser.ConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000360
361 def test_interpolation(self):
Brian Curtine4334b42010-07-26 02:30:15 +0000362 rawval = {
363 ConfigParser.ConfigParser: ("something %(with11)s "
364 "lots of interpolation (11 steps)"),
365 ConfigParser.SafeConfigParser: "%(with1)s",
366 }
Fred Drakec6f28912002-10-25 19:40:49 +0000367 cf = self.get_interpolation_config()
368 eq = self.assertEqual
369 eq(cf.get("Foo", "getname"), "Foo")
370 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
371 eq(cf.get("Foo", "bar9"),
372 "something with lots of interpolation (9 steps)")
373 eq(cf.get("Foo", "bar10"),
374 "something with lots of interpolation (10 steps)")
Georg Brandl392c6fc2008-05-25 07:25:25 +0000375 self.get_error(ConfigParser.InterpolationDepthError, "Foo", "bar11")
Fred Drake95b96d32001-02-12 17:23:20 +0000376
Fred Drake54782192002-12-31 06:57:25 +0000377 def test_interpolation_missing_value(self):
Fred Drakecc43b562010-02-19 05:24:30 +0000378 self.get_interpolation_config()
Georg Brandl392c6fc2008-05-25 07:25:25 +0000379 e = self.get_error(ConfigParser.InterpolationError,
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")
384
Fred Drake98e3b292002-10-25 20:42:44 +0000385 def test_items(self):
386 self.check_items_config([('default', '<default>'),
387 ('getdefault', '|<default>|'),
388 ('getname', '|section|'),
389 ('key', '|value|'),
390 ('name', 'value')])
391
David Goodger1cbf2062004-10-03 15:55:09 +0000392 def test_set_nonstring_types(self):
393 cf = self.newconfig()
394 cf.add_section('non-string')
395 cf.set('non-string', 'int', 1)
396 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%('])
397 cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1,
398 '%(list)': '%(list)'})
399 cf.set('non-string', 'string_with_interpolation', '%(list)s')
400 self.assertEqual(cf.get('non-string', 'int', raw=True), 1)
401 self.assertRaises(TypeError, cf.get, 'non-string', 'int')
402 self.assertEqual(cf.get('non-string', 'list', raw=True),
403 [0, 1, 1, 2, 3, 5, 8, 13, '%('])
404 self.assertRaises(TypeError, cf.get, 'non-string', 'list')
405 self.assertEqual(cf.get('non-string', 'dict', raw=True),
406 {'pi': 3.14159, '%(': 1, '%(list)': '%(list)'})
407 self.assertRaises(TypeError, cf.get, 'non-string', 'dict')
408 self.assertEqual(cf.get('non-string', 'string_with_interpolation',
409 raw=True), '%(list)s')
410 self.assertRaises(ValueError, cf.get, 'non-string',
411 'string_with_interpolation', raw=False)
412
Brian Curtine4334b42010-07-26 02:30:15 +0000413class MultilineValuesTestCase(TestCaseBase):
414 config_class = ConfigParser.ConfigParser
415 wonderful_spam = ("I'm having spam spam spam spam "
416 "spam spam spam beaked beans spam "
417 "spam spam and spam!").replace(' ', '\t\n')
418
419 def setUp(self):
420 cf = self.newconfig()
421 for i in range(100):
422 s = 'section{}'.format(i)
423 cf.add_section(s)
424 for j in range(10):
425 cf.set(s, 'lovely_spam{}'.format(j), self.wonderful_spam)
426 with open(test_support.TESTFN, 'w') as f:
427 cf.write(f)
428
429 def tearDown(self):
430 os.unlink(test_support.TESTFN)
431
432 def test_dominating_multiline_values(self):
433 # we're reading from file because this is where the code changed
434 # during performance updates in Python 3.2
435 cf_from_file = self.newconfig()
436 with open(test_support.TESTFN) as f:
437 cf_from_file.readfp(f)
438 self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'),
439 self.wonderful_spam.replace('\t\n', '\n'))
Fred Drake8ef67672000-09-27 22:45:25 +0000440
Fred Drakec6f28912002-10-25 19:40:49 +0000441class RawConfigParserTestCase(TestCaseBase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000442 config_class = ConfigParser.RawConfigParser
Fred Drakec6f28912002-10-25 19:40:49 +0000443
444 def test_interpolation(self):
445 cf = self.get_interpolation_config()
446 eq = self.assertEqual
447 eq(cf.get("Foo", "getname"), "%(__name__)s")
448 eq(cf.get("Foo", "bar"),
449 "something %(with1)s interpolation (1 step)")
450 eq(cf.get("Foo", "bar9"),
451 "something %(with9)s lots of interpolation (9 steps)")
452 eq(cf.get("Foo", "bar10"),
453 "something %(with10)s lots of interpolation (10 steps)")
454 eq(cf.get("Foo", "bar11"),
455 "something %(with11)s lots of interpolation (11 steps)")
Fred Drake95b96d32001-02-12 17:23:20 +0000456
Fred Drake98e3b292002-10-25 20:42:44 +0000457 def test_items(self):
458 self.check_items_config([('default', '<default>'),
459 ('getdefault', '|%(default)s|'),
460 ('getname', '|%(__name__)s|'),
461 ('key', '|%(name)s|'),
462 ('name', 'value')])
463
David Goodger1cbf2062004-10-03 15:55:09 +0000464 def test_set_nonstring_types(self):
465 cf = self.newconfig()
466 cf.add_section('non-string')
467 cf.set('non-string', 'int', 1)
468 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13])
469 cf.set('non-string', 'dict', {'pi': 3.14159})
470 self.assertEqual(cf.get('non-string', 'int'), 1)
471 self.assertEqual(cf.get('non-string', 'list'),
472 [0, 1, 1, 2, 3, 5, 8, 13])
473 self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159})
Tim Petersab9b32c2004-10-03 18:35:19 +0000474
Fred Drake8ef67672000-09-27 22:45:25 +0000475
Fred Drake0eebd5c2002-10-25 21:52:00 +0000476class SafeConfigParserTestCase(ConfigParserTestCase):
Georg Brandl392c6fc2008-05-25 07:25:25 +0000477 config_class = ConfigParser.SafeConfigParser
Fred Drake0eebd5c2002-10-25 21:52:00 +0000478
479 def test_safe_interpolation(self):
480 # See http://www.python.org/sf/511737
481 cf = self.fromstring("[section]\n"
482 "option1=xxx\n"
483 "option2=%(option1)s/xxx\n"
484 "ok=%(option1)s/%%s\n"
485 "not_ok=%(option2)s/%%s")
486 self.assertEqual(cf.get("section", "ok"), "xxx/%s")
487 self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s")
488
Georg Brandl92a6bae2007-03-13 17:43:32 +0000489 def test_set_malformatted_interpolation(self):
490 cf = self.fromstring("[sect]\n"
491 "option1=foo\n")
492
493 self.assertEqual(cf.get('sect', "option1"), "foo")
494
495 self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo")
496 self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%")
497 self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo")
498
499 self.assertEqual(cf.get('sect', "option1"), "foo")
500
Georg Brandl21cf5ee2009-04-12 17:24:11 +0000501 # bug #5741: double percents are *not* malformed
502 cf.set("sect", "option2", "foo%%bar")
503 self.assertEqual(cf.get("sect", "option2"), "foo%bar")
504
David Goodger1cbf2062004-10-03 15:55:09 +0000505 def test_set_nonstring_types(self):
506 cf = self.fromstring("[sect]\n"
507 "option1=foo\n")
508 # Check that we get a TypeError when setting non-string values
509 # in an existing section:
510 self.assertRaises(TypeError, cf.set, "sect", "option1", 1)
511 self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0)
512 self.assertRaises(TypeError, cf.set, "sect", "option1", object())
513 self.assertRaises(TypeError, cf.set, "sect", "option2", 1)
514 self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
515 self.assertRaises(TypeError, cf.set, "sect", "option2", object())
516
Facundo Batistab12f0b52008-02-23 12:46:10 +0000517 def test_add_section_default_1(self):
518 cf = self.newconfig()
519 self.assertRaises(ValueError, cf.add_section, "default")
520
521 def test_add_section_default_2(self):
522 cf = self.newconfig()
523 self.assertRaises(ValueError, cf.add_section, "DEFAULT")
524
Fred Drakecc43b562010-02-19 05:24:30 +0000525
526class SafeConfigParserTestCaseNoValue(SafeConfigParserTestCase):
527 allow_no_value = True
528
529
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000530class SortedTestCase(RawConfigParserTestCase):
531 def newconfig(self, defaults=None):
532 self.cf = self.config_class(defaults=defaults, dict_type=SortedDict)
533 return self.cf
534
535 def test_sorted(self):
536 self.fromstring("[b]\n"
537 "o4=1\n"
538 "o3=2\n"
539 "o2=3\n"
540 "o1=4\n"
541 "[a]\n"
Tim Petersf733abb2007-01-30 03:03:46 +0000542 "k=v\n")
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000543 output = StringIO.StringIO()
544 self.cf.write(output)
545 self.assertEquals(output.getvalue(),
546 "[a]\n"
Tim Petersf733abb2007-01-30 03:03:46 +0000547 "k = v\n\n"
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000548 "[b]\n"
549 "o1 = 4\n"
550 "o2 = 3\n"
551 "o3 = 2\n"
552 "o4 = 1\n\n")
Fred Drake0eebd5c2002-10-25 21:52:00 +0000553
Fred Drakecc43b562010-02-19 05:24:30 +0000554
Fred Drakec6f28912002-10-25 19:40:49 +0000555def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000556 test_support.run_unittest(
557 ConfigParserTestCase,
Brian Curtine4334b42010-07-26 02:30:15 +0000558 MultilineValuesTestCase,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000559 RawConfigParserTestCase,
Martin v. Löwisa00bcac2006-12-03 12:01:53 +0000560 SafeConfigParserTestCase,
Fred Drakecc43b562010-02-19 05:24:30 +0000561 SafeConfigParserTestCaseNoValue,
Brian Curtine4334b42010-07-26 02:30:15 +0000562 SortedTestCase,
Fred Drakecc43b562010-02-19 05:24:30 +0000563 )
564
Fred Drake3af0eb82002-10-25 18:09:24 +0000565
Fred Drakec6f28912002-10-25 19:40:49 +0000566if __name__ == "__main__":
567 test_main()