1from _compat_pickle import (IMPORT_MAPPING, REVERSE_IMPORT_MAPPING, 2 NAME_MAPPING, REVERSE_NAME_MAPPING) 3import builtins 4import pickle 5import io 6import collections 7import struct 8import sys 9import warnings 10import weakref 11 12import doctest 13import unittest 14from test import support 15from test.support import import_helper 16 17from test.pickletester import AbstractHookTests 18from test.pickletester import AbstractUnpickleTests 19from test.pickletester import AbstractPicklingErrorTests 20from test.pickletester import AbstractPickleTests 21from test.pickletester import AbstractPickleModuleTests 22from test.pickletester import AbstractPersistentPicklerTests 23from test.pickletester import AbstractIdentityPersistentPicklerTests 24from test.pickletester import AbstractPicklerUnpicklerObjectTests 25from test.pickletester import AbstractDispatchTableTests 26from test.pickletester import AbstractCustomPicklerClass 27from test.pickletester import BigmemPickleTests 28 29try: 30 import _pickle 31 has_c_implementation = True 32except ImportError: 33 has_c_implementation = False 34 35 36class PyPickleTests(AbstractPickleModuleTests, unittest.TestCase): 37 dump = staticmethod(pickle._dump) 38 dumps = staticmethod(pickle._dumps) 39 load = staticmethod(pickle._load) 40 loads = staticmethod(pickle._loads) 41 Pickler = pickle._Pickler 42 Unpickler = pickle._Unpickler 43 44 45class PyUnpicklerTests(AbstractUnpickleTests, unittest.TestCase): 46 47 unpickler = pickle._Unpickler 48 bad_stack_errors = (IndexError,) 49 truncated_errors = (pickle.UnpicklingError, EOFError, 50 AttributeError, ValueError, 51 struct.error, IndexError, ImportError) 52 53 def loads(self, buf, **kwds): 54 f = io.BytesIO(buf) 55 u = self.unpickler(f, **kwds) 56 return u.load() 57 58 59class PyPicklingErrorTests(AbstractPicklingErrorTests, unittest.TestCase): 60 61 pickler = pickle._Pickler 62 63 def dumps(self, arg, proto=None, **kwargs): 64 f = io.BytesIO() 65 p = self.pickler(f, proto, **kwargs) 66 p.dump(arg) 67 f.seek(0) 68 return bytes(f.read()) 69 70 71class PyPicklerTests(AbstractPickleTests, unittest.TestCase): 72 73 pickler = pickle._Pickler 74 unpickler = pickle._Unpickler 75 76 def dumps(self, arg, proto=None, **kwargs): 77 f = io.BytesIO() 78 p = self.pickler(f, proto, **kwargs) 79 p.dump(arg) 80 f.seek(0) 81 return bytes(f.read()) 82 83 def loads(self, buf, **kwds): 84 f = io.BytesIO(buf) 85 u = self.unpickler(f, **kwds) 86 return u.load() 87 88 89class InMemoryPickleTests(AbstractPickleTests, AbstractUnpickleTests, 90 BigmemPickleTests, unittest.TestCase): 91 92 bad_stack_errors = (pickle.UnpicklingError, IndexError) 93 truncated_errors = (pickle.UnpicklingError, EOFError, 94 AttributeError, ValueError, 95 struct.error, IndexError, ImportError) 96 97 def dumps(self, arg, protocol=None, **kwargs): 98 return pickle.dumps(arg, protocol, **kwargs) 99 100 def loads(self, buf, **kwds): 101 return pickle.loads(buf, **kwds) 102 103 test_framed_write_sizes_with_delayed_writer = None 104 test_find_class = None 105 test_custom_find_class = None 106 107 108class PersistentPicklerUnpicklerMixin(object): 109 110 def dumps(self, arg, proto=None): 111 class PersPickler(self.pickler): 112 def persistent_id(subself, obj): 113 return self.persistent_id(obj) 114 f = io.BytesIO() 115 p = PersPickler(f, proto) 116 p.dump(arg) 117 return f.getvalue() 118 119 def loads(self, buf, **kwds): 120 class PersUnpickler(self.unpickler): 121 def persistent_load(subself, obj): 122 return self.persistent_load(obj) 123 f = io.BytesIO(buf) 124 u = PersUnpickler(f, **kwds) 125 return u.load() 126 127 128class PyPersPicklerTests(AbstractPersistentPicklerTests, 129 PersistentPicklerUnpicklerMixin, unittest.TestCase): 130 131 pickler = pickle._Pickler 132 unpickler = pickle._Unpickler 133 134 135class PyIdPersPicklerTests(AbstractIdentityPersistentPicklerTests, 136 PersistentPicklerUnpicklerMixin, unittest.TestCase): 137 138 pickler = pickle._Pickler 139 unpickler = pickle._Unpickler 140 persistent_load_error = pickle.UnpicklingError 141 142 @support.cpython_only 143 def test_pickler_reference_cycle(self): 144 def check(Pickler): 145 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 146 f = io.BytesIO() 147 pickler = Pickler(f, proto) 148 pickler.dump('abc') 149 self.assertEqual(self.loads(f.getvalue()), 'abc') 150 pickler = Pickler(io.BytesIO()) 151 self.assertEqual(pickler.persistent_id('def'), 'def') 152 r = weakref.ref(pickler) 153 del pickler 154 self.assertIsNone(r()) 155 156 class PersPickler(self.pickler): 157 def persistent_id(subself, obj): 158 return obj 159 check(PersPickler) 160 161 class PersPickler(self.pickler): 162 @classmethod 163 def persistent_id(cls, obj): 164 return obj 165 check(PersPickler) 166 167 class PersPickler(self.pickler): 168 @staticmethod 169 def persistent_id(obj): 170 return obj 171 check(PersPickler) 172 173 @support.cpython_only 174 def test_custom_pickler_dispatch_table_memleak(self): 175 # See https://github.com/python/cpython/issues/89988 176 177 class Pickler(self.pickler): 178 def __init__(self, *args, **kwargs): 179 self.dispatch_table = table 180 super().__init__(*args, **kwargs) 181 182 class DispatchTable: 183 pass 184 185 table = DispatchTable() 186 pickler = Pickler(io.BytesIO()) 187 self.assertIs(pickler.dispatch_table, table) 188 table_ref = weakref.ref(table) 189 self.assertIsNotNone(table_ref()) 190 del pickler 191 del table 192 support.gc_collect() 193 self.assertIsNone(table_ref()) 194 195 @support.cpython_only 196 def test_unpickler_reference_cycle(self): 197 def check(Unpickler): 198 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 199 unpickler = Unpickler(io.BytesIO(self.dumps('abc', proto))) 200 self.assertEqual(unpickler.load(), 'abc') 201 unpickler = Unpickler(io.BytesIO()) 202 self.assertEqual(unpickler.persistent_load('def'), 'def') 203 r = weakref.ref(unpickler) 204 del unpickler 205 self.assertIsNone(r()) 206 207 class PersUnpickler(self.unpickler): 208 def persistent_load(subself, pid): 209 return pid 210 check(PersUnpickler) 211 212 class PersUnpickler(self.unpickler): 213 @classmethod 214 def persistent_load(cls, pid): 215 return pid 216 check(PersUnpickler) 217 218 class PersUnpickler(self.unpickler): 219 @staticmethod 220 def persistent_load(pid): 221 return pid 222 check(PersUnpickler) 223 224 def test_pickler_super(self): 225 class PersPickler(self.pickler): 226 def persistent_id(subself, obj): 227 called.append(obj) 228 self.assertIsNone(super().persistent_id(obj)) 229 return obj 230 231 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 232 f = io.BytesIO() 233 pickler = PersPickler(f, proto) 234 called = [] 235 pickler.dump('abc') 236 self.assertEqual(called, ['abc']) 237 self.assertEqual(self.loads(f.getvalue()), 'abc') 238 239 def test_unpickler_super(self): 240 class PersUnpickler(self.unpickler): 241 def persistent_load(subself, pid): 242 called.append(pid) 243 with self.assertRaises(self.persistent_load_error): 244 super().persistent_load(pid) 245 return pid 246 247 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 248 unpickler = PersUnpickler(io.BytesIO(self.dumps('abc', proto))) 249 called = [] 250 self.assertEqual(unpickler.load(), 'abc') 251 self.assertEqual(called, ['abc']) 252 253 def test_pickler_instance_attribute(self): 254 def persistent_id(obj): 255 called.append(obj) 256 return obj 257 258 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 259 f = io.BytesIO() 260 pickler = self.pickler(f, proto) 261 called = [] 262 old_persistent_id = pickler.persistent_id 263 pickler.persistent_id = persistent_id 264 self.assertEqual(pickler.persistent_id, persistent_id) 265 pickler.dump('abc') 266 self.assertEqual(called, ['abc']) 267 self.assertEqual(self.loads(f.getvalue()), 'abc') 268 del pickler.persistent_id 269 self.assertEqual(pickler.persistent_id, old_persistent_id) 270 271 def test_unpickler_instance_attribute(self): 272 def persistent_load(pid): 273 called.append(pid) 274 return pid 275 276 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 277 unpickler = self.unpickler(io.BytesIO(self.dumps('abc', proto))) 278 called = [] 279 old_persistent_load = unpickler.persistent_load 280 unpickler.persistent_load = persistent_load 281 self.assertEqual(unpickler.persistent_load, persistent_load) 282 self.assertEqual(unpickler.load(), 'abc') 283 self.assertEqual(called, ['abc']) 284 del unpickler.persistent_load 285 self.assertEqual(unpickler.persistent_load, old_persistent_load) 286 287 def test_pickler_super_instance_attribute(self): 288 class PersPickler(self.pickler): 289 def persistent_id(subself, obj): 290 raise AssertionError('should never be called') 291 def _persistent_id(subself, obj): 292 called.append(obj) 293 self.assertIsNone(super().persistent_id(obj)) 294 return obj 295 296 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 297 f = io.BytesIO() 298 pickler = PersPickler(f, proto) 299 called = [] 300 old_persistent_id = pickler.persistent_id 301 pickler.persistent_id = pickler._persistent_id 302 self.assertEqual(pickler.persistent_id, pickler._persistent_id) 303 pickler.dump('abc') 304 self.assertEqual(called, ['abc']) 305 self.assertEqual(self.loads(f.getvalue()), 'abc') 306 del pickler.persistent_id 307 self.assertEqual(pickler.persistent_id, old_persistent_id) 308 309 def test_unpickler_super_instance_attribute(self): 310 class PersUnpickler(self.unpickler): 311 def persistent_load(subself, pid): 312 raise AssertionError('should never be called') 313 def _persistent_load(subself, pid): 314 called.append(pid) 315 with self.assertRaises(self.persistent_load_error): 316 super().persistent_load(pid) 317 return pid 318 319 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 320 unpickler = PersUnpickler(io.BytesIO(self.dumps('abc', proto))) 321 called = [] 322 old_persistent_load = unpickler.persistent_load 323 unpickler.persistent_load = unpickler._persistent_load 324 self.assertEqual(unpickler.persistent_load, unpickler._persistent_load) 325 self.assertEqual(unpickler.load(), 'abc') 326 self.assertEqual(called, ['abc']) 327 del unpickler.persistent_load 328 self.assertEqual(unpickler.persistent_load, old_persistent_load) 329 330 331class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests, unittest.TestCase): 332 333 pickler_class = pickle._Pickler 334 unpickler_class = pickle._Unpickler 335 336 337class PyDispatchTableTests(AbstractDispatchTableTests, unittest.TestCase): 338 339 pickler_class = pickle._Pickler 340 341 def get_dispatch_table(self): 342 return pickle.dispatch_table.copy() 343 344 345class PyChainDispatchTableTests(AbstractDispatchTableTests, unittest.TestCase): 346 347 pickler_class = pickle._Pickler 348 349 def get_dispatch_table(self): 350 return collections.ChainMap({}, pickle.dispatch_table) 351 352 353class PyPicklerHookTests(AbstractHookTests, unittest.TestCase): 354 class CustomPyPicklerClass(pickle._Pickler, 355 AbstractCustomPicklerClass): 356 pass 357 pickler_class = CustomPyPicklerClass 358 359 360if has_c_implementation: 361 class CPickleTests(AbstractPickleModuleTests, unittest.TestCase): 362 from _pickle import dump, dumps, load, loads, Pickler, Unpickler 363 364 class CUnpicklerTests(PyUnpicklerTests): 365 unpickler = _pickle.Unpickler 366 bad_stack_errors = (pickle.UnpicklingError,) 367 truncated_errors = (pickle.UnpicklingError,) 368 369 class CPicklingErrorTests(PyPicklingErrorTests): 370 pickler = _pickle.Pickler 371 372 class CPicklerTests(PyPicklerTests): 373 pickler = _pickle.Pickler 374 unpickler = _pickle.Unpickler 375 376 class CPersPicklerTests(PyPersPicklerTests): 377 pickler = _pickle.Pickler 378 unpickler = _pickle.Unpickler 379 380 class CIdPersPicklerTests(PyIdPersPicklerTests): 381 pickler = _pickle.Pickler 382 unpickler = _pickle.Unpickler 383 persistent_load_error = _pickle.UnpicklingError 384 385 class CDumpPickle_LoadPickle(PyPicklerTests): 386 pickler = _pickle.Pickler 387 unpickler = pickle._Unpickler 388 389 class DumpPickle_CLoadPickle(PyPicklerTests): 390 pickler = pickle._Pickler 391 unpickler = _pickle.Unpickler 392 393 class CPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests, unittest.TestCase): 394 pickler_class = _pickle.Pickler 395 unpickler_class = _pickle.Unpickler 396 397 def test_issue18339(self): 398 unpickler = self.unpickler_class(io.BytesIO()) 399 with self.assertRaises(TypeError): 400 unpickler.memo = object 401 # used to cause a segfault 402 with self.assertRaises(ValueError): 403 unpickler.memo = {-1: None} 404 unpickler.memo = {1: None} 405 406 class CDispatchTableTests(AbstractDispatchTableTests, unittest.TestCase): 407 pickler_class = pickle.Pickler 408 def get_dispatch_table(self): 409 return pickle.dispatch_table.copy() 410 411 class CChainDispatchTableTests(AbstractDispatchTableTests, unittest.TestCase): 412 pickler_class = pickle.Pickler 413 def get_dispatch_table(self): 414 return collections.ChainMap({}, pickle.dispatch_table) 415 416 class CPicklerHookTests(AbstractHookTests, unittest.TestCase): 417 class CustomCPicklerClass(_pickle.Pickler, AbstractCustomPicklerClass): 418 pass 419 pickler_class = CustomCPicklerClass 420 421 @support.cpython_only 422 class HeapTypesTests(unittest.TestCase): 423 def setUp(self): 424 pickler = _pickle.Pickler(io.BytesIO()) 425 unpickler = _pickle.Unpickler(io.BytesIO()) 426 427 self._types = ( 428 _pickle.Pickler, 429 _pickle.Unpickler, 430 type(pickler.memo), 431 type(unpickler.memo), 432 433 # We cannot test the _pickle.Pdata; 434 # there's no way to get to it. 435 ) 436 437 def test_have_gc(self): 438 import gc 439 for tp in self._types: 440 with self.subTest(tp=tp): 441 self.assertTrue(gc.is_tracked(tp)) 442 443 def test_immutable(self): 444 for tp in self._types: 445 with self.subTest(tp=tp): 446 with self.assertRaisesRegex(TypeError, "immutable"): 447 tp.foo = "bar" 448 449 @support.cpython_only 450 class SizeofTests(unittest.TestCase): 451 check_sizeof = support.check_sizeof 452 453 def test_pickler(self): 454 basesize = support.calcobjsize('7P2n3i2n3i2P') 455 p = _pickle.Pickler(io.BytesIO()) 456 self.assertEqual(object.__sizeof__(p), basesize) 457 MT_size = struct.calcsize('3nP0n') 458 ME_size = struct.calcsize('Pn0P') 459 check = self.check_sizeof 460 check(p, basesize + 461 MT_size + 8 * ME_size + # Minimal memo table size. 462 sys.getsizeof(b'x'*4096)) # Minimal write buffer size. 463 for i in range(6): 464 p.dump(chr(i)) 465 check(p, basesize + 466 MT_size + 32 * ME_size + # Size of memo table required to 467 # save references to 6 objects. 468 0) # Write buffer is cleared after every dump(). 469 470 def test_unpickler(self): 471 basesize = support.calcobjsize('2P2n2P 2P2n2i5P 2P3n8P2n2i') 472 unpickler = _pickle.Unpickler 473 P = struct.calcsize('P') # Size of memo table entry. 474 n = struct.calcsize('n') # Size of mark table entry. 475 check = self.check_sizeof 476 for encoding in 'ASCII', 'UTF-16', 'latin-1': 477 for errors in 'strict', 'replace': 478 u = unpickler(io.BytesIO(), 479 encoding=encoding, errors=errors) 480 self.assertEqual(object.__sizeof__(u), basesize) 481 check(u, basesize + 482 32 * P + # Minimal memo table size. 483 len(encoding) + 1 + len(errors) + 1) 484 485 stdsize = basesize + len('ASCII') + 1 + len('strict') + 1 486 def check_unpickler(data, memo_size, marks_size): 487 dump = pickle.dumps(data) 488 u = unpickler(io.BytesIO(dump), 489 encoding='ASCII', errors='strict') 490 u.load() 491 check(u, stdsize + memo_size * P + marks_size * n) 492 493 check_unpickler(0, 32, 0) 494 # 20 is minimal non-empty mark stack size. 495 check_unpickler([0] * 100, 32, 20) 496 # 128 is memo table size required to save references to 100 objects. 497 check_unpickler([chr(i) for i in range(100)], 128, 20) 498 def recurse(deep): 499 data = 0 500 for i in range(deep): 501 data = [data, data] 502 return data 503 check_unpickler(recurse(0), 32, 0) 504 check_unpickler(recurse(1), 32, 20) 505 check_unpickler(recurse(20), 32, 20) 506 check_unpickler(recurse(50), 64, 60) 507 if not (support.is_wasi and support.Py_DEBUG): 508 # stack depth too shallow in pydebug WASI. 509 check_unpickler(recurse(100), 128, 140) 510 511 u = unpickler(io.BytesIO(pickle.dumps('a', 0)), 512 encoding='ASCII', errors='strict') 513 u.load() 514 check(u, stdsize + 32 * P + 2 + 1) 515 516 517ALT_IMPORT_MAPPING = { 518 ('_elementtree', 'xml.etree.ElementTree'), 519 ('cPickle', 'pickle'), 520 ('StringIO', 'io'), 521 ('cStringIO', 'io'), 522} 523 524ALT_NAME_MAPPING = { 525 ('__builtin__', 'basestring', 'builtins', 'str'), 526 ('exceptions', 'StandardError', 'builtins', 'Exception'), 527 ('UserDict', 'UserDict', 'collections', 'UserDict'), 528 ('socket', '_socketobject', 'socket', 'SocketType'), 529} 530 531def mapping(module, name): 532 if (module, name) in NAME_MAPPING: 533 module, name = NAME_MAPPING[(module, name)] 534 elif module in IMPORT_MAPPING: 535 module = IMPORT_MAPPING[module] 536 return module, name 537 538def reverse_mapping(module, name): 539 if (module, name) in REVERSE_NAME_MAPPING: 540 module, name = REVERSE_NAME_MAPPING[(module, name)] 541 elif module in REVERSE_IMPORT_MAPPING: 542 module = REVERSE_IMPORT_MAPPING[module] 543 return module, name 544 545def getmodule(module): 546 try: 547 return sys.modules[module] 548 except KeyError: 549 try: 550 with warnings.catch_warnings(): 551 action = 'always' if support.verbose else 'ignore' 552 warnings.simplefilter(action, DeprecationWarning) 553 __import__(module) 554 except AttributeError as exc: 555 if support.verbose: 556 print("Can't import module %r: %s" % (module, exc)) 557 raise ImportError 558 except ImportError as exc: 559 if support.verbose: 560 print(exc) 561 raise 562 return sys.modules[module] 563 564def getattribute(module, name): 565 obj = getmodule(module) 566 for n in name.split('.'): 567 obj = getattr(obj, n) 568 return obj 569 570def get_exceptions(mod): 571 for name in dir(mod): 572 attr = getattr(mod, name) 573 if isinstance(attr, type) and issubclass(attr, BaseException): 574 yield name, attr 575 576class CompatPickleTests(unittest.TestCase): 577 def test_import(self): 578 modules = set(IMPORT_MAPPING.values()) 579 modules |= set(REVERSE_IMPORT_MAPPING) 580 modules |= {module for module, name in REVERSE_NAME_MAPPING} 581 modules |= {module for module, name in NAME_MAPPING.values()} 582 for module in modules: 583 try: 584 getmodule(module) 585 except ImportError: 586 pass 587 588 def test_import_mapping(self): 589 for module3, module2 in REVERSE_IMPORT_MAPPING.items(): 590 with self.subTest((module3, module2)): 591 try: 592 getmodule(module3) 593 except ImportError: 594 pass 595 if module3[:1] != '_': 596 self.assertIn(module2, IMPORT_MAPPING) 597 self.assertEqual(IMPORT_MAPPING[module2], module3) 598 599 def test_name_mapping(self): 600 for (module3, name3), (module2, name2) in REVERSE_NAME_MAPPING.items(): 601 with self.subTest(((module3, name3), (module2, name2))): 602 if (module2, name2) == ('exceptions', 'OSError'): 603 attr = getattribute(module3, name3) 604 self.assertTrue(issubclass(attr, OSError)) 605 elif (module2, name2) == ('exceptions', 'ImportError'): 606 attr = getattribute(module3, name3) 607 self.assertTrue(issubclass(attr, ImportError)) 608 else: 609 module, name = mapping(module2, name2) 610 if module3[:1] != '_': 611 self.assertEqual((module, name), (module3, name3)) 612 try: 613 attr = getattribute(module3, name3) 614 except ImportError: 615 pass 616 else: 617 self.assertEqual(getattribute(module, name), attr) 618 619 def test_reverse_import_mapping(self): 620 for module2, module3 in IMPORT_MAPPING.items(): 621 with self.subTest((module2, module3)): 622 try: 623 getmodule(module3) 624 except ImportError as exc: 625 if support.verbose: 626 print(exc) 627 if ((module2, module3) not in ALT_IMPORT_MAPPING and 628 REVERSE_IMPORT_MAPPING.get(module3, None) != module2): 629 for (m3, n3), (m2, n2) in REVERSE_NAME_MAPPING.items(): 630 if (module3, module2) == (m3, m2): 631 break 632 else: 633 self.fail('No reverse mapping from %r to %r' % 634 (module3, module2)) 635 module = REVERSE_IMPORT_MAPPING.get(module3, module3) 636 module = IMPORT_MAPPING.get(module, module) 637 self.assertEqual(module, module3) 638 639 def test_reverse_name_mapping(self): 640 for (module2, name2), (module3, name3) in NAME_MAPPING.items(): 641 with self.subTest(((module2, name2), (module3, name3))): 642 try: 643 attr = getattribute(module3, name3) 644 except ImportError: 645 pass 646 module, name = reverse_mapping(module3, name3) 647 if (module2, name2, module3, name3) not in ALT_NAME_MAPPING: 648 self.assertEqual((module, name), (module2, name2)) 649 module, name = mapping(module, name) 650 self.assertEqual((module, name), (module3, name3)) 651 652 def test_exceptions(self): 653 self.assertEqual(mapping('exceptions', 'StandardError'), 654 ('builtins', 'Exception')) 655 self.assertEqual(mapping('exceptions', 'Exception'), 656 ('builtins', 'Exception')) 657 self.assertEqual(reverse_mapping('builtins', 'Exception'), 658 ('exceptions', 'Exception')) 659 self.assertEqual(mapping('exceptions', 'OSError'), 660 ('builtins', 'OSError')) 661 self.assertEqual(reverse_mapping('builtins', 'OSError'), 662 ('exceptions', 'OSError')) 663 664 for name, exc in get_exceptions(builtins): 665 with self.subTest(name): 666 if exc in (BlockingIOError, 667 ResourceWarning, 668 StopAsyncIteration, 669 PythonFinalizationError, 670 RecursionError, 671 EncodingWarning, 672 BaseExceptionGroup, 673 ExceptionGroup, 674 _IncompleteInputError): 675 continue 676 if exc is not OSError and issubclass(exc, OSError): 677 self.assertEqual(reverse_mapping('builtins', name), 678 ('exceptions', 'OSError')) 679 elif exc is not ImportError and issubclass(exc, ImportError): 680 self.assertEqual(reverse_mapping('builtins', name), 681 ('exceptions', 'ImportError')) 682 self.assertEqual(mapping('exceptions', name), 683 ('exceptions', name)) 684 else: 685 self.assertEqual(reverse_mapping('builtins', name), 686 ('exceptions', name)) 687 self.assertEqual(mapping('exceptions', name), 688 ('builtins', name)) 689 690 def test_multiprocessing_exceptions(self): 691 module = import_helper.import_module('multiprocessing.context') 692 for name, exc in get_exceptions(module): 693 if issubclass(exc, Warning): 694 continue 695 with self.subTest(name): 696 self.assertEqual(reverse_mapping('multiprocessing.context', name), 697 ('multiprocessing', name)) 698 self.assertEqual(mapping('multiprocessing', name), 699 ('multiprocessing.context', name)) 700 701 702def load_tests(loader, tests, pattern): 703 tests.addTest(doctest.DocTestSuite()) 704 return tests 705 706 707if __name__ == "__main__": 708 unittest.main() 709