1import errno 2import imp 3import marshal 4import os 5import py_compile 6import random 7import stat 8import struct 9import sys 10import unittest 11import textwrap 12import shutil 13 14from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree, 15 is_jython, check_warnings, EnvironmentVarGuard) 16from test import symlink_support 17from test import script_helper 18 19def _files(name): 20 return (name + os.extsep + "py", 21 name + os.extsep + "pyc", 22 name + os.extsep + "pyo", 23 name + os.extsep + "pyw", 24 name + "$py.class") 25 26def chmod_files(name): 27 for f in _files(name): 28 try: 29 os.chmod(f, 0600) 30 except OSError as exc: 31 if exc.errno != errno.ENOENT: 32 raise 33 34def remove_files(name): 35 for f in _files(name): 36 unlink(f) 37 38 39class ImportTests(unittest.TestCase): 40 41 def tearDown(self): 42 unload(TESTFN) 43 setUp = tearDown 44 45 def test_case_sensitivity(self): 46 # Brief digression to test that import is case-sensitive: if we got 47 # this far, we know for sure that "random" exists. 48 try: 49 import RAnDoM 50 except ImportError: 51 pass 52 else: 53 self.fail("import of RAnDoM should have failed (case mismatch)") 54 55 def test_double_const(self): 56 # Another brief digression to test the accuracy of manifest float 57 # constants. 58 from test import double_const # don't blink -- that *was* the test 59 60 def test_import(self): 61 def test_with_extension(ext): 62 # The extension is normally ".py", perhaps ".pyw". 63 source = TESTFN + ext 64 pyo = TESTFN + os.extsep + "pyo" 65 if is_jython: 66 pyc = TESTFN + "$py.class" 67 else: 68 pyc = TESTFN + os.extsep + "pyc" 69 70 with open(source, "w") as f: 71 print >> f, ("# This tests Python's ability to import a", ext, 72 "file.") 73 a = random.randrange(1000) 74 b = random.randrange(1000) 75 print >> f, "a =", a 76 print >> f, "b =", b 77 78 try: 79 mod = __import__(TESTFN) 80 except ImportError, err: 81 self.fail("import from %s failed: %s" % (ext, err)) 82 else: 83 self.assertEqual(mod.a, a, 84 "module loaded (%s) but contents invalid" % mod) 85 self.assertEqual(mod.b, b, 86 "module loaded (%s) but contents invalid" % mod) 87 finally: 88 unlink(source) 89 90 try: 91 if not sys.dont_write_bytecode: 92 imp.reload(mod) 93 except ImportError, err: 94 self.fail("import from .pyc/.pyo failed: %s" % err) 95 finally: 96 unlink(pyc) 97 unlink(pyo) 98 unload(TESTFN) 99 100 sys.path.insert(0, os.curdir) 101 try: 102 test_with_extension(os.extsep + "py") 103 if sys.platform.startswith("win"): 104 for ext in [".PY", ".Py", ".pY", ".pyw", ".PYW", ".pYw"]: 105 test_with_extension(ext) 106 finally: 107 del sys.path[0] 108 109 @unittest.skipUnless(os.name == 'posix', 110 "test meaningful only on posix systems") 111 @unittest.skipIf(sys.dont_write_bytecode, 112 "test meaningful only when writing bytecode") 113 def test_execute_bit_not_copied(self): 114 # Issue 6070: under posix .pyc files got their execute bit set if 115 # the .py file had the execute bit set, but they aren't executable. 116 oldmask = os.umask(022) 117 sys.path.insert(0, os.curdir) 118 try: 119 fname = TESTFN + os.extsep + "py" 120 f = open(fname, 'w').close() 121 os.chmod(fname, (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | 122 stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)) 123 __import__(TESTFN) 124 fn = fname + 'c' 125 if not os.path.exists(fn): 126 fn = fname + 'o' 127 if not os.path.exists(fn): 128 self.fail("__import__ did not result in creation of " 129 "either a .pyc or .pyo file") 130 s = os.stat(fn) 131 self.assertEqual(stat.S_IMODE(s.st_mode), 132 stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) 133 finally: 134 os.umask(oldmask) 135 remove_files(TESTFN) 136 unload(TESTFN) 137 del sys.path[0] 138 139 @unittest.skipIf(sys.dont_write_bytecode, 140 "test meaningful only when writing bytecode") 141 def test_rewrite_pyc_with_read_only_source(self): 142 # Issue 6074: a long time ago on posix, and more recently on Windows, 143 # a read only source file resulted in a read only pyc file, which 144 # led to problems with updating it later 145 sys.path.insert(0, os.curdir) 146 fname = TESTFN + os.extsep + "py" 147 try: 148 # Write a Python file, make it read-only and import it 149 with open(fname, 'w') as f: 150 f.write("x = 'original'\n") 151 # Tweak the mtime of the source to ensure pyc gets updated later 152 s = os.stat(fname) 153 os.utime(fname, (s.st_atime, s.st_mtime-100000000)) 154 os.chmod(fname, 0400) 155 m1 = __import__(TESTFN) 156 self.assertEqual(m1.x, 'original') 157 # Change the file and then reimport it 158 os.chmod(fname, 0600) 159 with open(fname, 'w') as f: 160 f.write("x = 'rewritten'\n") 161 unload(TESTFN) 162 m2 = __import__(TESTFN) 163 self.assertEqual(m2.x, 'rewritten') 164 # Now delete the source file and check the pyc was rewritten 165 unlink(fname) 166 unload(TESTFN) 167 m3 = __import__(TESTFN) 168 self.assertEqual(m3.x, 'rewritten') 169 finally: 170 chmod_files(TESTFN) 171 remove_files(TESTFN) 172 unload(TESTFN) 173 del sys.path[0] 174 175 def test_imp_module(self): 176 # Verify that the imp module can correctly load and find .py files 177 178 # XXX (ncoghlan): It would be nice to use test_support.CleanImport 179 # here, but that breaks because the os module registers some 180 # handlers in copy_reg on import. Since CleanImport doesn't 181 # revert that registration, the module is left in a broken 182 # state after reversion. Reinitialising the module contents 183 # and just reverting os.environ to its previous state is an OK 184 # workaround 185 orig_path = os.path 186 orig_getenv = os.getenv 187 with EnvironmentVarGuard(): 188 x = imp.find_module("os") 189 new_os = imp.load_module("os", *x) 190 self.assertIs(os, new_os) 191 self.assertIs(orig_path, new_os.path) 192 self.assertIsNot(orig_getenv, new_os.getenv) 193 194 def test_module_with_large_stack(self, module='longlist'): 195 # Regression test for http://bugs.python.org/issue561858. 196 filename = module + os.extsep + 'py' 197 198 # Create a file with a list of 65000 elements. 199 with open(filename, 'w+') as f: 200 f.write('d = [\n') 201 for i in range(65000): 202 f.write('"",\n') 203 f.write(']') 204 205 # Compile & remove .py file, we only need .pyc (or .pyo). 206 with open(filename, 'r') as f: 207 py_compile.compile(filename) 208 unlink(filename) 209 210 # Need to be able to load from current dir. 211 sys.path.append('') 212 213 # This used to crash. 214 exec 'import ' + module 215 216 # Cleanup. 217 del sys.path[-1] 218 unlink(filename + 'c') 219 unlink(filename + 'o') 220 221 def test_failing_import_sticks(self): 222 source = TESTFN + os.extsep + "py" 223 with open(source, "w") as f: 224 print >> f, "a = 1 // 0" 225 226 # New in 2.4, we shouldn't be able to import that no matter how often 227 # we try. 228 sys.path.insert(0, os.curdir) 229 try: 230 for i in [1, 2, 3]: 231 self.assertRaises(ZeroDivisionError, __import__, TESTFN) 232 self.assertNotIn(TESTFN, sys.modules, 233 "damaged module in sys.modules on %i try" % i) 234 finally: 235 del sys.path[0] 236 remove_files(TESTFN) 237 238 def test_failing_reload(self): 239 # A failing reload should leave the module object in sys.modules. 240 source = TESTFN + os.extsep + "py" 241 with open(source, "w") as f: 242 print >> f, "a = 1" 243 print >> f, "b = 2" 244 245 sys.path.insert(0, os.curdir) 246 try: 247 mod = __import__(TESTFN) 248 self.assertIn(TESTFN, sys.modules) 249 self.assertEqual(mod.a, 1, "module has wrong attribute values") 250 self.assertEqual(mod.b, 2, "module has wrong attribute values") 251 252 # On WinXP, just replacing the .py file wasn't enough to 253 # convince reload() to reparse it. Maybe the timestamp didn't 254 # move enough. We force it to get reparsed by removing the 255 # compiled file too. 256 remove_files(TESTFN) 257 258 # Now damage the module. 259 with open(source, "w") as f: 260 print >> f, "a = 10" 261 print >> f, "b = 20//0" 262 263 self.assertRaises(ZeroDivisionError, imp.reload, mod) 264 265 # But we still expect the module to be in sys.modules. 266 mod = sys.modules.get(TESTFN) 267 self.assertIsNot(mod, None, "expected module to be in sys.modules") 268 269 # We should have replaced a w/ 10, but the old b value should 270 # stick. 271 self.assertEqual(mod.a, 10, "module has wrong attribute values") 272 self.assertEqual(mod.b, 2, "module has wrong attribute values") 273 274 finally: 275 del sys.path[0] 276 remove_files(TESTFN) 277 unload(TESTFN) 278 279 def test_infinite_reload(self): 280 # http://bugs.python.org/issue742342 reports that Python segfaults 281 # (infinite recursion in C) when faced with self-recursive reload()ing. 282 283 sys.path.insert(0, os.path.dirname(__file__)) 284 try: 285 import infinite_reload 286 finally: 287 del sys.path[0] 288 289 def test_import_name_binding(self): 290 # import x.y.z binds x in the current namespace. 291 import test as x 292 import test.test_support 293 self.assertIs(x, test, x.__name__) 294 self.assertTrue(hasattr(test.test_support, "__file__")) 295 296 # import x.y.z as w binds z as w. 297 import test.test_support as y 298 self.assertIs(y, test.test_support, y.__name__) 299 300 def test_import_initless_directory_warning(self): 301 with check_warnings(('', ImportWarning)): 302 # Just a random non-package directory we always expect to be 303 # somewhere in sys.path... 304 self.assertRaises(ImportError, __import__, "site-packages") 305 306 def test_import_by_filename(self): 307 path = os.path.abspath(TESTFN) 308 with self.assertRaises(ImportError) as c: 309 __import__(path) 310 self.assertEqual("Import by filename is not supported.", 311 c.exception.args[0]) 312 313 def test_import_in_del_does_not_crash(self): 314 # Issue 4236 315 testfn = script_helper.make_script('', TESTFN, textwrap.dedent("""\ 316 import sys 317 class C: 318 def __del__(self): 319 import imp 320 sys.argv.insert(0, C()) 321 """)) 322 try: 323 script_helper.assert_python_ok(testfn) 324 finally: 325 unlink(testfn) 326 327 def test_bug7732(self): 328 source = TESTFN + '.py' 329 os.mkdir(source) 330 try: 331 self.assertRaises((ImportError, IOError), 332 imp.find_module, TESTFN, ["."]) 333 finally: 334 os.rmdir(source) 335 336 def test_timestamp_overflow(self): 337 # A modification timestamp larger than 2**32 should not be a problem 338 # when importing a module (issue #11235). 339 sys.path.insert(0, os.curdir) 340 try: 341 source = TESTFN + ".py" 342 compiled = source + ('c' if __debug__ else 'o') 343 with open(source, 'w') as f: 344 pass 345 try: 346 os.utime(source, (2 ** 33 - 5, 2 ** 33 - 5)) 347 except OverflowError: 348 self.skipTest("cannot set modification time to large integer") 349 except OSError as e: 350 if e.errno != getattr(errno, 'EOVERFLOW', None): 351 raise 352 self.skipTest("cannot set modification time to large integer ({})".format(e)) 353 __import__(TESTFN) 354 # The pyc file was created. 355 os.stat(compiled) 356 finally: 357 del sys.path[0] 358 remove_files(TESTFN) 359 360 def test_pyc_mtime(self): 361 # Test for issue #13863: .pyc timestamp sometimes incorrect on Windows. 362 sys.path.insert(0, os.curdir) 363 try: 364 # Jan 1, 2012; Jul 1, 2012. 365 mtimes = 1325376000, 1341100800 366 367 # Different names to avoid running into import caching. 368 tails = "spam", "eggs" 369 for mtime, tail in zip(mtimes, tails): 370 module = TESTFN + tail 371 source = module + ".py" 372 compiled = source + ('c' if __debug__ else 'o') 373 374 # Create a new Python file with the given mtime. 375 with open(source, 'w') as f: 376 f.write("# Just testing\nx=1, 2, 3\n") 377 os.utime(source, (mtime, mtime)) 378 379 # Generate the .pyc/o file; if it couldn't be created 380 # for some reason, skip the test. 381 m = __import__(module) 382 if not os.path.exists(compiled): 383 unlink(source) 384 self.skipTest("Couldn't create .pyc/.pyo file.") 385 386 # Actual modification time of .py file. 387 mtime1 = int(os.stat(source).st_mtime) & 0xffffffff 388 389 # mtime that was encoded in the .pyc file. 390 with open(compiled, 'rb') as f: 391 mtime2 = struct.unpack('<L', f.read(8)[4:])[0] 392 393 unlink(compiled) 394 unlink(source) 395 396 self.assertEqual(mtime1, mtime2) 397 finally: 398 sys.path.pop(0) 399 400 def test_replace_parent_in_sys_modules(self): 401 dir_name = os.path.abspath(TESTFN) 402 os.mkdir(dir_name) 403 try: 404 pkg_dir = os.path.join(dir_name, 'sa') 405 os.mkdir(pkg_dir) 406 with open(os.path.join(pkg_dir, '__init__.py'), 'w') as init_file: 407 init_file.write("import v1") 408 with open(os.path.join(pkg_dir, 'v1.py'), 'w') as v1_file: 409 v1_file.write("import sys;" 410 "sys.modules['sa'] = sys.modules[__name__];" 411 "import sa") 412 sys.path.insert(0, dir_name) 413 # a segfault means the test failed! 414 import sa 415 finally: 416 rmtree(dir_name) 417 418 def test_fromlist_type(self): 419 with self.assertRaises(TypeError) as cm: 420 __import__('encodings', fromlist=[u'aliases']) 421 self.assertIn('must be str, not unicode', str(cm.exception)) 422 with self.assertRaises(TypeError) as cm: 423 __import__('encodings', fromlist=[1]) 424 self.assertIn('must be str, not int', str(cm.exception)) 425 426 427class PycRewritingTests(unittest.TestCase): 428 # Test that the `co_filename` attribute on code objects always points 429 # to the right file, even when various things happen (e.g. both the .py 430 # and the .pyc file are renamed). 431 432 module_name = "unlikely_module_name" 433 module_source = """ 434import sys 435code_filename = sys._getframe().f_code.co_filename 436module_filename = __file__ 437constant = 1 438def func(): 439 pass 440func_filename = func.func_code.co_filename 441""" 442 dir_name = os.path.abspath(TESTFN) 443 file_name = os.path.join(dir_name, module_name) + os.extsep + "py" 444 compiled_name = file_name + ("c" if __debug__ else "o") 445 446 def setUp(self): 447 self.sys_path = sys.path[:] 448 self.orig_module = sys.modules.pop(self.module_name, None) 449 os.mkdir(self.dir_name) 450 with open(self.file_name, "w") as f: 451 f.write(self.module_source) 452 sys.path.insert(0, self.dir_name) 453 454 def tearDown(self): 455 sys.path[:] = self.sys_path 456 if self.orig_module is not None: 457 sys.modules[self.module_name] = self.orig_module 458 else: 459 unload(self.module_name) 460 unlink(self.file_name) 461 unlink(self.compiled_name) 462 rmtree(self.dir_name) 463 464 def import_module(self): 465 ns = globals() 466 __import__(self.module_name, ns, ns) 467 return sys.modules[self.module_name] 468 469 def test_basics(self): 470 mod = self.import_module() 471 self.assertEqual(mod.module_filename, self.file_name) 472 self.assertEqual(mod.code_filename, self.file_name) 473 self.assertEqual(mod.func_filename, self.file_name) 474 del sys.modules[self.module_name] 475 mod = self.import_module() 476 if not sys.dont_write_bytecode: 477 self.assertEqual(mod.module_filename, self.compiled_name) 478 self.assertEqual(mod.code_filename, self.file_name) 479 self.assertEqual(mod.func_filename, self.file_name) 480 481 def test_incorrect_code_name(self): 482 py_compile.compile(self.file_name, dfile="another_module.py") 483 mod = self.import_module() 484 self.assertEqual(mod.module_filename, self.compiled_name) 485 self.assertEqual(mod.code_filename, self.file_name) 486 self.assertEqual(mod.func_filename, self.file_name) 487 488 def test_module_without_source(self): 489 target = "another_module.py" 490 py_compile.compile(self.file_name, dfile=target) 491 os.remove(self.file_name) 492 mod = self.import_module() 493 self.assertEqual(mod.module_filename, self.compiled_name) 494 self.assertEqual(mod.code_filename, target) 495 self.assertEqual(mod.func_filename, target) 496 497 def test_foreign_code(self): 498 py_compile.compile(self.file_name) 499 with open(self.compiled_name, "rb") as f: 500 header = f.read(8) 501 code = marshal.load(f) 502 constants = list(code.co_consts) 503 foreign_code = test_main.func_code 504 pos = constants.index(1) 505 constants[pos] = foreign_code 506 code = type(code)(code.co_argcount, code.co_nlocals, code.co_stacksize, 507 code.co_flags, code.co_code, tuple(constants), 508 code.co_names, code.co_varnames, code.co_filename, 509 code.co_name, code.co_firstlineno, code.co_lnotab, 510 code.co_freevars, code.co_cellvars) 511 with open(self.compiled_name, "wb") as f: 512 f.write(header) 513 marshal.dump(code, f) 514 mod = self.import_module() 515 self.assertEqual(mod.constant.co_filename, foreign_code.co_filename) 516 517 518class PathsTests(unittest.TestCase): 519 path = TESTFN 520 521 def setUp(self): 522 os.mkdir(self.path) 523 self.syspath = sys.path[:] 524 525 def tearDown(self): 526 rmtree(self.path) 527 sys.path[:] = self.syspath 528 529 # Regression test for http://bugs.python.org/issue1293. 530 def test_trailing_slash(self): 531 with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f: 532 f.write("testdata = 'test_trailing_slash'") 533 sys.path.append(self.path+'/') 534 mod = __import__("test_trailing_slash") 535 self.assertEqual(mod.testdata, 'test_trailing_slash') 536 unload("test_trailing_slash") 537 538 # Regression test for http://bugs.python.org/issue3677. 539 def _test_UNC_path(self): 540 with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f: 541 f.write("testdata = 'test_trailing_slash'") 542 # Create the UNC path, like \\myhost\c$\foo\bar. 543 path = os.path.abspath(self.path) 544 import socket 545 hn = socket.gethostname() 546 drive = path[0] 547 unc = "\\\\%s\\%s$"%(hn, drive) 548 unc += path[2:] 549 try: 550 os.listdir(unc) 551 except OSError as e: 552 if e.errno in (errno.EPERM, errno.EACCES): 553 # See issue #15338 554 self.skipTest("cannot access administrative share %r" % (unc,)) 555 raise 556 sys.path.append(path) 557 mod = __import__("test_trailing_slash") 558 self.assertEqual(mod.testdata, 'test_trailing_slash') 559 unload("test_trailing_slash") 560 561 if sys.platform == "win32": 562 test_UNC_path = _test_UNC_path 563 564 565class RelativeImportTests(unittest.TestCase): 566 567 def tearDown(self): 568 unload("test.relimport") 569 setUp = tearDown 570 571 def test_relimport_star(self): 572 # This will import * from .test_import. 573 from . import relimport 574 self.assertTrue(hasattr(relimport, "RelativeImportTests")) 575 576 def test_issue3221(self): 577 # Regression test for http://bugs.python.org/issue3221. 578 def check_absolute(): 579 exec "from os import path" in ns 580 def check_relative(): 581 exec "from . import relimport" in ns 582 583 # Check both OK with __package__ and __name__ correct 584 ns = dict(__package__='test', __name__='test.notarealmodule') 585 check_absolute() 586 check_relative() 587 588 # Check both OK with only __name__ wrong 589 ns = dict(__package__='test', __name__='notarealpkg.notarealmodule') 590 check_absolute() 591 check_relative() 592 593 # Check relative fails with only __package__ wrong 594 ns = dict(__package__='foo', __name__='test.notarealmodule') 595 with check_warnings(('.+foo', RuntimeWarning)): 596 check_absolute() 597 self.assertRaises(SystemError, check_relative) 598 599 # Check relative fails with __package__ and __name__ wrong 600 ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule') 601 with check_warnings(('.+foo', RuntimeWarning)): 602 check_absolute() 603 self.assertRaises(SystemError, check_relative) 604 605 # Check both fail with package set to a non-string 606 ns = dict(__package__=object()) 607 self.assertRaises(ValueError, check_absolute) 608 self.assertRaises(ValueError, check_relative) 609 610 def test_absolute_import_without_future(self): 611 # If explicit relative import syntax is used, then do not try 612 # to perform an absolute import in the face of failure. 613 # Issue #7902. 614 with self.assertRaises(ImportError): 615 from .os import sep 616 self.fail("explicit relative import triggered an " 617 "implicit absolute import") 618 619 620class TestSymbolicallyLinkedPackage(unittest.TestCase): 621 package_name = 'sample' 622 623 def setUp(self): 624 if os.path.exists(self.tagged): 625 shutil.rmtree(self.tagged) 626 if os.path.exists(self.package_name): 627 symlink_support.remove_symlink(self.package_name) 628 self.orig_sys_path = sys.path[:] 629 630 # create a sample package; imagine you have a package with a tag and 631 # you want to symbolically link it from its untagged name. 632 os.mkdir(self.tagged) 633 init_file = os.path.join(self.tagged, '__init__.py') 634 open(init_file, 'w').close() 635 assert os.path.exists(init_file) 636 637 # now create a symlink to the tagged package 638 # sample -> sample-tagged 639 symlink_support.symlink(self.tagged, self.package_name) 640 641 assert os.path.isdir(self.package_name) 642 assert os.path.isfile(os.path.join(self.package_name, '__init__.py')) 643 644 @property 645 def tagged(self): 646 return self.package_name + '-tagged' 647 648 # regression test for issue6727 649 @unittest.skipUnless( 650 not hasattr(sys, 'getwindowsversion') 651 or sys.getwindowsversion() >= (6, 0), 652 "Windows Vista or later required") 653 @symlink_support.skip_unless_symlink 654 def test_symlinked_dir_importable(self): 655 # make sure sample can only be imported from the current directory. 656 sys.path[:] = ['.'] 657 658 # and try to import the package 659 __import__(self.package_name) 660 661 def tearDown(self): 662 # now cleanup 663 if os.path.exists(self.package_name): 664 symlink_support.remove_symlink(self.package_name) 665 if os.path.exists(self.tagged): 666 shutil.rmtree(self.tagged) 667 sys.path[:] = self.orig_sys_path 668 669def test_main(verbose=None): 670 run_unittest(ImportTests, PycRewritingTests, PathsTests, 671 RelativeImportTests, TestSymbolicallyLinkedPackage) 672 673if __name__ == '__main__': 674 # Test needs to be a package, so we can do relative imports. 675 from test.test_import import test_main 676 test_main() 677