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 (is_jython, swap_attr, swap_item, cpython_only) 23from test.support.import_helper import ( 24 forget, make_legacy_pyc, unlink, unload, DirsOnSysPath) 25from test.support.os_helper import ( 26 TESTFN, rmtree, temp_umask, TESTFN_UNENCODABLE, temp_dir) 27from test.support import script_helper 28from test.support import threading_helper 29from test.test_importlib.util import uncache 30from types import ModuleType 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', encoding='utf-8') 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', encoding='utf-8') 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", encoding='utf-8') 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', encoding='utf-8') 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", encoding='utf-8') 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", encoding='utf-8') 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", encoding='utf-8') 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", encoding='utf-8') 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', encoding='utf-8') 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 # bpo 38091: this is a hack to slow down the code that calls 441 # has_deadlock(); the logic was itself sometimes deadlocking. 442 def delay_has_deadlock(frame, event, arg): 443 if event == 'call' and frame.f_code.co_name == 'has_deadlock': 444 time.sleep(0.1) 445 446 sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'data')) 447 try: 448 exc = None 449 def run(): 450 sys.settrace(delay_has_deadlock) 451 event.wait() 452 try: 453 import package 454 except BaseException as e: 455 nonlocal exc 456 exc = e 457 sys.settrace(None) 458 459 for i in range(10): 460 event = threading.Event() 461 threads = [threading.Thread(target=run) for x in range(2)] 462 try: 463 with threading_helper.start_threads(threads, event.set): 464 time.sleep(0) 465 finally: 466 sys.modules.pop('package', None) 467 sys.modules.pop('package.submodule', None) 468 if exc is not None: 469 raise exc 470 finally: 471 del sys.path[0] 472 473 @unittest.skipUnless(sys.platform == "win32", "Windows-specific") 474 def test_dll_dependency_import(self): 475 from _winapi import GetModuleFileName 476 dllname = GetModuleFileName(sys.dllhandle) 477 pydname = importlib.util.find_spec("_sqlite3").origin 478 depname = os.path.join( 479 os.path.dirname(pydname), 480 "sqlite3{}.dll".format("_d" if "_d" in pydname else "")) 481 482 with os_helper.temp_dir() as tmp: 483 tmp2 = os.path.join(tmp, "DLLs") 484 os.mkdir(tmp2) 485 486 pyexe = os.path.join(tmp, os.path.basename(sys.executable)) 487 shutil.copy(sys.executable, pyexe) 488 shutil.copy(dllname, tmp) 489 for f in glob.glob(os.path.join(glob.escape(sys.prefix), "vcruntime*.dll")): 490 shutil.copy(f, tmp) 491 492 shutil.copy(pydname, tmp2) 493 494 env = None 495 env = {k.upper(): os.environ[k] for k in os.environ} 496 env["PYTHONPATH"] = tmp2 + ";" + os.path.dirname(os.__file__) 497 498 # Test 1: import with added DLL directory 499 subprocess.check_call([ 500 pyexe, "-Sc", ";".join([ 501 "import os", 502 "p = os.add_dll_directory({!r})".format( 503 os.path.dirname(depname)), 504 "import _sqlite3", 505 "p.close" 506 ])], 507 stderr=subprocess.STDOUT, 508 env=env, 509 cwd=os.path.dirname(pyexe)) 510 511 # Test 2: import with DLL adjacent to PYD 512 shutil.copy(depname, tmp2) 513 subprocess.check_call([pyexe, "-Sc", "import _sqlite3"], 514 stderr=subprocess.STDOUT, 515 env=env, 516 cwd=os.path.dirname(pyexe)) 517 518 519@skip_if_dont_write_bytecode 520class FilePermissionTests(unittest.TestCase): 521 # tests for file mode on cached .pyc files 522 523 @unittest.skipUnless(os.name == 'posix', 524 "test meaningful only on posix systems") 525 def test_creation_mode(self): 526 mask = 0o022 527 with temp_umask(mask), _ready_to_import() as (name, path): 528 cached_path = importlib.util.cache_from_source(path) 529 module = __import__(name) 530 if not os.path.exists(cached_path): 531 self.fail("__import__ did not result in creation of " 532 "a .pyc file") 533 stat_info = os.stat(cached_path) 534 535 # Check that the umask is respected, and the executable bits 536 # aren't set. 537 self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), 538 oct(0o666 & ~mask)) 539 540 @unittest.skipUnless(os.name == 'posix', 541 "test meaningful only on posix systems") 542 def test_cached_mode_issue_2051(self): 543 # permissions of .pyc should match those of .py, regardless of mask 544 mode = 0o600 545 with temp_umask(0o022), _ready_to_import() as (name, path): 546 cached_path = importlib.util.cache_from_source(path) 547 os.chmod(path, mode) 548 __import__(name) 549 if not os.path.exists(cached_path): 550 self.fail("__import__ did not result in creation of " 551 "a .pyc file") 552 stat_info = os.stat(cached_path) 553 554 self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(mode)) 555 556 @unittest.skipUnless(os.name == 'posix', 557 "test meaningful only on posix systems") 558 def test_cached_readonly(self): 559 mode = 0o400 560 with temp_umask(0o022), _ready_to_import() as (name, path): 561 cached_path = importlib.util.cache_from_source(path) 562 os.chmod(path, mode) 563 __import__(name) 564 if not os.path.exists(cached_path): 565 self.fail("__import__ did not result in creation of " 566 "a .pyc file") 567 stat_info = os.stat(cached_path) 568 569 expected = mode | 0o200 # Account for fix for issue #6074 570 self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(expected)) 571 572 def test_pyc_always_writable(self): 573 # Initially read-only .pyc files on Windows used to cause problems 574 # with later updates, see issue #6074 for details 575 with _ready_to_import() as (name, path): 576 # Write a Python file, make it read-only and import it 577 with open(path, 'w', encoding='utf-8') as f: 578 f.write("x = 'original'\n") 579 # Tweak the mtime of the source to ensure pyc gets updated later 580 s = os.stat(path) 581 os.utime(path, (s.st_atime, s.st_mtime-100000000)) 582 os.chmod(path, 0o400) 583 m = __import__(name) 584 self.assertEqual(m.x, 'original') 585 # Change the file and then reimport it 586 os.chmod(path, 0o600) 587 with open(path, 'w', encoding='utf-8') as f: 588 f.write("x = 'rewritten'\n") 589 unload(name) 590 importlib.invalidate_caches() 591 m = __import__(name) 592 self.assertEqual(m.x, 'rewritten') 593 # Now delete the source file and check the pyc was rewritten 594 unlink(path) 595 unload(name) 596 importlib.invalidate_caches() 597 bytecode_only = path + "c" 598 os.rename(importlib.util.cache_from_source(path), bytecode_only) 599 m = __import__(name) 600 self.assertEqual(m.x, 'rewritten') 601 602 603class PycRewritingTests(unittest.TestCase): 604 # Test that the `co_filename` attribute on code objects always points 605 # to the right file, even when various things happen (e.g. both the .py 606 # and the .pyc file are renamed). 607 608 module_name = "unlikely_module_name" 609 module_source = """ 610import sys 611code_filename = sys._getframe().f_code.co_filename 612module_filename = __file__ 613constant = 1 614def func(): 615 pass 616func_filename = func.__code__.co_filename 617""" 618 dir_name = os.path.abspath(TESTFN) 619 file_name = os.path.join(dir_name, module_name) + os.extsep + "py" 620 compiled_name = importlib.util.cache_from_source(file_name) 621 622 def setUp(self): 623 self.sys_path = sys.path[:] 624 self.orig_module = sys.modules.pop(self.module_name, None) 625 os.mkdir(self.dir_name) 626 with open(self.file_name, "w", encoding='utf-8') as f: 627 f.write(self.module_source) 628 sys.path.insert(0, self.dir_name) 629 importlib.invalidate_caches() 630 631 def tearDown(self): 632 sys.path[:] = self.sys_path 633 if self.orig_module is not None: 634 sys.modules[self.module_name] = self.orig_module 635 else: 636 unload(self.module_name) 637 unlink(self.file_name) 638 unlink(self.compiled_name) 639 rmtree(self.dir_name) 640 641 def import_module(self): 642 ns = globals() 643 __import__(self.module_name, ns, ns) 644 return sys.modules[self.module_name] 645 646 def test_basics(self): 647 mod = self.import_module() 648 self.assertEqual(mod.module_filename, self.file_name) 649 self.assertEqual(mod.code_filename, self.file_name) 650 self.assertEqual(mod.func_filename, self.file_name) 651 del sys.modules[self.module_name] 652 mod = self.import_module() 653 self.assertEqual(mod.module_filename, self.file_name) 654 self.assertEqual(mod.code_filename, self.file_name) 655 self.assertEqual(mod.func_filename, self.file_name) 656 657 def test_incorrect_code_name(self): 658 py_compile.compile(self.file_name, dfile="another_module.py") 659 mod = self.import_module() 660 self.assertEqual(mod.module_filename, self.file_name) 661 self.assertEqual(mod.code_filename, self.file_name) 662 self.assertEqual(mod.func_filename, self.file_name) 663 664 def test_module_without_source(self): 665 target = "another_module.py" 666 py_compile.compile(self.file_name, dfile=target) 667 os.remove(self.file_name) 668 pyc_file = make_legacy_pyc(self.file_name) 669 importlib.invalidate_caches() 670 mod = self.import_module() 671 self.assertEqual(mod.module_filename, pyc_file) 672 self.assertEqual(mod.code_filename, target) 673 self.assertEqual(mod.func_filename, target) 674 675 def test_foreign_code(self): 676 py_compile.compile(self.file_name) 677 with open(self.compiled_name, "rb") as f: 678 header = f.read(16) 679 code = marshal.load(f) 680 constants = list(code.co_consts) 681 foreign_code = importlib.import_module.__code__ 682 pos = constants.index(1) 683 constants[pos] = foreign_code 684 code = code.replace(co_consts=tuple(constants)) 685 with open(self.compiled_name, "wb") as f: 686 f.write(header) 687 marshal.dump(code, f) 688 mod = self.import_module() 689 self.assertEqual(mod.constant.co_filename, foreign_code.co_filename) 690 691 692class PathsTests(unittest.TestCase): 693 SAMPLES = ('test', 'test\u00e4\u00f6\u00fc\u00df', 'test\u00e9\u00e8', 694 'test\u00b0\u00b3\u00b2') 695 path = TESTFN 696 697 def setUp(self): 698 os.mkdir(self.path) 699 self.syspath = sys.path[:] 700 701 def tearDown(self): 702 rmtree(self.path) 703 sys.path[:] = self.syspath 704 705 # Regression test for http://bugs.python.org/issue1293. 706 def test_trailing_slash(self): 707 with open(os.path.join(self.path, 'test_trailing_slash.py'), 708 'w', encoding='utf-8') as f: 709 f.write("testdata = 'test_trailing_slash'") 710 sys.path.append(self.path+'/') 711 mod = __import__("test_trailing_slash") 712 self.assertEqual(mod.testdata, 'test_trailing_slash') 713 unload("test_trailing_slash") 714 715 # Regression test for http://bugs.python.org/issue3677. 716 @unittest.skipUnless(sys.platform == 'win32', 'Windows-specific') 717 def test_UNC_path(self): 718 with open(os.path.join(self.path, 'test_unc_path.py'), 'w') as f: 719 f.write("testdata = 'test_unc_path'") 720 importlib.invalidate_caches() 721 # Create the UNC path, like \\myhost\c$\foo\bar. 722 path = os.path.abspath(self.path) 723 import socket 724 hn = socket.gethostname() 725 drive = path[0] 726 unc = "\\\\%s\\%s$"%(hn, drive) 727 unc += path[2:] 728 try: 729 os.listdir(unc) 730 except OSError as e: 731 if e.errno in (errno.EPERM, errno.EACCES, errno.ENOENT): 732 # See issue #15338 733 self.skipTest("cannot access administrative share %r" % (unc,)) 734 raise 735 sys.path.insert(0, unc) 736 try: 737 mod = __import__("test_unc_path") 738 except ImportError as e: 739 self.fail("could not import 'test_unc_path' from %r: %r" 740 % (unc, e)) 741 self.assertEqual(mod.testdata, 'test_unc_path') 742 self.assertTrue(mod.__file__.startswith(unc), mod.__file__) 743 unload("test_unc_path") 744 745 746class RelativeImportTests(unittest.TestCase): 747 748 def tearDown(self): 749 unload("test.relimport") 750 setUp = tearDown 751 752 def test_relimport_star(self): 753 # This will import * from .test_import. 754 from .. import relimport 755 self.assertTrue(hasattr(relimport, "RelativeImportTests")) 756 757 def test_issue3221(self): 758 # Note for mergers: the 'absolute' tests from the 2.x branch 759 # are missing in Py3k because implicit relative imports are 760 # a thing of the past 761 # 762 # Regression test for http://bugs.python.org/issue3221. 763 def check_relative(): 764 exec("from . import relimport", ns) 765 766 # Check relative import OK with __package__ and __name__ correct 767 ns = dict(__package__='test', __name__='test.notarealmodule') 768 check_relative() 769 770 # Check relative import OK with only __name__ wrong 771 ns = dict(__package__='test', __name__='notarealpkg.notarealmodule') 772 check_relative() 773 774 # Check relative import fails with only __package__ wrong 775 ns = dict(__package__='foo', __name__='test.notarealmodule') 776 self.assertRaises(ModuleNotFoundError, check_relative) 777 778 # Check relative import fails with __package__ and __name__ wrong 779 ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule') 780 self.assertRaises(ModuleNotFoundError, check_relative) 781 782 # Check relative import fails with package set to a non-string 783 ns = dict(__package__=object()) 784 self.assertRaises(TypeError, check_relative) 785 786 def test_parentless_import_shadowed_by_global(self): 787 # Test as if this were done from the REPL where this error most commonly occurs (bpo-37409). 788 script_helper.assert_python_failure('-W', 'ignore', '-c', 789 "foo = 1; from . import foo") 790 791 def test_absolute_import_without_future(self): 792 # If explicit relative import syntax is used, then do not try 793 # to perform an absolute import in the face of failure. 794 # Issue #7902. 795 with self.assertRaises(ImportError): 796 from .os import sep 797 self.fail("explicit relative import triggered an " 798 "implicit absolute import") 799 800 def test_import_from_non_package(self): 801 path = os.path.join(os.path.dirname(__file__), 'data', 'package2') 802 with uncache('submodule1', 'submodule2'), DirsOnSysPath(path): 803 with self.assertRaises(ImportError): 804 import submodule1 805 self.assertNotIn('submodule1', sys.modules) 806 self.assertNotIn('submodule2', sys.modules) 807 808 def test_import_from_unloaded_package(self): 809 with uncache('package2', 'package2.submodule1', 'package2.submodule2'), \ 810 DirsOnSysPath(os.path.join(os.path.dirname(__file__), 'data')): 811 import package2.submodule1 812 package2.submodule1.submodule2 813 814 815class OverridingImportBuiltinTests(unittest.TestCase): 816 def test_override_builtin(self): 817 # Test that overriding builtins.__import__ can bypass sys.modules. 818 import os 819 820 def foo(): 821 import os 822 return os 823 self.assertEqual(foo(), os) # Quick sanity check. 824 825 with swap_attr(builtins, "__import__", lambda *x: 5): 826 self.assertEqual(foo(), 5) 827 828 # Test what happens when we shadow __import__ in globals(); this 829 # currently does not impact the import process, but if this changes, 830 # other code will need to change, so keep this test as a tripwire. 831 with swap_item(globals(), "__import__", lambda *x: 5): 832 self.assertEqual(foo(), os) 833 834 835class PycacheTests(unittest.TestCase): 836 # Test the various PEP 3147/488-related behaviors. 837 838 def _clean(self): 839 forget(TESTFN) 840 rmtree('__pycache__') 841 unlink(self.source) 842 843 def setUp(self): 844 self.source = TESTFN + '.py' 845 self._clean() 846 with open(self.source, 'w', encoding='utf-8') as fp: 847 print('# This is a test file written by test_import.py', file=fp) 848 sys.path.insert(0, os.curdir) 849 importlib.invalidate_caches() 850 851 def tearDown(self): 852 assert sys.path[0] == os.curdir, 'Unexpected sys.path[0]' 853 del sys.path[0] 854 self._clean() 855 856 @skip_if_dont_write_bytecode 857 def test_import_pyc_path(self): 858 self.assertFalse(os.path.exists('__pycache__')) 859 __import__(TESTFN) 860 self.assertTrue(os.path.exists('__pycache__')) 861 pyc_path = importlib.util.cache_from_source(self.source) 862 self.assertTrue(os.path.exists(pyc_path), 863 'bytecode file {!r} for {!r} does not ' 864 'exist'.format(pyc_path, TESTFN)) 865 866 @unittest.skipUnless(os.name == 'posix', 867 "test meaningful only on posix systems") 868 @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0, 869 "due to varying filesystem permission semantics (issue #11956)") 870 @skip_if_dont_write_bytecode 871 def test_unwritable_directory(self): 872 # When the umask causes the new __pycache__ directory to be 873 # unwritable, the import still succeeds but no .pyc file is written. 874 with temp_umask(0o222): 875 __import__(TESTFN) 876 self.assertTrue(os.path.exists('__pycache__')) 877 pyc_path = importlib.util.cache_from_source(self.source) 878 self.assertFalse(os.path.exists(pyc_path), 879 'bytecode file {!r} for {!r} ' 880 'exists'.format(pyc_path, TESTFN)) 881 882 @skip_if_dont_write_bytecode 883 def test_missing_source(self): 884 # With PEP 3147 cache layout, removing the source but leaving the pyc 885 # file does not satisfy the import. 886 __import__(TESTFN) 887 pyc_file = importlib.util.cache_from_source(self.source) 888 self.assertTrue(os.path.exists(pyc_file)) 889 os.remove(self.source) 890 forget(TESTFN) 891 importlib.invalidate_caches() 892 self.assertRaises(ImportError, __import__, TESTFN) 893 894 @skip_if_dont_write_bytecode 895 def test_missing_source_legacy(self): 896 # Like test_missing_source() except that for backward compatibility, 897 # when the pyc file lives where the py file would have been (and named 898 # without the tag), it is importable. The __file__ of the imported 899 # module is the pyc location. 900 __import__(TESTFN) 901 # pyc_file gets removed in _clean() via tearDown(). 902 pyc_file = make_legacy_pyc(self.source) 903 os.remove(self.source) 904 unload(TESTFN) 905 importlib.invalidate_caches() 906 m = __import__(TESTFN) 907 try: 908 self.assertEqual(m.__file__, 909 os.path.join(os.getcwd(), os.curdir, os.path.relpath(pyc_file))) 910 finally: 911 os.remove(pyc_file) 912 913 def test___cached__(self): 914 # Modules now also have an __cached__ that points to the pyc file. 915 m = __import__(TESTFN) 916 pyc_file = importlib.util.cache_from_source(TESTFN + '.py') 917 self.assertEqual(m.__cached__, os.path.join(os.getcwd(), os.curdir, pyc_file)) 918 919 @skip_if_dont_write_bytecode 920 def test___cached___legacy_pyc(self): 921 # Like test___cached__() except that for backward compatibility, 922 # when the pyc file lives where the py file would have been (and named 923 # without the tag), it is importable. The __cached__ of the imported 924 # module is the pyc location. 925 __import__(TESTFN) 926 # pyc_file gets removed in _clean() via tearDown(). 927 pyc_file = make_legacy_pyc(self.source) 928 os.remove(self.source) 929 unload(TESTFN) 930 importlib.invalidate_caches() 931 m = __import__(TESTFN) 932 self.assertEqual(m.__cached__, 933 os.path.join(os.getcwd(), os.curdir, os.path.relpath(pyc_file))) 934 935 @skip_if_dont_write_bytecode 936 def test_package___cached__(self): 937 # Like test___cached__ but for packages. 938 def cleanup(): 939 rmtree('pep3147') 940 unload('pep3147.foo') 941 unload('pep3147') 942 os.mkdir('pep3147') 943 self.addCleanup(cleanup) 944 # Touch the __init__.py 945 with open(os.path.join('pep3147', '__init__.py'), 'wb'): 946 pass 947 with open(os.path.join('pep3147', 'foo.py'), 'wb'): 948 pass 949 importlib.invalidate_caches() 950 m = __import__('pep3147.foo') 951 init_pyc = importlib.util.cache_from_source( 952 os.path.join('pep3147', '__init__.py')) 953 self.assertEqual(m.__cached__, os.path.join(os.getcwd(), os.curdir, init_pyc)) 954 foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py')) 955 self.assertEqual(sys.modules['pep3147.foo'].__cached__, 956 os.path.join(os.getcwd(), os.curdir, foo_pyc)) 957 958 def test_package___cached___from_pyc(self): 959 # Like test___cached__ but ensuring __cached__ when imported from a 960 # PEP 3147 pyc file. 961 def cleanup(): 962 rmtree('pep3147') 963 unload('pep3147.foo') 964 unload('pep3147') 965 os.mkdir('pep3147') 966 self.addCleanup(cleanup) 967 # Touch the __init__.py 968 with open(os.path.join('pep3147', '__init__.py'), 'wb'): 969 pass 970 with open(os.path.join('pep3147', 'foo.py'), 'wb'): 971 pass 972 importlib.invalidate_caches() 973 m = __import__('pep3147.foo') 974 unload('pep3147.foo') 975 unload('pep3147') 976 importlib.invalidate_caches() 977 m = __import__('pep3147.foo') 978 init_pyc = importlib.util.cache_from_source( 979 os.path.join('pep3147', '__init__.py')) 980 self.assertEqual(m.__cached__, os.path.join(os.getcwd(), os.curdir, init_pyc)) 981 foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py')) 982 self.assertEqual(sys.modules['pep3147.foo'].__cached__, 983 os.path.join(os.getcwd(), os.curdir, foo_pyc)) 984 985 def test_recompute_pyc_same_second(self): 986 # Even when the source file doesn't change timestamp, a change in 987 # source size is enough to trigger recomputation of the pyc file. 988 __import__(TESTFN) 989 unload(TESTFN) 990 with open(self.source, 'a', encoding='utf-8') as fp: 991 print("x = 5", file=fp) 992 m = __import__(TESTFN) 993 self.assertEqual(m.x, 5) 994 995 996class TestSymbolicallyLinkedPackage(unittest.TestCase): 997 package_name = 'sample' 998 tagged = package_name + '-tagged' 999 1000 def setUp(self): 1001 os_helper.rmtree(self.tagged) 1002 os_helper.rmtree(self.package_name) 1003 self.orig_sys_path = sys.path[:] 1004 1005 # create a sample package; imagine you have a package with a tag and 1006 # you want to symbolically link it from its untagged name. 1007 os.mkdir(self.tagged) 1008 self.addCleanup(os_helper.rmtree, self.tagged) 1009 init_file = os.path.join(self.tagged, '__init__.py') 1010 os_helper.create_empty_file(init_file) 1011 assert os.path.exists(init_file) 1012 1013 # now create a symlink to the tagged package 1014 # sample -> sample-tagged 1015 os.symlink(self.tagged, self.package_name, target_is_directory=True) 1016 self.addCleanup(os_helper.unlink, self.package_name) 1017 importlib.invalidate_caches() 1018 1019 self.assertEqual(os.path.isdir(self.package_name), True) 1020 1021 assert os.path.isfile(os.path.join(self.package_name, '__init__.py')) 1022 1023 def tearDown(self): 1024 sys.path[:] = self.orig_sys_path 1025 1026 # regression test for issue6727 1027 @unittest.skipUnless( 1028 not hasattr(sys, 'getwindowsversion') 1029 or sys.getwindowsversion() >= (6, 0), 1030 "Windows Vista or later required") 1031 @os_helper.skip_unless_symlink 1032 def test_symlinked_dir_importable(self): 1033 # make sure sample can only be imported from the current directory. 1034 sys.path[:] = ['.'] 1035 assert os.path.exists(self.package_name) 1036 assert os.path.exists(os.path.join(self.package_name, '__init__.py')) 1037 1038 # Try to import the package 1039 importlib.import_module(self.package_name) 1040 1041 1042@cpython_only 1043class ImportlibBootstrapTests(unittest.TestCase): 1044 # These tests check that importlib is bootstrapped. 1045 1046 def test_frozen_importlib(self): 1047 mod = sys.modules['_frozen_importlib'] 1048 self.assertTrue(mod) 1049 1050 def test_frozen_importlib_is_bootstrap(self): 1051 from importlib import _bootstrap 1052 mod = sys.modules['_frozen_importlib'] 1053 self.assertIs(mod, _bootstrap) 1054 self.assertEqual(mod.__name__, 'importlib._bootstrap') 1055 self.assertEqual(mod.__package__, 'importlib') 1056 self.assertTrue(mod.__file__.endswith('_bootstrap.py'), mod.__file__) 1057 1058 def test_frozen_importlib_external_is_bootstrap_external(self): 1059 from importlib import _bootstrap_external 1060 mod = sys.modules['_frozen_importlib_external'] 1061 self.assertIs(mod, _bootstrap_external) 1062 self.assertEqual(mod.__name__, 'importlib._bootstrap_external') 1063 self.assertEqual(mod.__package__, 'importlib') 1064 self.assertTrue(mod.__file__.endswith('_bootstrap_external.py'), mod.__file__) 1065 1066 def test_there_can_be_only_one(self): 1067 # Issue #15386 revealed a tricky loophole in the bootstrapping 1068 # This test is technically redundant, since the bug caused importing 1069 # this test module to crash completely, but it helps prove the point 1070 from importlib import machinery 1071 mod = sys.modules['_frozen_importlib'] 1072 self.assertIs(machinery.ModuleSpec, mod.ModuleSpec) 1073 1074 1075@cpython_only 1076class GetSourcefileTests(unittest.TestCase): 1077 1078 """Test importlib._bootstrap_external._get_sourcefile() as used by the C API. 1079 1080 Because of the peculiarities of the need of this function, the tests are 1081 knowingly whitebox tests. 1082 1083 """ 1084 1085 def test_get_sourcefile(self): 1086 # Given a valid bytecode path, return the path to the corresponding 1087 # source file if it exists. 1088 with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: 1089 _path_isfile.return_value = True 1090 path = TESTFN + '.pyc' 1091 expect = TESTFN + '.py' 1092 self.assertEqual(_get_sourcefile(path), expect) 1093 1094 def test_get_sourcefile_no_source(self): 1095 # Given a valid bytecode path without a corresponding source path, 1096 # return the original bytecode path. 1097 with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: 1098 _path_isfile.return_value = False 1099 path = TESTFN + '.pyc' 1100 self.assertEqual(_get_sourcefile(path), path) 1101 1102 def test_get_sourcefile_bad_ext(self): 1103 # Given a path with an invalid bytecode extension, return the 1104 # bytecode path passed as the argument. 1105 path = TESTFN + '.bad_ext' 1106 self.assertEqual(_get_sourcefile(path), path) 1107 1108 1109class ImportTracebackTests(unittest.TestCase): 1110 1111 def setUp(self): 1112 os.mkdir(TESTFN) 1113 self.old_path = sys.path[:] 1114 sys.path.insert(0, TESTFN) 1115 1116 def tearDown(self): 1117 sys.path[:] = self.old_path 1118 rmtree(TESTFN) 1119 1120 def create_module(self, mod, contents, ext=".py"): 1121 fname = os.path.join(TESTFN, mod + ext) 1122 with open(fname, "w", encoding='utf-8') as f: 1123 f.write(contents) 1124 self.addCleanup(unload, mod) 1125 importlib.invalidate_caches() 1126 return fname 1127 1128 def assert_traceback(self, tb, files): 1129 deduped_files = [] 1130 while tb: 1131 code = tb.tb_frame.f_code 1132 fn = code.co_filename 1133 if not deduped_files or fn != deduped_files[-1]: 1134 deduped_files.append(fn) 1135 tb = tb.tb_next 1136 self.assertEqual(len(deduped_files), len(files), deduped_files) 1137 for fn, pat in zip(deduped_files, files): 1138 self.assertIn(pat, fn) 1139 1140 def test_nonexistent_module(self): 1141 try: 1142 # assertRaises() clears __traceback__ 1143 import nonexistent_xyzzy 1144 except ImportError as e: 1145 tb = e.__traceback__ 1146 else: 1147 self.fail("ImportError should have been raised") 1148 self.assert_traceback(tb, [__file__]) 1149 1150 def test_nonexistent_module_nested(self): 1151 self.create_module("foo", "import nonexistent_xyzzy") 1152 try: 1153 import foo 1154 except ImportError as e: 1155 tb = e.__traceback__ 1156 else: 1157 self.fail("ImportError should have been raised") 1158 self.assert_traceback(tb, [__file__, 'foo.py']) 1159 1160 def test_exec_failure(self): 1161 self.create_module("foo", "1/0") 1162 try: 1163 import foo 1164 except ZeroDivisionError as e: 1165 tb = e.__traceback__ 1166 else: 1167 self.fail("ZeroDivisionError should have been raised") 1168 self.assert_traceback(tb, [__file__, 'foo.py']) 1169 1170 def test_exec_failure_nested(self): 1171 self.create_module("foo", "import bar") 1172 self.create_module("bar", "1/0") 1173 try: 1174 import foo 1175 except ZeroDivisionError as e: 1176 tb = e.__traceback__ 1177 else: 1178 self.fail("ZeroDivisionError should have been raised") 1179 self.assert_traceback(tb, [__file__, 'foo.py', 'bar.py']) 1180 1181 # A few more examples from issue #15425 1182 def test_syntax_error(self): 1183 self.create_module("foo", "invalid syntax is invalid") 1184 try: 1185 import foo 1186 except SyntaxError as e: 1187 tb = e.__traceback__ 1188 else: 1189 self.fail("SyntaxError should have been raised") 1190 self.assert_traceback(tb, [__file__]) 1191 1192 def _setup_broken_package(self, parent, child): 1193 pkg_name = "_parent_foo" 1194 self.addCleanup(unload, pkg_name) 1195 pkg_path = os.path.join(TESTFN, pkg_name) 1196 os.mkdir(pkg_path) 1197 # Touch the __init__.py 1198 init_path = os.path.join(pkg_path, '__init__.py') 1199 with open(init_path, 'w', encoding='utf-8') as f: 1200 f.write(parent) 1201 bar_path = os.path.join(pkg_path, 'bar.py') 1202 with open(bar_path, 'w', encoding='utf-8') as f: 1203 f.write(child) 1204 importlib.invalidate_caches() 1205 return init_path, bar_path 1206 1207 def test_broken_submodule(self): 1208 init_path, bar_path = self._setup_broken_package("", "1/0") 1209 try: 1210 import _parent_foo.bar 1211 except ZeroDivisionError as e: 1212 tb = e.__traceback__ 1213 else: 1214 self.fail("ZeroDivisionError should have been raised") 1215 self.assert_traceback(tb, [__file__, bar_path]) 1216 1217 def test_broken_from(self): 1218 init_path, bar_path = self._setup_broken_package("", "1/0") 1219 try: 1220 from _parent_foo import bar 1221 except ZeroDivisionError as e: 1222 tb = e.__traceback__ 1223 else: 1224 self.fail("ImportError should have been raised") 1225 self.assert_traceback(tb, [__file__, bar_path]) 1226 1227 def test_broken_parent(self): 1228 init_path, bar_path = self._setup_broken_package("1/0", "") 1229 try: 1230 import _parent_foo.bar 1231 except ZeroDivisionError as e: 1232 tb = e.__traceback__ 1233 else: 1234 self.fail("ZeroDivisionError should have been raised") 1235 self.assert_traceback(tb, [__file__, init_path]) 1236 1237 def test_broken_parent_from(self): 1238 init_path, bar_path = self._setup_broken_package("1/0", "") 1239 try: 1240 from _parent_foo import bar 1241 except ZeroDivisionError as e: 1242 tb = e.__traceback__ 1243 else: 1244 self.fail("ZeroDivisionError should have been raised") 1245 self.assert_traceback(tb, [__file__, init_path]) 1246 1247 @cpython_only 1248 def test_import_bug(self): 1249 # We simulate a bug in importlib and check that it's not stripped 1250 # away from the traceback. 1251 self.create_module("foo", "") 1252 importlib = sys.modules['_frozen_importlib_external'] 1253 if 'load_module' in vars(importlib.SourceLoader): 1254 old_exec_module = importlib.SourceLoader.exec_module 1255 else: 1256 old_exec_module = None 1257 try: 1258 def exec_module(*args): 1259 1/0 1260 importlib.SourceLoader.exec_module = exec_module 1261 try: 1262 import foo 1263 except ZeroDivisionError as e: 1264 tb = e.__traceback__ 1265 else: 1266 self.fail("ZeroDivisionError should have been raised") 1267 self.assert_traceback(tb, [__file__, '<frozen importlib', __file__]) 1268 finally: 1269 if old_exec_module is None: 1270 del importlib.SourceLoader.exec_module 1271 else: 1272 importlib.SourceLoader.exec_module = old_exec_module 1273 1274 @unittest.skipUnless(TESTFN_UNENCODABLE, 'need TESTFN_UNENCODABLE') 1275 def test_unencodable_filename(self): 1276 # Issue #11619: The Python parser and the import machinery must not 1277 # encode filenames, especially on Windows 1278 pyname = script_helper.make_script('', TESTFN_UNENCODABLE, 'pass') 1279 self.addCleanup(unlink, pyname) 1280 name = pyname[:-3] 1281 script_helper.assert_python_ok("-c", "mod = __import__(%a)" % name, 1282 __isolated=False) 1283 1284 1285class CircularImportTests(unittest.TestCase): 1286 1287 """See the docstrings of the modules being imported for the purpose of the 1288 test.""" 1289 1290 def tearDown(self): 1291 """Make sure no modules pre-exist in sys.modules which are being used to 1292 test.""" 1293 for key in list(sys.modules.keys()): 1294 if key.startswith('test.test_import.data.circular_imports'): 1295 del sys.modules[key] 1296 1297 def test_direct(self): 1298 try: 1299 import test.test_import.data.circular_imports.basic 1300 except ImportError: 1301 self.fail('circular import through relative imports failed') 1302 1303 def test_indirect(self): 1304 try: 1305 import test.test_import.data.circular_imports.indirect 1306 except ImportError: 1307 self.fail('relative import in module contributing to circular ' 1308 'import failed') 1309 1310 def test_subpackage(self): 1311 try: 1312 import test.test_import.data.circular_imports.subpackage 1313 except ImportError: 1314 self.fail('circular import involving a subpackage failed') 1315 1316 def test_rebinding(self): 1317 try: 1318 import test.test_import.data.circular_imports.rebinding as rebinding 1319 except ImportError: 1320 self.fail('circular import with rebinding of module attribute failed') 1321 from test.test_import.data.circular_imports.subpkg import util 1322 self.assertIs(util.util, rebinding.util) 1323 1324 def test_binding(self): 1325 try: 1326 import test.test_import.data.circular_imports.binding 1327 except ImportError: 1328 self.fail('circular import with binding a submodule to a name failed') 1329 1330 def test_crossreference1(self): 1331 import test.test_import.data.circular_imports.use 1332 import test.test_import.data.circular_imports.source 1333 1334 def test_crossreference2(self): 1335 with self.assertRaises(AttributeError) as cm: 1336 import test.test_import.data.circular_imports.source 1337 errmsg = str(cm.exception) 1338 self.assertIn('test.test_import.data.circular_imports.source', errmsg) 1339 self.assertIn('spam', errmsg) 1340 self.assertIn('partially initialized module', errmsg) 1341 self.assertIn('circular import', errmsg) 1342 1343 def test_circular_from_import(self): 1344 with self.assertRaises(ImportError) as cm: 1345 import test.test_import.data.circular_imports.from_cycle1 1346 self.assertIn( 1347 "cannot import name 'b' from partially initialized module " 1348 "'test.test_import.data.circular_imports.from_cycle1' " 1349 "(most likely due to a circular import)", 1350 str(cm.exception), 1351 ) 1352 1353 def test_unwritable_module(self): 1354 self.addCleanup(unload, "test.test_import.data.unwritable") 1355 self.addCleanup(unload, "test.test_import.data.unwritable.x") 1356 1357 import test.test_import.data.unwritable as unwritable 1358 with self.assertWarns(ImportWarning): 1359 from test.test_import.data.unwritable import x 1360 1361 self.assertNotEqual(type(unwritable), ModuleType) 1362 self.assertEqual(type(x), ModuleType) 1363 with self.assertRaises(AttributeError): 1364 unwritable.x = 42 1365 1366 1367if __name__ == '__main__': 1368 # Test needs to be a package, so we can do relative imports. 1369 unittest.main() 1370