1 import ConfigParser 2 import StringIO 3 import os 4 import unittest 5 import UserDict 6 7 from test import test_support 8 9 10 class 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 32 class 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 358 class 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 416 class 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 444 class 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 479 class 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 529 class SafeConfigParserTestCaseNoValue(SafeConfigParserTestCase): 530 allow_no_value = True 531 532 class 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 555 class 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 582 class 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 607 class 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 723 def 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 737 if __name__ == "__main__": 738 test_main() 739