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