1 import errno 2 import imp 3 import marshal 4 import os 5 import py_compile 6 import random 7 import stat 8 import struct 9 import sys 10 import unittest 11 import textwrap 12 import shutil 13 14 from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree, 15 is_jython, check_warnings, EnvironmentVarGuard) 16 from test import symlink_support 17 from test import script_helper 18 19 def _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 26 def 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 34 def remove_files(name): 35 for f in _files(name): 36 unlink(f) 37 38 39 class 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 401 class PycRewritingTests(unittest.TestCase): 402 # Test that the `co_filename` attribute on code objects always points 403 # to the right file, even when various things happen (e.g. both the .py 404 # and the .pyc file are renamed). 405 406 module_name = "unlikely_module_name" 407 module_source = """ 408 import sys 409 code_filename = sys._getframe().f_code.co_filename 410 module_filename = __file__ 411 constant = 1 412 def func(): 413 pass 414 func_filename = func.func_code.co_filename 415 """ 416 dir_name = os.path.abspath(TESTFN) 417 file_name = os.path.join(dir_name, module_name) + os.extsep + "py" 418 compiled_name = file_name + ("c" if __debug__ else "o") 419 420 def setUp(self): 421 self.sys_path = sys.path[:] 422 self.orig_module = sys.modules.pop(self.module_name, None) 423 os.mkdir(self.dir_name) 424 with open(self.file_name, "w") as f: 425 f.write(self.module_source) 426 sys.path.insert(0, self.dir_name) 427 428 def tearDown(self): 429 sys.path[:] = self.sys_path 430 if self.orig_module is not None: 431 sys.modules[self.module_name] = self.orig_module 432 else: 433 unload(self.module_name) 434 unlink(self.file_name) 435 unlink(self.compiled_name) 436 rmtree(self.dir_name) 437 438 def import_module(self): 439 ns = globals() 440 __import__(self.module_name, ns, ns) 441 return sys.modules[self.module_name] 442 443 def test_basics(self): 444 mod = self.import_module() 445 self.assertEqual(mod.module_filename, self.file_name) 446 self.assertEqual(mod.code_filename, self.file_name) 447 self.assertEqual(mod.func_filename, self.file_name) 448 del sys.modules[self.module_name] 449 mod = self.import_module() 450 if not sys.dont_write_bytecode: 451 self.assertEqual(mod.module_filename, self.compiled_name) 452 self.assertEqual(mod.code_filename, self.file_name) 453 self.assertEqual(mod.func_filename, self.file_name) 454 455 def test_incorrect_code_name(self): 456 py_compile.compile(self.file_name, dfile="another_module.py") 457 mod = self.import_module() 458 self.assertEqual(mod.module_filename, self.compiled_name) 459 self.assertEqual(mod.code_filename, self.file_name) 460 self.assertEqual(mod.func_filename, self.file_name) 461 462 def test_module_without_source(self): 463 target = "another_module.py" 464 py_compile.compile(self.file_name, dfile=target) 465 os.remove(self.file_name) 466 mod = self.import_module() 467 self.assertEqual(mod.module_filename, self.compiled_name) 468 self.assertEqual(mod.code_filename, target) 469 self.assertEqual(mod.func_filename, target) 470 471 def test_foreign_code(self): 472 py_compile.compile(self.file_name) 473 with open(self.compiled_name, "rb") as f: 474 header = f.read(8) 475 code = marshal.load(f) 476 constants = list(code.co_consts) 477 foreign_code = test_main.func_code 478 pos = constants.index(1) 479 constants[pos] = foreign_code 480 code = type(code)(code.co_argcount, code.co_nlocals, code.co_stacksize, 481 code.co_flags, code.co_code, tuple(constants), 482 code.co_names, code.co_varnames, code.co_filename, 483 code.co_name, code.co_firstlineno, code.co_lnotab, 484 code.co_freevars, code.co_cellvars) 485 with open(self.compiled_name, "wb") as f: 486 f.write(header) 487 marshal.dump(code, f) 488 mod = self.import_module() 489 self.assertEqual(mod.constant.co_filename, foreign_code.co_filename) 490 491 492 class PathsTests(unittest.TestCase): 493 path = TESTFN 494 495 def setUp(self): 496 os.mkdir(self.path) 497 self.syspath = sys.path[:] 498 499 def tearDown(self): 500 rmtree(self.path) 501 sys.path[:] = self.syspath 502 503 # Regression test for http://bugs.python.org/issue1293. 504 def test_trailing_slash(self): 505 with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f: 506 f.write("testdata = 'test_trailing_slash'") 507 sys.path.append(self.path+'/') 508 mod = __import__("test_trailing_slash") 509 self.assertEqual(mod.testdata, 'test_trailing_slash') 510 unload("test_trailing_slash") 511 512 # Regression test for http://bugs.python.org/issue3677. 513 def _test_UNC_path(self): 514 with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f: 515 f.write("testdata = 'test_trailing_slash'") 516 # Create the UNC path, like \\myhost\c$\foo\bar. 517 path = os.path.abspath(self.path) 518 import socket 519 hn = socket.gethostname() 520 drive = path[0] 521 unc = "\\\\%s\\%s$"%(hn, drive) 522 unc += path[2:] 523 try: 524 os.listdir(unc) 525 except OSError as e: 526 if e.errno in (errno.EPERM, errno.EACCES): 527 # See issue #15338 528 self.skipTest("cannot access administrative share %r" % (unc,)) 529 raise 530 sys.path.append(path) 531 mod = __import__("test_trailing_slash") 532 self.assertEqual(mod.testdata, 'test_trailing_slash') 533 unload("test_trailing_slash") 534 535 if sys.platform == "win32": 536 test_UNC_path = _test_UNC_path 537 538 539 class RelativeImportTests(unittest.TestCase): 540 541 def tearDown(self): 542 unload("test.relimport") 543 setUp = tearDown 544 545 def test_relimport_star(self): 546 # This will import * from .test_import. 547 from . import relimport 548 self.assertTrue(hasattr(relimport, "RelativeImportTests")) 549 550 def test_issue3221(self): 551 # Regression test for http://bugs.python.org/issue3221. 552 def check_absolute(): 553 exec "from os import path" in ns 554 def check_relative(): 555 exec "from . import relimport" in ns 556 557 # Check both OK with __package__ and __name__ correct 558 ns = dict(__package__='test', __name__='test.notarealmodule') 559 check_absolute() 560 check_relative() 561 562 # Check both OK with only __name__ wrong 563 ns = dict(__package__='test', __name__='notarealpkg.notarealmodule') 564 check_absolute() 565 check_relative() 566 567 # Check relative fails with only __package__ wrong 568 ns = dict(__package__='foo', __name__='test.notarealmodule') 569 with check_warnings(('.+foo', RuntimeWarning)): 570 check_absolute() 571 self.assertRaises(SystemError, check_relative) 572 573 # Check relative fails with __package__ and __name__ wrong 574 ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule') 575 with check_warnings(('.+foo', RuntimeWarning)): 576 check_absolute() 577 self.assertRaises(SystemError, check_relative) 578 579 # Check both fail with package set to a non-string 580 ns = dict(__package__=object()) 581 self.assertRaises(ValueError, check_absolute) 582 self.assertRaises(ValueError, check_relative) 583 584 def test_absolute_import_without_future(self): 585 # If explicit relative import syntax is used, then do not try 586 # to perform an absolute import in the face of failure. 587 # Issue #7902. 588 with self.assertRaises(ImportError): 589 from .os import sep 590 self.fail("explicit relative import triggered an " 591 "implicit absolute import") 592 593 594 class TestSymbolicallyLinkedPackage(unittest.TestCase): 595 package_name = 'sample' 596 597 def setUp(self): 598 if os.path.exists(self.tagged): 599 shutil.rmtree(self.tagged) 600 if os.path.exists(self.package_name): 601 symlink_support.remove_symlink(self.package_name) 602 self.orig_sys_path = sys.path[:] 603 604 # create a sample package; imagine you have a package with a tag and 605 # you want to symbolically link it from its untagged name. 606 os.mkdir(self.tagged) 607 init_file = os.path.join(self.tagged, '__init__.py') 608 open(init_file, 'w').close() 609 assert os.path.exists(init_file) 610 611 # now create a symlink to the tagged package 612 # sample -> sample-tagged 613 symlink_support.symlink(self.tagged, self.package_name) 614 615 assert os.path.isdir(self.package_name) 616 assert os.path.isfile(os.path.join(self.package_name, '__init__.py')) 617 618 @property 619 def tagged(self): 620 return self.package_name + '-tagged' 621 622 # regression test for issue6727 623 @unittest.skipUnless( 624 not hasattr(sys, 'getwindowsversion') 625 or sys.getwindowsversion() >= (6, 0), 626 "Windows Vista or later required") 627 @symlink_support.skip_unless_symlink 628 def test_symlinked_dir_importable(self): 629 # make sure sample can only be imported from the current directory. 630 sys.path[:] = ['.'] 631 632 # and try to import the package 633 __import__(self.package_name) 634 635 def tearDown(self): 636 # now cleanup 637 if os.path.exists(self.package_name): 638 symlink_support.remove_symlink(self.package_name) 639 if os.path.exists(self.tagged): 640 shutil.rmtree(self.tagged) 641 sys.path[:] = self.orig_sys_path 642 643 def test_main(verbose=None): 644 run_unittest(ImportTests, PycRewritingTests, PathsTests, 645 RelativeImportTests, TestSymbolicallyLinkedPackage) 646 647 if __name__ == '__main__': 648 # Test needs to be a package, so we can do relative imports. 649 from test.test_import import test_main 650 test_main() 651