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 288 def test_set_unicode(self): 289 try: 290 unicode 291 except NameError: 292 self.skipTest('no unicode support') 293 294 cf = self.fromstring("[sect]\n" 295 "option1=foo\n") 296 cf.set("sect", "option1", unicode("splat")) 297 cf.set("sect", "option2", unicode("splat")) 298 299 def test_read_returns_file_list(self): 300 file1 = test_support.findfile("cfgparser.1") 301 # check when we pass a mix of readable and non-readable files: 302 cf = self.newconfig() 303 parsed_files = cf.read([file1, "nonexistent-file"]) 304 self.assertEqual(parsed_files, [file1]) 305 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") 306 # check when we pass only a filename: 307 cf = self.newconfig() 308 parsed_files = cf.read(file1) 309 self.assertEqual(parsed_files, [file1]) 310 self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") 311 # check when we pass only missing files: 312 cf = self.newconfig() 313 parsed_files = cf.read(["nonexistent-file"]) 314 self.assertEqual(parsed_files, []) 315 # check when we pass no files: 316 cf = self.newconfig() 317 parsed_files = cf.read([]) 318 self.assertEqual(parsed_files, []) 319 320 # shared by subclasses 321 def get_interpolation_config(self): 322 return self.fromstring( 323 "[Foo]\n" 324 "bar=something %(with1)s interpolation (1 step)\n" 325 "bar9=something %(with9)s lots of interpolation (9 steps)\n" 326 "bar10=something %(with10)s lots of interpolation (10 steps)\n" 327 "bar11=something %(with11)s lots of interpolation (11 steps)\n" 328 "with11=%(with10)s\n" 329 "with10=%(with9)s\n" 330 "with9=%(with8)s\n" 331 "with8=%(With7)s\n" 332 "with7=%(WITH6)s\n" 333 "with6=%(with5)s\n" 334 "With5=%(with4)s\n" 335 "WITH4=%(with3)s\n" 336 "with3=%(with2)s\n" 337 "with2=%(with1)s\n" 338 "with1=with\n" 339 "\n" 340 "[Mutual Recursion]\n" 341 "foo=%(bar)s\n" 342 "bar=%(foo)s\n" 343 "\n" 344 "[Interpolation Error]\n" 345 "name=%(reference)s\n", 346 # no definition for 'reference' 347 defaults={"getname": "%(__name__)s"}) 348 349 def check_items_config(self, expected): 350 cf = self.fromstring( 351 "[section]\n" 352 "name = value\n" 353 "key: |%(name)s| \n" 354 "getdefault: |%(default)s|\n" 355 "getname: |%(__name__)s|", 356 defaults={"default": "<default>"}) 357 L = list(cf.items("section")) 358 L.sort() 359 self.assertEqual(L, expected) 360 361 362class ConfigParserTestCase(TestCaseBase): 363 config_class = ConfigParser.ConfigParser 364 allow_no_value = True 365 366 def test_interpolation(self): 367 rawval = { 368 ConfigParser.ConfigParser: ("something %(with11)s " 369 "lots of interpolation (11 steps)"), 370 ConfigParser.SafeConfigParser: "%(with1)s", 371 } 372 cf = self.get_interpolation_config() 373 eq = self.assertEqual 374 eq(cf.get("Foo", "getname"), "Foo") 375 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)") 376 eq(cf.get("Foo", "bar9"), 377 "something with lots of interpolation (9 steps)") 378 eq(cf.get("Foo", "bar10"), 379 "something with lots of interpolation (10 steps)") 380 self.get_error(ConfigParser.InterpolationDepthError, "Foo", "bar11") 381 382 def test_interpolation_missing_value(self): 383 self.get_interpolation_config() 384 e = self.get_error(ConfigParser.InterpolationError, 385 "Interpolation Error", "name") 386 self.assertEqual(e.reference, "reference") 387 self.assertEqual(e.section, "Interpolation Error") 388 self.assertEqual(e.option, "name") 389 390 def test_items(self): 391 self.check_items_config([('default', '<default>'), 392 ('getdefault', '|<default>|'), 393 ('getname', '|section|'), 394 ('key', '|value|'), 395 ('name', 'value')]) 396 397 def test_set_nonstring_types(self): 398 cf = self.newconfig() 399 cf.add_section('non-string') 400 cf.set('non-string', 'int', 1) 401 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13, '%(']) 402 cf.set('non-string', 'dict', {'pi': 3.14159, '%(': 1, 403 '%(list)': '%(list)'}) 404 cf.set('non-string', 'string_with_interpolation', '%(list)s') 405 cf.set('non-string', 'no-value') 406 self.assertEqual(cf.get('non-string', 'int', raw=True), 1) 407 self.assertRaises(TypeError, cf.get, 'non-string', 'int') 408 self.assertEqual(cf.get('non-string', 'list', raw=True), 409 [0, 1, 1, 2, 3, 5, 8, 13, '%(']) 410 self.assertRaises(TypeError, cf.get, 'non-string', 'list') 411 self.assertEqual(cf.get('non-string', 'dict', raw=True), 412 {'pi': 3.14159, '%(': 1, '%(list)': '%(list)'}) 413 self.assertRaises(TypeError, cf.get, 'non-string', 'dict') 414 self.assertEqual(cf.get('non-string', 'string_with_interpolation', 415 raw=True), '%(list)s') 416 self.assertRaises(ValueError, cf.get, 'non-string', 417 'string_with_interpolation', raw=False) 418 self.assertEqual(cf.get('non-string', 'no-value'), None) 419 420class MultilineValuesTestCase(TestCaseBase): 421 config_class = ConfigParser.ConfigParser 422 wonderful_spam = ("I'm having spam spam spam spam " 423 "spam spam spam beaked beans spam " 424 "spam spam and spam!").replace(' ', '\t\n') 425 426 def setUp(self): 427 cf = self.newconfig() 428 for i in range(100): 429 s = 'section{}'.format(i) 430 cf.add_section(s) 431 for j in range(10): 432 cf.set(s, 'lovely_spam{}'.format(j), self.wonderful_spam) 433 with open(test_support.TESTFN, 'w') as f: 434 cf.write(f) 435 436 def tearDown(self): 437 os.unlink(test_support.TESTFN) 438 439 def test_dominating_multiline_values(self): 440 # we're reading from file because this is where the code changed 441 # during performance updates in Python 3.2 442 cf_from_file = self.newconfig() 443 with open(test_support.TESTFN) as f: 444 cf_from_file.readfp(f) 445 self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'), 446 self.wonderful_spam.replace('\t\n', '\n')) 447 448class RawConfigParserTestCase(TestCaseBase): 449 config_class = ConfigParser.RawConfigParser 450 451 def test_interpolation(self): 452 cf = self.get_interpolation_config() 453 eq = self.assertEqual 454 eq(cf.get("Foo", "getname"), "%(__name__)s") 455 eq(cf.get("Foo", "bar"), 456 "something %(with1)s interpolation (1 step)") 457 eq(cf.get("Foo", "bar9"), 458 "something %(with9)s lots of interpolation (9 steps)") 459 eq(cf.get("Foo", "bar10"), 460 "something %(with10)s lots of interpolation (10 steps)") 461 eq(cf.get("Foo", "bar11"), 462 "something %(with11)s lots of interpolation (11 steps)") 463 464 def test_items(self): 465 self.check_items_config([('default', '<default>'), 466 ('getdefault', '|%(default)s|'), 467 ('getname', '|%(__name__)s|'), 468 ('key', '|%(name)s|'), 469 ('name', 'value')]) 470 471 def test_set_nonstring_types(self): 472 cf = self.newconfig() 473 cf.add_section('non-string') 474 cf.set('non-string', 'int', 1) 475 cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13]) 476 cf.set('non-string', 'dict', {'pi': 3.14159}) 477 self.assertEqual(cf.get('non-string', 'int'), 1) 478 self.assertEqual(cf.get('non-string', 'list'), 479 [0, 1, 1, 2, 3, 5, 8, 13]) 480 self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159}) 481 482 483class SafeConfigParserTestCase(ConfigParserTestCase): 484 config_class = ConfigParser.SafeConfigParser 485 486 def test_safe_interpolation(self): 487 # See http://www.python.org/sf/511737 488 cf = self.fromstring("[section]\n" 489 "option1=xxx\n" 490 "option2=%(option1)s/xxx\n" 491 "ok=%(option1)s/%%s\n" 492 "not_ok=%(option2)s/%%s") 493 self.assertEqual(cf.get("section", "ok"), "xxx/%s") 494 self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s") 495 496 def test_set_malformatted_interpolation(self): 497 cf = self.fromstring("[sect]\n" 498 "option1=foo\n") 499 500 self.assertEqual(cf.get('sect', "option1"), "foo") 501 502 self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo") 503 self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%") 504 self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo") 505 506 self.assertEqual(cf.get('sect', "option1"), "foo") 507 508 # bug #5741: double percents are *not* malformed 509 cf.set("sect", "option2", "foo%%bar") 510 self.assertEqual(cf.get("sect", "option2"), "foo%bar") 511 512 def test_set_nonstring_types(self): 513 cf = self.fromstring("[sect]\n" 514 "option1=foo\n") 515 # Check that we get a TypeError when setting non-string values 516 # in an existing section: 517 self.assertRaises(TypeError, cf.set, "sect", "option1", 1) 518 self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0) 519 self.assertRaises(TypeError, cf.set, "sect", "option1", object()) 520 self.assertRaises(TypeError, cf.set, "sect", "option2", 1) 521 self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0) 522 self.assertRaises(TypeError, cf.set, "sect", "option2", object()) 523 524 def test_add_section_default_1(self): 525 cf = self.newconfig() 526 self.assertRaises(ValueError, cf.add_section, "default") 527 528 def test_add_section_default_2(self): 529 cf = self.newconfig() 530 self.assertRaises(ValueError, cf.add_section, "DEFAULT") 531 532 533class SafeConfigParserTestCaseNoValue(SafeConfigParserTestCase): 534 allow_no_value = True 535 536class TestChainMap(unittest.TestCase): 537 def test_issue_12717(self): 538 d1 = dict(red=1, green=2) 539 d2 = dict(green=3, blue=4) 540 dcomb = d2.copy() 541 dcomb.update(d1) 542 cm = ConfigParser._Chainmap(d1, d2) 543 self.assertIsInstance(cm.keys(), list) 544 self.assertEqual(set(cm.keys()), set(dcomb.keys())) # keys() 545 self.assertEqual(set(cm.values()), set(dcomb.values())) # values() 546 self.assertEqual(set(cm.items()), set(dcomb.items())) # items() 547 self.assertEqual(set(cm), set(dcomb)) # __iter__ () 548 self.assertEqual(cm, dcomb) # __eq__() 549 self.assertEqual([cm[k] for k in dcomb], dcomb.values()) # __getitem__() 550 klist = 'red green blue black brown'.split() 551 self.assertEqual([cm.get(k, 10) for k in klist], 552 [dcomb.get(k, 10) for k in klist]) # get() 553 self.assertEqual([k in cm for k in klist], 554 [k in dcomb for k in klist]) # __contains__() 555 with test_support.check_py3k_warnings(): 556 self.assertEqual([cm.has_key(k) for k in klist], 557 [dcomb.has_key(k) for k in klist]) # has_key() 558 559class Issue7005TestCase(unittest.TestCase): 560 """Test output when None is set() as a value and allow_no_value == False. 561 562 http://bugs.python.org/issue7005 563 564 """ 565 566 expected_output = "[section]\noption = None\n\n" 567 568 def prepare(self, config_class): 569 # This is the default, but that's the point. 570 cp = config_class(allow_no_value=False) 571 cp.add_section("section") 572 cp.set("section", "option", None) 573 sio = StringIO.StringIO() 574 cp.write(sio) 575 return sio.getvalue() 576 577 def test_none_as_value_stringified(self): 578 output = self.prepare(ConfigParser.ConfigParser) 579 self.assertEqual(output, self.expected_output) 580 581 def test_none_as_value_stringified_raw(self): 582 output = self.prepare(ConfigParser.RawConfigParser) 583 self.assertEqual(output, self.expected_output) 584 585 586class SortedTestCase(RawConfigParserTestCase): 587 def newconfig(self, defaults=None): 588 self.cf = self.config_class(defaults=defaults, dict_type=SortedDict) 589 return self.cf 590 591 def test_sorted(self): 592 self.fromstring("[b]\n" 593 "o4=1\n" 594 "o3=2\n" 595 "o2=3\n" 596 "o1=4\n" 597 "[a]\n" 598 "k=v\n") 599 output = StringIO.StringIO() 600 self.cf.write(output) 601 self.assertEqual(output.getvalue(), 602 "[a]\n" 603 "k = v\n\n" 604 "[b]\n" 605 "o1 = 4\n" 606 "o2 = 3\n" 607 "o3 = 2\n" 608 "o4 = 1\n\n") 609 610 611class ExceptionPicklingTestCase(unittest.TestCase): 612 """Tests for issue #13760: ConfigParser exceptions are not picklable.""" 613 614 def test_error(self): 615 import pickle 616 e1 = ConfigParser.Error('value') 617 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 618 pickled = pickle.dumps(e1, proto) 619 e2 = pickle.loads(pickled) 620 self.assertEqual(e1.message, e2.message) 621 self.assertEqual(repr(e1), repr(e2)) 622 623 def test_nosectionerror(self): 624 import pickle 625 e1 = ConfigParser.NoSectionError('section') 626 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 627 pickled = pickle.dumps(e1, proto) 628 e2 = pickle.loads(pickled) 629 self.assertEqual(e1.message, e2.message) 630 self.assertEqual(e1.args, e2.args) 631 self.assertEqual(e1.section, e2.section) 632 self.assertEqual(repr(e1), repr(e2)) 633 634 def test_nooptionerror(self): 635 import pickle 636 e1 = ConfigParser.NoOptionError('option', 'section') 637 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 638 pickled = pickle.dumps(e1, proto) 639 e2 = pickle.loads(pickled) 640 self.assertEqual(e1.message, e2.message) 641 self.assertEqual(e1.args, e2.args) 642 self.assertEqual(e1.section, e2.section) 643 self.assertEqual(e1.option, e2.option) 644 self.assertEqual(repr(e1), repr(e2)) 645 646 def test_duplicatesectionerror(self): 647 import pickle 648 e1 = ConfigParser.DuplicateSectionError('section') 649 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 650 pickled = pickle.dumps(e1, proto) 651 e2 = pickle.loads(pickled) 652 self.assertEqual(e1.message, e2.message) 653 self.assertEqual(e1.args, e2.args) 654 self.assertEqual(e1.section, e2.section) 655 self.assertEqual(repr(e1), repr(e2)) 656 657 def test_interpolationerror(self): 658 import pickle 659 e1 = ConfigParser.InterpolationError('option', 'section', 'msg') 660 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 661 pickled = pickle.dumps(e1, proto) 662 e2 = pickle.loads(pickled) 663 self.assertEqual(e1.message, e2.message) 664 self.assertEqual(e1.args, e2.args) 665 self.assertEqual(e1.section, e2.section) 666 self.assertEqual(e1.option, e2.option) 667 self.assertEqual(repr(e1), repr(e2)) 668 669 def test_interpolationmissingoptionerror(self): 670 import pickle 671 e1 = ConfigParser.InterpolationMissingOptionError('option', 'section', 672 'rawval', 'reference') 673 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 674 pickled = pickle.dumps(e1, proto) 675 e2 = pickle.loads(pickled) 676 self.assertEqual(e1.message, e2.message) 677 self.assertEqual(e1.args, e2.args) 678 self.assertEqual(e1.section, e2.section) 679 self.assertEqual(e1.option, e2.option) 680 self.assertEqual(e1.reference, e2.reference) 681 self.assertEqual(repr(e1), repr(e2)) 682 683 def test_interpolationsyntaxerror(self): 684 import pickle 685 e1 = ConfigParser.InterpolationSyntaxError('option', 'section', 'msg') 686 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 687 pickled = pickle.dumps(e1, proto) 688 e2 = pickle.loads(pickled) 689 self.assertEqual(e1.message, e2.message) 690 self.assertEqual(e1.args, e2.args) 691 self.assertEqual(e1.section, e2.section) 692 self.assertEqual(e1.option, e2.option) 693 self.assertEqual(repr(e1), repr(e2)) 694 695 def test_interpolationdeptherror(self): 696 import pickle 697 e1 = ConfigParser.InterpolationDepthError('option', 'section', 698 'rawval') 699 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 700 pickled = pickle.dumps(e1, proto) 701 e2 = pickle.loads(pickled) 702 self.assertEqual(e1.message, e2.message) 703 self.assertEqual(e1.args, e2.args) 704 self.assertEqual(e1.section, e2.section) 705 self.assertEqual(e1.option, e2.option) 706 self.assertEqual(repr(e1), repr(e2)) 707 708 def test_parsingerror(self): 709 import pickle 710 e1 = ConfigParser.ParsingError('source') 711 e1.append(1, 'line1') 712 e1.append(2, 'line2') 713 e1.append(3, 'line3') 714 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 715 pickled = pickle.dumps(e1, proto) 716 e2 = pickle.loads(pickled) 717 self.assertEqual(e1.message, e2.message) 718 self.assertEqual(e1.args, e2.args) 719 self.assertEqual(e1.filename, e2.filename) 720 self.assertEqual(e1.errors, e2.errors) 721 self.assertEqual(repr(e1), repr(e2)) 722 723 def test_missingsectionheadererror(self): 724 import pickle 725 e1 = ConfigParser.MissingSectionHeaderError('filename', 123, 'line') 726 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 727 pickled = pickle.dumps(e1, proto) 728 e2 = pickle.loads(pickled) 729 self.assertEqual(e1.message, e2.message) 730 self.assertEqual(e1.args, e2.args) 731 self.assertEqual(e1.line, e2.line) 732 self.assertEqual(e1.filename, e2.filename) 733 self.assertEqual(e1.lineno, e2.lineno) 734 self.assertEqual(repr(e1), repr(e2)) 735 736 737def test_main(): 738 test_support.run_unittest( 739 ConfigParserTestCase, 740 MultilineValuesTestCase, 741 RawConfigParserTestCase, 742 SafeConfigParserTestCase, 743 SafeConfigParserTestCaseNoValue, 744 SortedTestCase, 745 Issue7005TestCase, 746 TestChainMap, 747 ExceptionPicklingTestCase, 748 ) 749 750 751if __name__ == "__main__": 752 test_main() 753