source: python/trunk/Lib/test/test_cfgparser.py

Last change on this file was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

  • Property svn:eol-style set to native
File size: 27.1 KB
Line 
1import ConfigParser
2import StringIO
3import os
4import unittest
5import UserDict
6
7from test import test_support
8
9
10class 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
20
21 def values(self):
22 # XXX never used?
23 result = self.items()
24 return [i[1] for i in result]
25
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())
30
31
32class TestCaseBase(unittest.TestCase):
33 allow_no_value = False
34
35 def newconfig(self, defaults=None):
36 if defaults is None:
37 self.cf = self.config_class(allow_no_value=self.allow_no_value)
38 else:
39 self.cf = self.config_class(defaults,
40 allow_no_value=self.allow_no_value)
41 return self.cf
42
43 def fromstring(self, string, defaults=None):
44 cf = self.newconfig(defaults)
45 sio = StringIO.StringIO(string)
46 cf.readfp(sio)
47 return cf
48
49 def test_basic(self):
50 config_string = (
51 "[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 )
70 if self.allow_no_value:
71 config_string += (
72 "[NoValue]\n"
73 "option-without-value\n"
74 )
75
76 cf = self.fromstring(config_string)
77 L = cf.sections()
78 L.sort()
79 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()
90 eq = self.assertEqual
91 eq(L, E)
92
93 # 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!')
101 if self.allow_no_value:
102 eq(cf.get('NoValue', 'option-without-value'), None)
103
104 self.assertNotIn('__name__', cf.options("Foo Bar"),
105 '__name__ "option" should not be exposed by the API!')
106
107 # Make sure the right things happen for remove_option();
108 # added to include check for SourceForge bug #123324:
109 self.assertTrue(cf.remove_option('Foo Bar', 'foo'),
110 "remove_option() failed to report existence of option")
111 self.assertFalse(cf.has_option('Foo Bar', 'foo'),
112 "remove_option() failed to remove option")
113 self.assertFalse(cf.remove_option('Foo Bar', 'foo'),
114 "remove_option() failed to report non-existence of option"
115 " that was removed")
116
117 self.assertRaises(ConfigParser.NoSectionError,
118 cf.remove_option, 'No Such Section', 'foo')
119
120 eq(cf.get('Long Line', 'foo'),
121 'this line is much, much longer than my editor\nlikes it.')
122
123 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",
134 "could not locate option, expecting case-insensitive option names")
135 self.assertTrue(cf.has_option("a", "b"))
136 cf.set("A", "A-B", "A-B value")
137 for opt in ("a-b", "A-b", "a-B", "A-B"):
138 self.assertTrue(
139 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"), [])
145
146 # 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")
151
152 # SF bug #561822:
153 cf = self.fromstring("[section]\nnekey=nevalue\n",
154 defaults={"key":"value"})
155 self.assertTrue(cf.has_option("section", "Key"))
156
157
158 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
168 def test_parse_errors(self):
169 self.newconfig()
170 self.parse_error(ConfigParser.ParsingError,
171 "[Foo]\n extra-spaces: splat\n")
172 self.parse_error(ConfigParser.ParsingError,
173 "[Foo]\n extra-spaces= splat\n")
174 self.parse_error(ConfigParser.ParsingError,
175 "[Foo]\n:value-without-option-name\n")
176 self.parse_error(ConfigParser.ParsingError,
177 "[Foo]\n=value-without-option-name\n")
178 self.parse_error(ConfigParser.MissingSectionHeaderError,
179 "No Section!\n")
180
181 def parse_error(self, exc, src):
182 sio = StringIO.StringIO(src)
183 self.assertRaises(exc, self.cf.readfp, sio)
184
185 def test_query_errors(self):
186 cf = self.newconfig()
187 self.assertEqual(cf.sections(), [],
188 "new ConfigParser should have no defined sections")
189 self.assertFalse(cf.has_section("Foo"),
190 "new ConfigParser should have no acknowledged "
191 "sections")
192 self.assertRaises(ConfigParser.NoSectionError,
193 cf.options, "Foo")
194 self.assertRaises(ConfigParser.NoSectionError,
195 cf.set, "foo", "bar", "value")
196 self.get_error(ConfigParser.NoSectionError, "foo", "bar")
197 cf.add_section("foo")
198 self.get_error(ConfigParser.NoOptionError, "foo", "bar")
199
200 def get_error(self, exc, section, option):
201 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__))
208
209 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):
229 self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x))
230 self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x))
231 self.assertRaises(ValueError,
232 cf.getboolean, 'BOOLTEST', 'e%d' % x)
233
234 def test_weird_errors(self):
235 cf = self.newconfig()
236 cf.add_section("Foo")
237 self.assertRaises(ConfigParser.DuplicateSectionError,
238 cf.add_section, "Foo")
239
240 def test_write(self):
241 config_string = (
242 "[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"
247 " long line\n"
248 )
249 if self.allow_no_value:
250 config_string += (
251 "[Valueless]\n"
252 "option-without-value\n"
253 )
254
255 cf = self.fromstring(config_string)
256 output = StringIO.StringIO()
257 cf.write(output)
258 expect_string = (
259 "[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 )
268 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)
275
276 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
295 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()
299 parsed_files = cf.read([file1, "nonexistent-file"])
300 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()
309 parsed_files = cf.read(["nonexistent-file"])
310 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
316 # 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"
327 "with8=%(With7)s\n"
328 "with7=%(WITH6)s\n"
329 "with6=%(with5)s\n"
330 "With5=%(with4)s\n"
331 "WITH4=%(with3)s\n"
332 "with3=%(with2)s\n"
333 "with2=%(with1)s\n"
334 "with1=with\n"
335 "\n"
336 "[Mutual Recursion]\n"
337 "foo=%(bar)s\n"
338 "bar=%(foo)s\n"
339 "\n"
340 "[Interpolation Error]\n"
341 "name=%(reference)s\n",
342 # no definition for 'reference'
343 defaults={"getname": "%(__name__)s"})
344
345 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
357
358class ConfigParserTestCase(TestCaseBase):
359 config_class = ConfigParser.ConfigParser
360 allow_no_value = True
361
362 def test_interpolation(self):
363 rawval = {
364 ConfigParser.ConfigParser: ("something %(with11)s "
365 "lots of interpolation (11 steps)"),
366 ConfigParser.SafeConfigParser: "%(with1)s",
367 }
368 cf = self.get_interpolation_config()
369 eq = self.assertEqual
370 eq(cf.get("Foo", "getname"), "Foo")
371 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
372 eq(cf.get("Foo", "bar9"),
373 "something with lots of interpolation (9 steps)")
374 eq(cf.get("Foo", "bar10"),
375 "something with lots of interpolation (10 steps)")
376 self.get_error(ConfigParser.InterpolationDepthError, "Foo", "bar11")
377
378 def test_interpolation_missing_value(self):
379 self.get_interpolation_config()
380 e = self.get_error(ConfigParser.InterpolationError,
381 "Interpolation Error", "name")
382 self.assertEqual(e.reference, "reference")
383 self.assertEqual(e.section, "Interpolation Error")
384 self.assertEqual(e.option, "name")
385
386 def test_items(self):
387 self.check_items_config([('default', '<default>'),
388 ('getdefault', '|<default>|'),
389 ('getname', '|section|'),
390 ('key', '|value|'),
391 ('name', 'value')])
392
393 def test_set_nonstring_types(self):
394 cf = self.newconfig()
395 cf.add_section('non-string')
396 cf.set('non-string', 'int', 1)
397 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%('])
398 cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1,
399 '%(list)': '%(list)'})
400 cf.set('non-string', 'string_with_interpolation', '%(list)s')
401 cf.set('non-string', 'no-value')
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 self.assertEqual(cf.get('non-string', 'no-value'), None)
415
416class MultilineValuesTestCase(TestCaseBase):
417 config_class = ConfigParser.ConfigParser
418 wonderful_spam = ("I'm having spam spam spam spam "
419 "spam spam spam beaked beans spam "
420 "spam spam and spam!").replace(' ', '\t\n')
421
422 def setUp(self):
423 cf = self.newconfig()
424 for i in range(100):
425 s = 'section{}'.format(i)
426 cf.add_section(s)
427 for j in range(10):
428 cf.set(s, 'lovely_spam{}'.format(j), self.wonderful_spam)
429 with open(test_support.TESTFN, 'w') as f:
430 cf.write(f)
431
432 def tearDown(self):
433 os.unlink(test_support.TESTFN)
434
435 def test_dominating_multiline_values(self):
436 # we're reading from file because this is where the code changed
437 # during performance updates in Python 3.2
438 cf_from_file = self.newconfig()
439 with open(test_support.TESTFN) as f:
440 cf_from_file.readfp(f)
441 self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'),
442 self.wonderful_spam.replace('\t\n', '\n'))
443
444class RawConfigParserTestCase(TestCaseBase):
445 config_class = ConfigParser.RawConfigParser
446
447 def test_interpolation(self):
448 cf = self.get_interpolation_config()
449 eq = self.assertEqual
450 eq(cf.get("Foo", "getname"), "%(__name__)s")
451 eq(cf.get("Foo", "bar"),
452 "something %(with1)s interpolation (1 step)")
453 eq(cf.get("Foo", "bar9"),
454 "something %(with9)s lots of interpolation (9 steps)")
455 eq(cf.get("Foo", "bar10"),
456 "something %(with10)s lots of interpolation (10 steps)")
457 eq(cf.get("Foo", "bar11"),
458 "something %(with11)s lots of interpolation (11 steps)")
459
460 def test_items(self):
461 self.check_items_config([('default', '<default>'),
462 ('getdefault', '|%(default)s|'),
463 ('getname', '|%(__name__)s|'),
464 ('key', '|%(name)s|'),
465 ('name', 'value')])
466
467 def test_set_nonstring_types(self):
468 cf = self.newconfig()
469 cf.add_section('non-string')
470 cf.set('non-string', 'int', 1)
471 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13])
472 cf.set('non-string', 'dict', {'pi': 3.14159})
473 self.assertEqual(cf.get('non-string', 'int'), 1)
474 self.assertEqual(cf.get('non-string', 'list'),
475 [0, 1, 1, 2, 3, 5, 8, 13])
476 self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159})
477
478
479class SafeConfigParserTestCase(ConfigParserTestCase):
480 config_class = ConfigParser.SafeConfigParser
481
482 def test_safe_interpolation(self):
483 # See http://www.python.org/sf/511737
484 cf = self.fromstring("[section]\n"
485 "option1=xxx\n"
486 "option2=%(option1)s/xxx\n"
487 "ok=%(option1)s/%%s\n"
488 "not_ok=%(option2)s/%%s")
489 self.assertEqual(cf.get("section", "ok"), "xxx/%s")
490 self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s")
491
492 def test_set_malformatted_interpolation(self):
493 cf = self.fromstring("[sect]\n"
494 "option1=foo\n")
495
496 self.assertEqual(cf.get('sect', "option1"), "foo")
497
498 self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo")
499 self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%")
500 self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo")
501
502 self.assertEqual(cf.get('sect', "option1"), "foo")
503
504 # bug #5741: double percents are *not* malformed
505 cf.set("sect", "option2", "foo%%bar")
506 self.assertEqual(cf.get("sect", "option2"), "foo%bar")
507
508 def test_set_nonstring_types(self):
509 cf = self.fromstring("[sect]\n"
510 "option1=foo\n")
511 # Check that we get a TypeError when setting non-string values
512 # in an existing section:
513 self.assertRaises(TypeError, cf.set, "sect", "option1", 1)
514 self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0)
515 self.assertRaises(TypeError, cf.set, "sect", "option1", object())
516 self.assertRaises(TypeError, cf.set, "sect", "option2", 1)
517 self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
518 self.assertRaises(TypeError, cf.set, "sect", "option2", object())
519
520 def test_add_section_default_1(self):
521 cf = self.newconfig()
522 self.assertRaises(ValueError, cf.add_section, "default")
523
524 def test_add_section_default_2(self):
525 cf = self.newconfig()
526 self.assertRaises(ValueError, cf.add_section, "DEFAULT")
527
528
529class SafeConfigParserTestCaseNoValue(SafeConfigParserTestCase):
530 allow_no_value = True
531
532class TestChainMap(unittest.TestCase):
533 def test_issue_12717(self):
534 d1 = dict(red=1, green=2)
535 d2 = dict(green=3, blue=4)
536 dcomb = d2.copy()
537 dcomb.update(d1)
538 cm = ConfigParser._Chainmap(d1, d2)
539 self.assertIsInstance(cm.keys(), list)
540 self.assertEqual(set(cm.keys()), set(dcomb.keys())) # keys()
541 self.assertEqual(set(cm.values()), set(dcomb.values())) # values()
542 self.assertEqual(set(cm.items()), set(dcomb.items())) # items()
543 self.assertEqual(set(cm), set(dcomb)) # __iter__ ()
544 self.assertEqual(cm, dcomb) # __eq__()
545 self.assertEqual([cm[k] for k in dcomb], dcomb.values()) # __getitem__()
546 klist = 'red green blue black brown'.split()
547 self.assertEqual([cm.get(k, 10) for k in klist],
548 [dcomb.get(k, 10) for k in klist]) # get()
549 self.assertEqual([k in cm for k in klist],
550 [k in dcomb for k in klist]) # __contains__()
551 with test_support.check_py3k_warnings():
552 self.assertEqual([cm.has_key(k) for k in klist],
553 [dcomb.has_key(k) for k in klist]) # has_key()
554
555class Issue7005TestCase(unittest.TestCase):
556 """Test output when None is set() as a value and allow_no_value == False.
557
558 http://bugs.python.org/issue7005
559
560 """
561
562 expected_output = "[section]\noption = None\n\n"
563
564 def prepare(self, config_class):
565 # This is the default, but that's the point.
566 cp = config_class(allow_no_value=False)
567 cp.add_section("section")
568 cp.set("section", "option", None)
569 sio = StringIO.StringIO()
570 cp.write(sio)
571 return sio.getvalue()
572
573 def test_none_as_value_stringified(self):
574 output = self.prepare(ConfigParser.ConfigParser)
575 self.assertEqual(output, self.expected_output)
576
577 def test_none_as_value_stringified_raw(self):
578 output = self.prepare(ConfigParser.RawConfigParser)
579 self.assertEqual(output, self.expected_output)
580
581
582class SortedTestCase(RawConfigParserTestCase):
583 def newconfig(self, defaults=None):
584 self.cf = self.config_class(defaults=defaults, dict_type=SortedDict)
585 return self.cf
586
587 def test_sorted(self):
588 self.fromstring("[b]\n"
589 "o4=1\n"
590 "o3=2\n"
591 "o2=3\n"
592 "o1=4\n"
593 "[a]\n"
594 "k=v\n")
595 output = StringIO.StringIO()
596 self.cf.write(output)
597 self.assertEqual(output.getvalue(),
598 "[a]\n"
599 "k = v\n\n"
600 "[b]\n"
601 "o1 = 4\n"
602 "o2 = 3\n"
603 "o3 = 2\n"
604 "o4 = 1\n\n")
605
606
607class ExceptionPicklingTestCase(unittest.TestCase):
608 """Tests for issue #13760: ConfigParser exceptions are not picklable."""
609
610 def test_error(self):
611 import pickle
612 e1 = ConfigParser.Error('value')
613 pickled = pickle.dumps(e1)
614 e2 = pickle.loads(pickled)
615 self.assertEqual(e1.message, e2.message)
616 self.assertEqual(repr(e1), repr(e2))
617
618 def test_nosectionerror(self):
619 import pickle
620 e1 = ConfigParser.NoSectionError('section')
621 pickled = pickle.dumps(e1)
622 e2 = pickle.loads(pickled)
623 self.assertEqual(e1.message, e2.message)
624 self.assertEqual(e1.args, e2.args)
625 self.assertEqual(e1.section, e2.section)
626 self.assertEqual(repr(e1), repr(e2))
627
628 def test_nooptionerror(self):
629 import pickle
630 e1 = ConfigParser.NoOptionError('option', 'section')
631 pickled = pickle.dumps(e1)
632 e2 = pickle.loads(pickled)
633 self.assertEqual(e1.message, e2.message)
634 self.assertEqual(e1.args, e2.args)
635 self.assertEqual(e1.section, e2.section)
636 self.assertEqual(e1.option, e2.option)
637 self.assertEqual(repr(e1), repr(e2))
638
639 def test_duplicatesectionerror(self):
640 import pickle
641 e1 = ConfigParser.DuplicateSectionError('section')
642 pickled = pickle.dumps(e1)
643 e2 = pickle.loads(pickled)
644 self.assertEqual(e1.message, e2.message)
645 self.assertEqual(e1.args, e2.args)
646 self.assertEqual(e1.section, e2.section)
647 self.assertEqual(repr(e1), repr(e2))
648
649 def test_interpolationerror(self):
650 import pickle
651 e1 = ConfigParser.InterpolationError('option', 'section', 'msg')
652 pickled = pickle.dumps(e1)
653 e2 = pickle.loads(pickled)
654 self.assertEqual(e1.message, e2.message)
655 self.assertEqual(e1.args, e2.args)
656 self.assertEqual(e1.section, e2.section)
657 self.assertEqual(e1.option, e2.option)
658 self.assertEqual(repr(e1), repr(e2))
659
660 def test_interpolationmissingoptionerror(self):
661 import pickle
662 e1 = ConfigParser.InterpolationMissingOptionError('option', 'section',
663 'rawval', 'reference')
664 pickled = pickle.dumps(e1)
665 e2 = pickle.loads(pickled)
666 self.assertEqual(e1.message, e2.message)
667 self.assertEqual(e1.args, e2.args)
668 self.assertEqual(e1.section, e2.section)
669 self.assertEqual(e1.option, e2.option)
670 self.assertEqual(e1.reference, e2.reference)
671 self.assertEqual(repr(e1), repr(e2))
672
673 def test_interpolationsyntaxerror(self):
674 import pickle
675 e1 = ConfigParser.InterpolationSyntaxError('option', 'section', 'msg')
676 pickled = pickle.dumps(e1)
677 e2 = pickle.loads(pickled)
678 self.assertEqual(e1.message, e2.message)
679 self.assertEqual(e1.args, e2.args)
680 self.assertEqual(e1.section, e2.section)
681 self.assertEqual(e1.option, e2.option)
682 self.assertEqual(repr(e1), repr(e2))
683
684 def test_interpolationdeptherror(self):
685 import pickle
686 e1 = ConfigParser.InterpolationDepthError('option', 'section',
687 'rawval')
688 pickled = pickle.dumps(e1)
689 e2 = pickle.loads(pickled)
690 self.assertEqual(e1.message, e2.message)
691 self.assertEqual(e1.args, e2.args)
692 self.assertEqual(e1.section, e2.section)
693 self.assertEqual(e1.option, e2.option)
694 self.assertEqual(repr(e1), repr(e2))
695
696 def test_parsingerror(self):
697 import pickle
698 e1 = ConfigParser.ParsingError('source')
699 e1.append(1, 'line1')
700 e1.append(2, 'line2')
701 e1.append(3, 'line3')
702 pickled = pickle.dumps(e1)
703 e2 = pickle.loads(pickled)
704 self.assertEqual(e1.message, e2.message)
705 self.assertEqual(e1.args, e2.args)
706 self.assertEqual(e1.filename, e2.filename)
707 self.assertEqual(e1.errors, e2.errors)
708 self.assertEqual(repr(e1), repr(e2))
709
710 def test_missingsectionheadererror(self):
711 import pickle
712 e1 = ConfigParser.MissingSectionHeaderError('filename', 123, 'line')
713 pickled = pickle.dumps(e1)
714 e2 = pickle.loads(pickled)
715 self.assertEqual(e1.message, e2.message)
716 self.assertEqual(e1.args, e2.args)
717 self.assertEqual(e1.line, e2.line)
718 self.assertEqual(e1.filename, e2.filename)
719 self.assertEqual(e1.lineno, e2.lineno)
720 self.assertEqual(repr(e1), repr(e2))
721
722
723def test_main():
724 test_support.run_unittest(
725 ConfigParserTestCase,
726 MultilineValuesTestCase,
727 RawConfigParserTestCase,
728 SafeConfigParserTestCase,
729 SafeConfigParserTestCaseNoValue,
730 SortedTestCase,
731 Issue7005TestCase,
732 TestChainMap,
733 ExceptionPicklingTestCase,
734 )
735
736
737if __name__ == "__main__":
738 test_main()
Note: See TracBrowser for help on using the repository browser.