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