1# We import importlib *ASAP* in order to test #15386 2import importlib 3import importlib.util 4from importlib._bootstrap_external import _get_sourcefile 5import builtins 6import marshal 7import os 8import py_compile 9import random 10import shutil 11import subprocess 12import stat 13import sys 14import threading 15import time 16import unittest 17import unittest.mock as mock 18import textwrap 19import errno 20import contextlib 21import glob 22 23import test.support 24from test.support import ( 25 TESTFN, forget, is_jython, 26 make_legacy_pyc, rmtree, swap_attr, swap_item, temp_umask, 27 unlink, unload, cpython_only, TESTFN_UNENCODABLE, 28 temp_dir, DirsOnSysPath) 29from test.support import script_helper 30from test.test_importlib.util import uncache 31 32 33skip_if_dont_write_bytecode = unittest.skipIf( 34 sys.dont_write_bytecode, 35 "test meaningful only when writing bytecode") 36 37def remove_files(name): 38 for f in (name + ".py", 39 name + ".pyc", 40 name + ".pyw", 41 name + "$py.class"): 42 unlink(f) 43 rmtree('__pycache__') 44 45 46@contextlib.contextmanager 47def _ready_to_import(name=None, source=""): 48 # sets up a temporary directory and removes it 49 # creates the module file 50 # temporarily clears the module from sys.modules (if any) 51 # reverts or removes the module when cleaning up 52 name = name or "spam" 53 with temp_dir() as tempdir: 54 path = script_helper.make_script(tempdir, name, source) 55 old_module = sys.modules.pop(name, None) 56 try: 57 sys.path.insert(0, tempdir) 58 yield name, path 59 sys.path.remove(tempdir) 60 finally: 61 if old_module is not None: 62 sys.modules[name] = old_module 63 elif name in sys.modules: 64 del sys.modules[name] 65 66 67class ImportTests(unittest.TestCase): 68 69 def setUp(self): 70 remove_files(TESTFN) 71 importlib.invalidate_caches() 72 73 def tearDown(self): 74 unload(TESTFN) 75 76 def test_import_raises_ModuleNotFoundError(self): 77 with self.assertRaises(ModuleNotFoundError): 78 import something_that_should_not_exist_anywhere 79 80 def test_from_import_missing_module_raises_ModuleNotFoundError(self): 81 with self.assertRaises(ModuleNotFoundError): 82 from something_that_should_not_exist_anywhere import blah 83 84 def test_from_import_missing_attr_raises_ImportError(self): 85 with self.assertRaises(ImportError): 86 from importlib import something_that_should_not_exist_anywhere 87 88 def test_from_import_missing_attr_has_name_and_path(self): 89 with self.assertRaises(ImportError) as cm: 90 from os import i_dont_exist 91 self.assertEqual(cm.exception.name, 'os') 92 self.assertEqual(cm.exception.path, os.__file__) 93 self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from 'os' \(.*os.py\)") 94 95 @cpython_only 96 def test_from_import_missing_attr_has_name_and_so_path(self): 97 import _testcapi 98 with self.assertRaises(ImportError) as cm: 99 from _testcapi import i_dont_exist 100 self.assertEqual(cm.exception.name, '_testcapi') 101 self.assertEqual(cm.exception.path, _testcapi.__file__) 102 self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from '_testcapi' \(.*\.(so|pyd)\)") 103 104 def test_from_import_missing_attr_has_name(self): 105 with self.assertRaises(ImportError) as cm: 106 # _warning has no path as it's a built-in module. 107 from _warning import i_dont_exist 108 self.assertEqual(cm.exception.name, '_warning') 109 self.assertIsNone(cm.exception.path) 110 111 def test_from_import_missing_attr_path_is_canonical(self): 112 with self.assertRaises(ImportError) as cm: 113 from os.path import i_dont_exist 114 self.assertIn(cm.exception.name, {'posixpath', 'ntpath'}) 115 self.assertIsNotNone(cm.exception) 116 117 def test_from_import_star_invalid_type(self): 118 import re 119 with _ready_to_import() as (name, path): 120 with open(path, 'w') as f: 121 f.write("__all__ = [b'invalid_type']") 122 globals = {} 123 with self.assertRaisesRegex( 124 TypeError, f"{re.escape(name)}\\.__all__ must be str" 125 ): 126 exec(f"from {name} import *", globals) 127 self.assertNotIn(b"invalid_type", globals) 128 with _ready_to_import() as (name, path): 129 with open(path, 'w') as f: 130 f.write("globals()[b'invalid_type'] = object()") 131 globals = {} 132 with self.assertRaisesRegex( 133 TypeError, f"{re.escape(name)}\\.__dict__ must be str" 134 ): 135 exec(f"from {name} import *", globals) 136 self.assertNotIn(b"invalid_type", globals) 137 138 def test_case_sensitivity(self): 139 # Brief digression to test that import is case-sensitive: if we got 140 # this far, we know for sure that "random" exists. 141 with self.assertRaises(ImportError): 142 import RAnDoM 143 144 def test_double_const(self): 145 # Another brief digression to test the accuracy of manifest float 146 # constants. 147 from test import double_const # don't blink -- that *was* the test 148 149 def test_import(self): 150 def test_with_extension(ext): 151 # The extension is normally ".py", perhaps ".pyw". 152 source = TESTFN + ext 153 if is_jython: 154 pyc = TESTFN + "$py.class" 155 else: 156 pyc = TESTFN + ".pyc" 157 158 with open(source, "w") as f: 159 print("# This tests Python's ability to import a", 160 ext, "file.", file=f) 161 a = random.randrange(1000) 162 b = random.randrange(1000) 163 print("a =", a, file=f) 164 print("b =", b, file=f) 165 166 if TESTFN in sys.modules: 167 del sys.modules[TESTFN] 168 importlib.invalidate_caches() 169 try: 170 try: 171 mod = __import__(TESTFN) 172 except ImportError as err: 173 self.fail("import from %s failed: %s" % (ext, err)) 174 175 self.assertEqual(mod.a, a, 176 "module loaded (%s) but contents invalid" % mod) 177 self.assertEqual(mod.b, b, 178 "module loaded (%s) but contents invalid" % mod) 179 finally: 180 forget(TESTFN) 181 unlink(source) 182 unlink(pyc) 183 184 sys.path.insert(0, os.curdir) 185 try: 186 test_with_extension(".py") 187 if sys.platform.startswith("win"): 188 for ext in [".PY", ".Py", ".pY", ".pyw", ".PYW", ".pYw"]: 189 test_with_extension(ext) 190 finally: 191 del sys.path[0] 192 193 def test_module_with_large_stack(self, module='longlist'): 194 # Regression test for http://bugs.python.org/issue561858. 195 filename = module + '.py' 196 197 # Create a file with a list of 65000 elements. 198 with open(filename, 'w') as f: 199 f.write('d = [\n') 200 for i in range(65000): 201 f.write('"",\n') 202 f.write(']') 203 204 try: 205 # Compile & remove .py file; we only need .pyc. 206 # Bytecode must be relocated from the PEP 3147 bytecode-only location. 207 py_compile.compile(filename) 208 finally: 209 unlink(filename) 210 211 # Need to be able to load from current dir. 212 sys.path.append('') 213 importlib.invalidate_caches() 214 215 namespace = {} 216 try: 217 make_legacy_pyc(filename) 218 # This used to crash. 219 exec('import ' + module, None, namespace) 220 finally: 221 # Cleanup. 222 del sys.path[-1] 223 unlink(filename + 'c') 224 unlink(filename + 'o') 225 226 # Remove references to the module (unload the module) 227 namespace.clear() 228 try: 229 del sys.modules[module] 230 except KeyError: 231 pass 232 233 def test_failing_import_sticks(self): 234 source = TESTFN + ".py" 235 with open(source, "w") as f: 236 print("a = 1/0", file=f) 237 238 # New in 2.4, we shouldn't be able to import that no matter how often 239 # we try. 240 sys.path.insert(0, os.curdir) 241 importlib.invalidate_caches() 242 if TESTFN in sys.modules: 243 del sys.modules[TESTFN] 244 try: 245 for i in [1, 2, 3]: 246 self.assertRaises(ZeroDivisionError, __import__, TESTFN) 247 self.assertNotIn(TESTFN, sys.modules, 248 "damaged module in sys.modules on %i try" % i) 249 finally: 250 del sys.path[0] 251 remove_files(TESTFN) 252 253 def test_import_name_binding(self): 254 # import x.y.z binds x in the current namespace 255 import test as x 256 import test.support 257 self.assertIs(x, test, x.__name__) 258 self.assertTrue(hasattr(test.support, "__file__")) 259 260 # import x.y.z as w binds z as w 261 import test.support as y 262 self.assertIs(y, test.support, y.__name__) 263 264 def test_issue31286(self): 265 # import in a 'finally' block resulted in SystemError 266 try: 267 x = ... 268 finally: 269 import test.support.script_helper as x 270 271 # import in a 'while' loop resulted in stack overflow 272 i = 0 273 while i < 10: 274 import test.support.script_helper as x 275 i += 1 276 277 # import in a 'for' loop resulted in segmentation fault 278 for i in range(2): 279 import test.support.script_helper as x 280 281 def test_failing_reload(self): 282 # A failing reload should leave the module object in sys.modules. 283 source = TESTFN + os.extsep + "py" 284 with open(source, "w") as f: 285 f.write("a = 1\nb=2\n") 286 287 sys.path.insert(0, os.curdir) 288 try: 289 mod = __import__(TESTFN) 290 self.assertIn(TESTFN, sys.modules) 291 self.assertEqual(mod.a, 1, "module has wrong attribute values") 292 self.assertEqual(mod.b, 2, "module has wrong attribute values") 293 294 # On WinXP, just replacing the .py file wasn't enough to 295 # convince reload() to reparse it. Maybe the timestamp didn't 296 # move enough. We force it to get reparsed by removing the 297 # compiled file too. 298 remove_files(TESTFN) 299 300 # Now damage the module. 301 with open(source, "w") as f: 302 f.write("a = 10\nb=20//0\n") 303 304 self.assertRaises(ZeroDivisionError, importlib.reload, mod) 305 # But we still expect the module to be in sys.modules. 306 mod = sys.modules.get(TESTFN) 307 self.assertIsNotNone(mod, "expected module to be in sys.modules") 308 309 # We should have replaced a w/ 10, but the old b value should 310 # stick. 311 self.assertEqual(mod.a, 10, "module has wrong attribute values") 312 self.assertEqual(mod.b, 2, "module has wrong attribute values") 313 314 finally: 315 del sys.path[0] 316 remove_files(TESTFN) 317 unload(TESTFN) 318 319 @skip_if_dont_write_bytecode 320 def test_file_to_source(self): 321 # check if __file__ points to the source file where available 322 source = TESTFN + ".py" 323 with open(source, "w") as f: 324 f.write("test = None\n") 325 326 sys.path.insert(0, os.curdir) 327 try: 328 mod = __import__(TESTFN) 329 self.assertTrue(mod.__file__.endswith('.py')) 330 os.remove(source) 331 del sys.modules[TESTFN] 332 make_legacy_pyc(source) 333 importlib.invalidate_caches() 334 mod = __import__(TESTFN) 335 base, ext = os.path.splitext(mod.__file__) 336 self.assertEqual(ext, '.pyc') 337 finally: 338 del sys.path[0] 339 remove_files(TESTFN) 340 if TESTFN in sys.modules: 341 del sys.modules[TESTFN] 342 343 def test_import_by_filename(self): 344 path = os.path.abspath(TESTFN) 345 encoding = sys.getfilesystemencoding() 346 try: 347 path.encode(encoding) 348 except UnicodeEncodeError: 349 self.skipTest('path is not encodable to {}'.format(encoding)) 350 with self.assertRaises(ImportError) as c: 351 __import__(path) 352 353 def test_import_in_del_does_not_crash(self): 354 # Issue 4236 355 testfn = script_helper.make_script('', TESTFN, textwrap.dedent("""\ 356 import sys 357 class C: 358 def __del__(self): 359 import importlib 360 sys.argv.insert(0, C()) 361 """)) 362 script_helper.assert_python_ok(testfn) 363 364 @skip_if_dont_write_bytecode 365 def test_timestamp_overflow(self): 366 # A modification timestamp larger than 2**32 should not be a problem 367 # when importing a module (issue #11235). 368 sys.path.insert(0, os.curdir) 369 try: 370 source = TESTFN + ".py" 371 compiled = importlib.util.cache_from_source(source) 372 with open(source, 'w') as f: 373 pass 374 try: 375 os.utime(source, (2 ** 33 - 5, 2 ** 33 - 5)) 376 except OverflowError: 377 self.skipTest("cannot set modification time to large integer") 378 except OSError as e: 379 if e.errno not in (getattr(errno, 'EOVERFLOW', None), 380 getattr(errno, 'EINVAL', None)): 381 raise 382 self.skipTest("cannot set modification time to large integer ({})".format(e)) 383 __import__(TESTFN) 384 # The pyc file was created. 385 os.stat(compiled) 386 finally: 387 del sys.path[0] 388 remove_files(TESTFN) 389 390 def test_bogus_fromlist(self): 391 try: 392 __import__('http', fromlist=['blah']) 393 except ImportError: 394 self.fail("fromlist must allow bogus names") 395 396 @cpython_only 397 def test_delete_builtins_import(self): 398 args = ["-c", "del __builtins__.__import__; import os"] 399 popen = script_helper.spawn_python(*args) 400 stdout, stderr = popen.communicate() 401 self.assertIn(b"ImportError", stdout) 402 403 def test_from_import_message_for_nonexistent_module(self): 404 with self.assertRaisesRegex(ImportError, "^No module named 'bogus'"): 405 from bogus import foo 406 407 def test_from_import_message_for_existing_module(self): 408 with self.assertRaisesRegex(ImportError, "^cannot import name 'bogus'"): 409 from re import bogus 410 411 def test_from_import_AttributeError(self): 412 # Issue #24492: trying to import an attribute that raises an 413 # AttributeError should lead to an ImportError. 414 class AlwaysAttributeError: 415 def __getattr__(self, _): 416 raise AttributeError 417 418 module_name = 'test_from_import_AttributeError' 419 self.addCleanup(unload, module_name) 420 sys.modules[module_name] = AlwaysAttributeError() 421 with self.assertRaises(ImportError) as cm: 422 from test_from_import_AttributeError import does_not_exist 423 424 self.assertEqual(str(cm.exception), 425 "cannot import name 'does_not_exist' from '<unknown module name>' (unknown location)") 426 427 @cpython_only 428 def test_issue31492(self): 429 # There shouldn't be an assertion failure in case of failing to import 430 # from a module with a bad __name__ attribute, or in case of failing 431 # to access an attribute of such a module. 432 with swap_attr(os, '__name__', None): 433 with self.assertRaises(ImportError): 434 from os import does_not_exist 435 436 with self.assertRaises(AttributeError): 437 os.does_not_exist 438 439 def test_concurrency(self): 440 sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'data')) 441 try: 442 exc = None 443 def run(): 444 event.wait() 445 try: 446 import package 447 except BaseException as e: 448 nonlocal exc 449 exc = e 450 451 for i in range(10): 452 event = threading.Event() 453 threads = [threading.Thread(target=run) for x in range(2)] 454 try: 455 with test.support.start_threads(threads, event.set): 456 time.sleep(0) 457 finally: 458 sys.modules.pop('package', None) 459 sys.modules.pop('package.submodule', None) 460 if exc is not None: 461 raise exc 462 finally: 463 del sys.path[0] 464 465 @unittest.skipUnless(sys.platform == "win32", "Windows-specific") 466 def test_dll_dependency_import(self): 467 from _winapi import GetModuleFileName 468 dllname = GetModuleFileName(sys.dllhandle) 469 pydname = importlib.util.find_spec("_sqlite3").origin 470 depname = os.path.join( 471 os.path.dirname(pydname), 472 "sqlite3{}.dll".format("_d" if "_d" in pydname else "")) 473 474 with test.support.temp_dir() as tmp: 475 tmp2 = os.path.join(tmp, "DLLs") 476 os.mkdir(tmp2) 477 478 pyexe = os.path.join(tmp, os.path.basename(sys.executable)) 479 shutil.copy(sys.executable, pyexe) 480 shutil.copy(dllname, tmp) 481 for f in glob.glob(os.path.join(glob.escape(sys.prefix), "vcruntime*.dll")): 482 shutil.copy(f, tmp) 483 484 shutil.copy(pydname, tmp2) 485 486 env = None 487 env = {k.upper(): os.environ[k] for k in os.environ} 488 env["PYTHONPATH"] = tmp2 + ";" + os.path.dirname(os.__file__) 489 490 # Test 1: import with added DLL directory 491 subprocess.check_call([ 492 pyexe, "-Sc", ";".join([ 493 "import os", 494 "p = os.add_dll_directory({!r})".format( 495 os.path.dirname(depname)), 496 "import _sqlite3", 497 "p.close" 498 ])], 499 stderr=subprocess.STDOUT, 500 env=env, 501 cwd=os.path.dirname(pyexe)) 502 503 # Test 2: import with DLL adjacent to PYD 504 shutil.copy(depname, tmp2) 505 subprocess.check_call([pyexe, "-Sc", "import _sqlite3"], 506 stderr=subprocess.STDOUT, 507 env=env, 508 cwd=os.path.dirname(pyexe)) 509 510 511@skip_if_dont_write_bytecode 512class FilePermissionTests(unittest.TestCase): 513 # tests for file mode on cached .pyc files 514 515 @unittest.skipUnless(os.name == 'posix', 516 "test meaningful only on posix systems") 517 def test_creation_mode(self): 518 mask = 0o022 519 with temp_umask(mask), _ready_to_import() as (name, path): 520 cached_path = importlib.util.cache_from_source(path) 521 module = __import__(name) 522 if not os.path.exists(cached_path): 523 self.fail("__import__ did not result in creation of " 524 "a .pyc file") 525 stat_info = os.stat(cached_path) 526 527 # Check that the umask is respected, and the executable bits 528 # aren't set. 529 self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), 530 oct(0o666 & ~mask)) 531 532 @unittest.skipUnless(os.name == 'posix', 533 "test meaningful only on posix systems") 534 def test_cached_mode_issue_2051(self): 535 # permissions of .pyc should match those of .py, regardless of mask 536 mode = 0o600 537 with temp_umask(0o022), _ready_to_import() as (name, path): 538 cached_path = importlib.util.cache_from_source(path) 539 os.chmod(path, mode) 540 __import__(name) 541 if not os.path.exists(cached_path): 542 self.fail("__import__ did not result in creation of " 543 "a .pyc file") 544 stat_info = os.stat(cached_path) 545 546 self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(mode)) 547 548 @unittest.skipUnless(os.name == 'posix', 549 "test meaningful only on posix systems") 550 def test_cached_readonly(self): 551 mode = 0o400 552 with temp_umask(0o022), _ready_to_import() as (name, path): 553 cached_path = importlib.util.cache_from_source(path) 554 os.chmod(path, mode) 555 __import__(name) 556 if not os.path.exists(cached_path): 557 self.fail("__import__ did not result in creation of " 558 "a .pyc file") 559 stat_info = os.stat(cached_path) 560 561 expected = mode | 0o200 # Account for fix for issue #6074 562 self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(expected)) 563 564 def test_pyc_always_writable(self): 565 # Initially read-only .pyc files on Windows used to cause problems 566 # with later updates, see issue #6074 for details 567 with _ready_to_import() as (name, path): 568 # Write a Python file, make it read-only and import it 569 with open(path, 'w') as f: 570 f.write("x = 'original'\n") 571 # Tweak the mtime of the source to ensure pyc gets updated later 572 s = os.stat(path) 573 os.utime(path, (s.st_atime, s.st_mtime-100000000)) 574 os.chmod(path, 0o400) 575 m = __import__(name) 576 self.assertEqual(m.x, 'original') 577 # Change the file and then reimport it 578 os.chmod(path, 0o600) 579 with open(path, 'w') as f: 580 f.write("x = 'rewritten'\n") 581 unload(name) 582 importlib.invalidate_caches() 583 m = __import__(name) 584 self.assertEqual(m.x, 'rewritten') 585 # Now delete the source file and check the pyc was rewritten 586 unlink(path) 587 unload(name) 588 importlib.invalidate_caches() 589 bytecode_only = path + "c" 590 os.rename(importlib.util.cache_from_source(path), bytecode_only) 591 m = __import__(name) 592 self.assertEqual(m.x, 'rewritten') 593 594 595class PycRewritingTests(unittest.TestCase): 596 # Test that the `co_filename` attribute on code objects always points 597 # to the right file, even when various things happen (e.g. both the .py 598 # and the .pyc file are renamed). 599 600 module_name = "unlikely_module_name" 601 module_source = """ 602import sys 603code_filename = sys._getframe().f_code.co_filename 604module_filename = __file__ 605constant = 1 606def func(): 607 pass 608func_filename = func.__code__.co_filename 609""" 610 dir_name = os.path.abspath(TESTFN) 611 file_name = os.path.join(dir_name, module_name) + os.extsep + "py" 612 compiled_name = importlib.util.cache_from_source(file_name) 613 614 def setUp(self): 615 self.sys_path = sys.path[:] 616 self.orig_module = sys.modules.pop(self.module_name, None) 617 os.mkdir(self.dir_name) 618 with open(self.file_name, "w") as f: 619 f.write(self.module_source) 620 sys.path.insert(0, self.dir_name) 621 importlib.invalidate_caches() 622 623 def tearDown(self): 624 sys.path[:] = self.sys_path 625 if self.orig_module is not None: 626 sys.modules[self.module_name] = self.orig_module 627 else: 628 unload(self.module_name) 629 unlink(self.file_name) 630 unlink(self.compiled_name) 631 rmtree(self.dir_name) 632 633 def import_module(self): 634 ns = globals() 635 __import__(self.module_name, ns, ns) 636 return sys.modules[self.module_name] 637 638 def test_basics(self): 639 mod = self.import_module() 640 self.assertEqual(mod.module_filename, self.file_name) 641 self.assertEqual(mod.code_filename, self.file_name) 642 self.assertEqual(mod.func_filename, self.file_name) 643 del sys.modules[self.module_name] 644 mod = self.import_module() 645 self.assertEqual(mod.module_filename, self.file_name) 646 self.assertEqual(mod.code_filename, self.file_name) 647 self.assertEqual(mod.func_filename, self.file_name) 648 649 def test_incorrect_code_name(self): 650 py_compile.compile(self.file_name, dfile="another_module.py") 651 mod = self.import_module() 652 self.assertEqual(mod.module_filename, self.file_name) 653 self.assertEqual(mod.code_filename, self.file_name) 654 self.assertEqual(mod.func_filename, self.file_name) 655 656 def test_module_without_source(self): 657 target = "another_module.py" 658 py_compile.compile(self.file_name, dfile=target) 659 os.remove(self.file_name) 660 pyc_file = make_legacy_pyc(self.file_name) 661 importlib.invalidate_caches() 662 mod = self.import_module() 663 self.assertEqual(mod.module_filename, pyc_file) 664 self.assertEqual(mod.code_filename, target) 665 self.assertEqual(mod.func_filename, target) 666 667 def test_foreign_code(self): 668 py_compile.compile(self.file_name) 669 with open(self.compiled_name, "rb") as f: 670 header = f.read(16) 671 code = marshal.load(f) 672 constants = list(code.co_consts) 673 foreign_code = importlib.import_module.__code__ 674 pos = constants.index(1) 675 constants[pos] = foreign_code 676 code = code.replace(co_consts=tuple(constants)) 677 with open(self.compiled_name, "wb") as f: 678 f.write(header) 679 marshal.dump(code, f) 680 mod = self.import_module() 681 self.assertEqual(mod.constant.co_filename, foreign_code.co_filename) 682 683 684class PathsTests(unittest.TestCase): 685 SAMPLES = ('test', 'test\u00e4\u00f6\u00fc\u00df', 'test\u00e9\u00e8', 686 'test\u00b0\u00b3\u00b2') 687 path = TESTFN 688 689 def setUp(self): 690 os.mkdir(self.path) 691 self.syspath = sys.path[:] 692 693 def tearDown(self): 694 rmtree(self.path) 695 sys.path[:] = self.syspath 696 697 # Regression test for http://bugs.python.org/issue1293. 698 def test_trailing_slash(self): 699 with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f: 700 f.write("testdata = 'test_trailing_slash'") 701 sys.path.append(self.path+'/') 702 mod = __import__("test_trailing_slash") 703 self.assertEqual(mod.testdata, 'test_trailing_slash') 704 unload("test_trailing_slash") 705 706 # Regression test for http://bugs.python.org/issue3677. 707 @unittest.skipUnless(sys.platform == 'win32', 'Windows-specific') 708 def test_UNC_path(self): 709 with open(os.path.join(self.path, 'test_unc_path.py'), 'w') as f: 710 f.write("testdata = 'test_unc_path'") 711 importlib.invalidate_caches() 712 # Create the UNC path, like \\myhost\c$\foo\bar. 713 path = os.path.abspath(self.path) 714 import socket 715 hn = socket.gethostname() 716 drive = path[0] 717 unc = "\\\\%s\\%s$"%(hn, drive) 718 unc += path[2:] 719 try: 720 os.listdir(unc) 721 except OSError as e: 722 if e.errno in (errno.EPERM, errno.EACCES, errno.ENOENT): 723 # See issue #15338 724 self.skipTest("cannot access administrative share %r" % (unc,)) 725 raise 726 sys.path.insert(0, unc) 727 try: 728 mod = __import__("test_unc_path") 729 except ImportError as e: 730 self.fail("could not import 'test_unc_path' from %r: %r" 731 % (unc, e)) 732 self.assertEqual(mod.testdata, 'test_unc_path') 733 self.assertTrue(mod.__file__.startswith(unc), mod.__file__) 734 unload("test_unc_path") 735 736 737class RelativeImportTests(unittest.TestCase): 738 739 def tearDown(self): 740 unload("test.relimport") 741 setUp = tearDown 742 743 def test_relimport_star(self): 744 # This will import * from .test_import. 745 from .. import relimport 746 self.assertTrue(hasattr(relimport, "RelativeImportTests")) 747 748 def test_issue3221(self): 749 # Note for mergers: the 'absolute' tests from the 2.x branch 750 # are missing in Py3k because implicit relative imports are 751 # a thing of the past 752 # 753 # Regression test for http://bugs.python.org/issue3221. 754 def check_relative(): 755 exec("from . import relimport", ns) 756 757 # Check relative import OK with __package__ and __name__ correct 758 ns = dict(__package__='test', __name__='test.notarealmodule') 759 check_relative() 760 761 # Check relative import OK with only __name__ wrong 762 ns = dict(__package__='test', __name__='notarealpkg.notarealmodule') 763 check_relative() 764 765 # Check relative import fails with only __package__ wrong 766 ns = dict(__package__='foo', __name__='test.notarealmodule') 767 self.assertRaises(ModuleNotFoundError, check_relative) 768 769 # Check relative import fails with __package__ and __name__ wrong 770 ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule') 771 self.assertRaises(ModuleNotFoundError, check_relative) 772 773 # Check relative import fails with package set to a non-string 774 ns = dict(__package__=object()) 775 self.assertRaises(TypeError, check_relative) 776 777 def test_parentless_import_shadowed_by_global(self): 778 # Test as if this were done from the REPL where this error most commonly occurs (bpo-37409). 779 script_helper.assert_python_failure('-W', 'ignore', '-c', 780 "foo = 1; from . import foo") 781 782 def test_absolute_import_without_future(self): 783 # If explicit relative import syntax is used, then do not try 784 # to perform an absolute import in the face of failure. 785 # Issue #7902. 786 with self.assertRaises(ImportError): 787 from .os import sep 788 self.fail("explicit relative import triggered an " 789 "implicit absolute import") 790 791 def test_import_from_non_package(self): 792 path = os.path.join(os.path.dirname(__file__), 'data', 'package2') 793 with uncache('submodule1', 'submodule2'), DirsOnSysPath(path): 794 with self.assertRaises(ImportError): 795 import submodule1 796 self.assertNotIn('submodule1', sys.modules) 797 self.assertNotIn('submodule2', sys.modules) 798 799 def test_import_from_unloaded_package(self): 800 with uncache('package2', 'package2.submodule1', 'package2.submodule2'), \ 801 DirsOnSysPath(os.path.join(os.path.dirname(__file__), 'data')): 802 import package2.submodule1 803 package2.submodule1.submodule2 804 805 806class OverridingImportBuiltinTests(unittest.TestCase): 807 def test_override_builtin(self): 808 # Test that overriding builtins.__import__ can bypass sys.modules. 809 import os 810 811 def foo(): 812 import os 813 return os 814 self.assertEqual(foo(), os) # Quick sanity check. 815 816 with swap_attr(builtins, "__import__", lambda *x: 5): 817 self.assertEqual(foo(), 5) 818 819 # Test what happens when we shadow __import__ in globals(); this 820 # currently does not impact the import process, but if this changes, 821 # other code will need to change, so keep this test as a tripwire. 822 with swap_item(globals(), "__import__", lambda *x: 5): 823 self.assertEqual(foo(), os) 824 825 826class PycacheTests(unittest.TestCase): 827 # Test the various PEP 3147/488-related behaviors. 828 829 def _clean(self): 830 forget(TESTFN) 831 rmtree('__pycache__') 832 unlink(self.source) 833 834 def setUp(self): 835 self.source = TESTFN + '.py' 836 self._clean() 837 with open(self.source, 'w') as fp: 838 print('# This is a test file written by test_import.py', file=fp) 839 sys.path.insert(0, os.curdir) 840 importlib.invalidate_caches() 841 842 def tearDown(self): 843 assert sys.path[0] == os.curdir, 'Unexpected sys.path[0]' 844 del sys.path[0] 845 self._clean() 846 847 @skip_if_dont_write_bytecode 848 def test_import_pyc_path(self): 849 self.assertFalse(os.path.exists('__pycache__')) 850 __import__(TESTFN) 851 self.assertTrue(os.path.exists('__pycache__')) 852 pyc_path = importlib.util.cache_from_source(self.source) 853 self.assertTrue(os.path.exists(pyc_path), 854 'bytecode file {!r} for {!r} does not ' 855 'exist'.format(pyc_path, TESTFN)) 856 857 @unittest.skipUnless(os.name == 'posix', 858 "test meaningful only on posix systems") 859 @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0, 860 "due to varying filesystem permission semantics (issue #11956)") 861 @skip_if_dont_write_bytecode 862 def test_unwritable_directory(self): 863 # When the umask causes the new __pycache__ directory to be 864 # unwritable, the import still succeeds but no .pyc file is written. 865 with temp_umask(0o222): 866 __import__(TESTFN) 867 self.assertTrue(os.path.exists('__pycache__')) 868 pyc_path = importlib.util.cache_from_source(self.source) 869 self.assertFalse(os.path.exists(pyc_path), 870 'bytecode file {!r} for {!r} ' 871 'exists'.format(pyc_path, TESTFN)) 872 873 @skip_if_dont_write_bytecode 874 def test_missing_source(self): 875 # With PEP 3147 cache layout, removing the source but leaving the pyc 876 # file does not satisfy the import. 877 __import__(TESTFN) 878 pyc_file = importlib.util.cache_from_source(self.source) 879 self.assertTrue(os.path.exists(pyc_file)) 880 os.remove(self.source) 881 forget(TESTFN) 882 importlib.invalidate_caches() 883 self.assertRaises(ImportError, __import__, TESTFN) 884 885 @skip_if_dont_write_bytecode 886 def test_missing_source_legacy(self): 887 # Like test_missing_source() except that for backward compatibility, 888 # when the pyc file lives where the py file would have been (and named 889 # without the tag), it is importable. The __file__ of the imported 890 # module is the pyc location. 891 __import__(TESTFN) 892 # pyc_file gets removed in _clean() via tearDown(). 893 pyc_file = make_legacy_pyc(self.source) 894 os.remove(self.source) 895 unload(TESTFN) 896 importlib.invalidate_caches() 897 m = __import__(TESTFN) 898 try: 899 self.assertEqual(m.__file__, 900 os.path.join(os.curdir, os.path.relpath(pyc_file))) 901 finally: 902 os.remove(pyc_file) 903 904 def test___cached__(self): 905 # Modules now also have an __cached__ that points to the pyc file. 906 m = __import__(TESTFN) 907 pyc_file = importlib.util.cache_from_source(TESTFN + '.py') 908 self.assertEqual(m.__cached__, os.path.join(os.curdir, pyc_file)) 909 910 @skip_if_dont_write_bytecode 911 def test___cached___legacy_pyc(self): 912 # Like test___cached__() except that for backward compatibility, 913 # when the pyc file lives where the py file would have been (and named 914 # without the tag), it is importable. The __cached__ of the imported 915 # module is the pyc location. 916 __import__(TESTFN) 917 # pyc_file gets removed in _clean() via tearDown(). 918 pyc_file = make_legacy_pyc(self.source) 919 os.remove(self.source) 920 unload(TESTFN) 921 importlib.invalidate_caches() 922 m = __import__(TESTFN) 923 self.assertEqual(m.__cached__, 924 os.path.join(os.curdir, os.path.relpath(pyc_file))) 925 926 @skip_if_dont_write_bytecode 927 def test_package___cached__(self): 928 # Like test___cached__ but for packages. 929 def cleanup(): 930 rmtree('pep3147') 931 unload('pep3147.foo') 932 unload('pep3147') 933 os.mkdir('pep3147') 934 self.addCleanup(cleanup) 935 # Touch the __init__.py 936 with open(os.path.join('pep3147', '__init__.py'), 'w'): 937 pass 938 with open(os.path.join('pep3147', 'foo.py'), 'w'): 939 pass 940 importlib.invalidate_caches() 941 m = __import__('pep3147.foo') 942 init_pyc = importlib.util.cache_from_source( 943 os.path.join('pep3147', '__init__.py')) 944 self.assertEqual(m.__cached__, os.path.join(os.curdir, init_pyc)) 945 foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py')) 946 self.assertEqual(sys.modules['pep3147.foo'].__cached__, 947 os.path.join(os.curdir, foo_pyc)) 948 949 def test_package___cached___from_pyc(self): 950 # Like test___cached__ but ensuring __cached__ when imported from a 951 # PEP 3147 pyc file. 952 def cleanup(): 953 rmtree('pep3147') 954 unload('pep3147.foo') 955 unload('pep3147') 956 os.mkdir('pep3147') 957 self.addCleanup(cleanup) 958 # Touch the __init__.py 959 with open(os.path.join('pep3147', '__init__.py'), 'w'): 960 pass 961 with open(os.path.join('pep3147', 'foo.py'), 'w'): 962 pass 963 importlib.invalidate_caches() 964 m = __import__('pep3147.foo') 965 unload('pep3147.foo') 966 unload('pep3147') 967 importlib.invalidate_caches() 968 m = __import__('pep3147.foo') 969 init_pyc = importlib.util.cache_from_source( 970 os.path.join('pep3147', '__init__.py')) 971 self.assertEqual(m.__cached__, os.path.join(os.curdir, init_pyc)) 972 foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py')) 973 self.assertEqual(sys.modules['pep3147.foo'].__cached__, 974 os.path.join(os.curdir, foo_pyc)) 975 976 def test_recompute_pyc_same_second(self): 977 # Even when the source file doesn't change timestamp, a change in 978 # source size is enough to trigger recomputation of the pyc file. 979 __import__(TESTFN) 980 unload(TESTFN) 981 with open(self.source, 'a') as fp: 982 print("x = 5", file=fp) 983 m = __import__(TESTFN) 984 self.assertEqual(m.x, 5) 985 986 987class TestSymbolicallyLinkedPackage(unittest.TestCase): 988 package_name = 'sample' 989 tagged = package_name + '-tagged' 990 991 def setUp(self): 992 test.support.rmtree(self.tagged) 993 test.support.rmtree(self.package_name) 994 self.orig_sys_path = sys.path[:] 995 996 # create a sample package; imagine you have a package with a tag and 997 # you want to symbolically link it from its untagged name. 998 os.mkdir(self.tagged) 999 self.addCleanup(test.support.rmtree, self.tagged) 1000 init_file = os.path.join(self.tagged, '__init__.py') 1001 test.support.create_empty_file(init_file) 1002 assert os.path.exists(init_file) 1003 1004 # now create a symlink to the tagged package 1005 # sample -> sample-tagged 1006 os.symlink(self.tagged, self.package_name, target_is_directory=True) 1007 self.addCleanup(test.support.unlink, self.package_name) 1008 importlib.invalidate_caches() 1009 1010 self.assertEqual(os.path.isdir(self.package_name), True) 1011 1012 assert os.path.isfile(os.path.join(self.package_name, '__init__.py')) 1013 1014 def tearDown(self): 1015 sys.path[:] = self.orig_sys_path 1016 1017 # regression test for issue6727 1018 @unittest.skipUnless( 1019 not hasattr(sys, 'getwindowsversion') 1020 or sys.getwindowsversion() >= (6, 0), 1021 "Windows Vista or later required") 1022 @test.support.skip_unless_symlink 1023 def test_symlinked_dir_importable(self): 1024 # make sure sample can only be imported from the current directory. 1025 sys.path[:] = ['.'] 1026 assert os.path.exists(self.package_name) 1027 assert os.path.exists(os.path.join(self.package_name, '__init__.py')) 1028 1029 # Try to import the package 1030 importlib.import_module(self.package_name) 1031 1032 1033@cpython_only 1034class ImportlibBootstrapTests(unittest.TestCase): 1035 # These tests check that importlib is bootstrapped. 1036 1037 def test_frozen_importlib(self): 1038 mod = sys.modules['_frozen_importlib'] 1039 self.assertTrue(mod) 1040 1041 def test_frozen_importlib_is_bootstrap(self): 1042 from importlib import _bootstrap 1043 mod = sys.modules['_frozen_importlib'] 1044 self.assertIs(mod, _bootstrap) 1045 self.assertEqual(mod.__name__, 'importlib._bootstrap') 1046 self.assertEqual(mod.__package__, 'importlib') 1047 self.assertTrue(mod.__file__.endswith('_bootstrap.py'), mod.__file__) 1048 1049 def test_frozen_importlib_external_is_bootstrap_external(self): 1050 from importlib import _bootstrap_external 1051 mod = sys.modules['_frozen_importlib_external'] 1052 self.assertIs(mod, _bootstrap_external) 1053 self.assertEqual(mod.__name__, 'importlib._bootstrap_external') 1054 self.assertEqual(mod.__package__, 'importlib') 1055 self.assertTrue(mod.__file__.endswith('_bootstrap_external.py'), mod.__file__) 1056 1057 def test_there_can_be_only_one(self): 1058 # Issue #15386 revealed a tricky loophole in the bootstrapping 1059 # This test is technically redundant, since the bug caused importing 1060 # this test module to crash completely, but it helps prove the point 1061 from importlib import machinery 1062 mod = sys.modules['_frozen_importlib'] 1063 self.assertIs(machinery.ModuleSpec, mod.ModuleSpec) 1064 1065 1066@cpython_only 1067class GetSourcefileTests(unittest.TestCase): 1068 1069 """Test importlib._bootstrap_external._get_sourcefile() as used by the C API. 1070 1071 Because of the peculiarities of the need of this function, the tests are 1072 knowingly whitebox tests. 1073 1074 """ 1075 1076 def test_get_sourcefile(self): 1077 # Given a valid bytecode path, return the path to the corresponding 1078 # source file if it exists. 1079 with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: 1080 _path_isfile.return_value = True; 1081 path = TESTFN + '.pyc' 1082 expect = TESTFN + '.py' 1083 self.assertEqual(_get_sourcefile(path), expect) 1084 1085 def test_get_sourcefile_no_source(self): 1086 # Given a valid bytecode path without a corresponding source path, 1087 # return the original bytecode path. 1088 with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: 1089 _path_isfile.return_value = False; 1090 path = TESTFN + '.pyc' 1091 self.assertEqual(_get_sourcefile(path), path) 1092 1093 def test_get_sourcefile_bad_ext(self): 1094 # Given a path with an invalid bytecode extension, return the 1095 # bytecode path passed as the argument. 1096 path = TESTFN + '.bad_ext' 1097 self.assertEqual(_get_sourcefile(path), path) 1098 1099 1100class ImportTracebackTests(unittest.TestCase): 1101 1102 def setUp(self): 1103 os.mkdir(TESTFN) 1104 self.old_path = sys.path[:] 1105 sys.path.insert(0, TESTFN) 1106 1107 def tearDown(self): 1108 sys.path[:] = self.old_path 1109 rmtree(TESTFN) 1110 1111 def create_module(self, mod, contents, ext=".py"): 1112 fname = os.path.join(TESTFN, mod + ext) 1113 with open(fname, "w") as f: 1114 f.write(contents) 1115 self.addCleanup(unload, mod) 1116 importlib.invalidate_caches() 1117 return fname 1118 1119 def assert_traceback(self, tb, files): 1120 deduped_files = [] 1121 while tb: 1122 code = tb.tb_frame.f_code 1123 fn = code.co_filename 1124 if not deduped_files or fn != deduped_files[-1]: 1125 deduped_files.append(fn) 1126 tb = tb.tb_next 1127 self.assertEqual(len(deduped_files), len(files), deduped_files) 1128 for fn, pat in zip(deduped_files, files): 1129 self.assertIn(pat, fn) 1130 1131 def test_nonexistent_module(self): 1132 try: 1133 # assertRaises() clears __traceback__ 1134 import nonexistent_xyzzy 1135 except ImportError as e: 1136 tb = e.__traceback__ 1137 else: 1138 self.fail("ImportError should have been raised") 1139 self.assert_traceback(tb, [__file__]) 1140 1141 def test_nonexistent_module_nested(self): 1142 self.create_module("foo", "import nonexistent_xyzzy") 1143 try: 1144 import foo 1145 except ImportError as e: 1146 tb = e.__traceback__ 1147 else: 1148 self.fail("ImportError should have been raised") 1149 self.assert_traceback(tb, [__file__, 'foo.py']) 1150 1151 def test_exec_failure(self): 1152 self.create_module("foo", "1/0") 1153 try: 1154 import foo 1155 except ZeroDivisionError as e: 1156 tb = e.__traceback__ 1157 else: 1158 self.fail("ZeroDivisionError should have been raised") 1159 self.assert_traceback(tb, [__file__, 'foo.py']) 1160 1161 def test_exec_failure_nested(self): 1162 self.create_module("foo", "import bar") 1163 self.create_module("bar", "1/0") 1164 try: 1165 import foo 1166 except ZeroDivisionError as e: 1167 tb = e.__traceback__ 1168 else: 1169 self.fail("ZeroDivisionError should have been raised") 1170 self.assert_traceback(tb, [__file__, 'foo.py', 'bar.py']) 1171 1172 # A few more examples from issue #15425 1173 def test_syntax_error(self): 1174 self.create_module("foo", "invalid syntax is invalid") 1175 try: 1176 import foo 1177 except SyntaxError as e: 1178 tb = e.__traceback__ 1179 else: 1180 self.fail("SyntaxError should have been raised") 1181 self.assert_traceback(tb, [__file__]) 1182 1183 def _setup_broken_package(self, parent, child): 1184 pkg_name = "_parent_foo" 1185 self.addCleanup(unload, pkg_name) 1186 pkg_path = os.path.join(TESTFN, pkg_name) 1187 os.mkdir(pkg_path) 1188 # Touch the __init__.py 1189 init_path = os.path.join(pkg_path, '__init__.py') 1190 with open(init_path, 'w') as f: 1191 f.write(parent) 1192 bar_path = os.path.join(pkg_path, 'bar.py') 1193 with open(bar_path, 'w') as f: 1194 f.write(child) 1195 importlib.invalidate_caches() 1196 return init_path, bar_path 1197 1198 def test_broken_submodule(self): 1199 init_path, bar_path = self._setup_broken_package("", "1/0") 1200 try: 1201 import _parent_foo.bar 1202 except ZeroDivisionError as e: 1203 tb = e.__traceback__ 1204 else: 1205 self.fail("ZeroDivisionError should have been raised") 1206 self.assert_traceback(tb, [__file__, bar_path]) 1207 1208 def test_broken_from(self): 1209 init_path, bar_path = self._setup_broken_package("", "1/0") 1210 try: 1211 from _parent_foo import bar 1212 except ZeroDivisionError as e: 1213 tb = e.__traceback__ 1214 else: 1215 self.fail("ImportError should have been raised") 1216 self.assert_traceback(tb, [__file__, bar_path]) 1217 1218 def test_broken_parent(self): 1219 init_path, bar_path = self._setup_broken_package("1/0", "") 1220 try: 1221 import _parent_foo.bar 1222 except ZeroDivisionError as e: 1223 tb = e.__traceback__ 1224 else: 1225 self.fail("ZeroDivisionError should have been raised") 1226 self.assert_traceback(tb, [__file__, init_path]) 1227 1228 def test_broken_parent_from(self): 1229 init_path, bar_path = self._setup_broken_package("1/0", "") 1230 try: 1231 from _parent_foo import bar 1232 except ZeroDivisionError as e: 1233 tb = e.__traceback__ 1234 else: 1235 self.fail("ZeroDivisionError should have been raised") 1236 self.assert_traceback(tb, [__file__, init_path]) 1237 1238 @cpython_only 1239 def test_import_bug(self): 1240 # We simulate a bug in importlib and check that it's not stripped 1241 # away from the traceback. 1242 self.create_module("foo", "") 1243 importlib = sys.modules['_frozen_importlib_external'] 1244 if 'load_module' in vars(importlib.SourceLoader): 1245 old_exec_module = importlib.SourceLoader.exec_module 1246 else: 1247 old_exec_module = None 1248 try: 1249 def exec_module(*args): 1250 1/0 1251 importlib.SourceLoader.exec_module = exec_module 1252 try: 1253 import foo 1254 except ZeroDivisionError as e: 1255 tb = e.__traceback__ 1256 else: 1257 self.fail("ZeroDivisionError should have been raised") 1258 self.assert_traceback(tb, [__file__, '<frozen importlib', __file__]) 1259 finally: 1260 if old_exec_module is None: 1261 del importlib.SourceLoader.exec_module 1262 else: 1263 importlib.SourceLoader.exec_module = old_exec_module 1264 1265 @unittest.skipUnless(TESTFN_UNENCODABLE, 'need TESTFN_UNENCODABLE') 1266 def test_unencodable_filename(self): 1267 # Issue #11619: The Python parser and the import machinery must not 1268 # encode filenames, especially on Windows 1269 pyname = script_helper.make_script('', TESTFN_UNENCODABLE, 'pass') 1270 self.addCleanup(unlink, pyname) 1271 name = pyname[:-3] 1272 script_helper.assert_python_ok("-c", "mod = __import__(%a)" % name, 1273 __isolated=False) 1274 1275 1276class CircularImportTests(unittest.TestCase): 1277 1278 """See the docstrings of the modules being imported for the purpose of the 1279 test.""" 1280 1281 def tearDown(self): 1282 """Make sure no modules pre-exist in sys.modules which are being used to 1283 test.""" 1284 for key in list(sys.modules.keys()): 1285 if key.startswith('test.test_import.data.circular_imports'): 1286 del sys.modules[key] 1287 1288 def test_direct(self): 1289 try: 1290 import test.test_import.data.circular_imports.basic 1291 except ImportError: 1292 self.fail('circular import through relative imports failed') 1293 1294 def test_indirect(self): 1295 try: 1296 import test.test_import.data.circular_imports.indirect 1297 except ImportError: 1298 self.fail('relative import in module contributing to circular ' 1299 'import failed') 1300 1301 def test_subpackage(self): 1302 try: 1303 import test.test_import.data.circular_imports.subpackage 1304 except ImportError: 1305 self.fail('circular import involving a subpackage failed') 1306 1307 def test_rebinding(self): 1308 try: 1309 import test.test_import.data.circular_imports.rebinding as rebinding 1310 except ImportError: 1311 self.fail('circular import with rebinding of module attribute failed') 1312 from test.test_import.data.circular_imports.subpkg import util 1313 self.assertIs(util.util, rebinding.util) 1314 1315 def test_binding(self): 1316 try: 1317 import test.test_import.data.circular_imports.binding 1318 except ImportError: 1319 self.fail('circular import with binding a submodule to a name failed') 1320 1321 def test_crossreference1(self): 1322 import test.test_import.data.circular_imports.use 1323 import test.test_import.data.circular_imports.source 1324 1325 def test_crossreference2(self): 1326 with self.assertRaises(AttributeError) as cm: 1327 import test.test_import.data.circular_imports.source 1328 errmsg = str(cm.exception) 1329 self.assertIn('test.test_import.data.circular_imports.source', errmsg) 1330 self.assertIn('spam', errmsg) 1331 self.assertIn('partially initialized module', errmsg) 1332 self.assertIn('circular import', errmsg) 1333 1334 def test_circular_from_import(self): 1335 with self.assertRaises(ImportError) as cm: 1336 import test.test_import.data.circular_imports.from_cycle1 1337 self.assertIn( 1338 "cannot import name 'b' from partially initialized module " 1339 "'test.test_import.data.circular_imports.from_cycle1' " 1340 "(most likely due to a circular import)", 1341 str(cm.exception), 1342 ) 1343 1344 1345if __name__ == '__main__': 1346 # Test needs to be a package, so we can do relative imports. 1347 unittest.main() 1348