Home | History | Annotate | Download | only in test
      1 import imp
      2 import marshal
      3 import os
      4 import py_compile
      5 import random
      6 import stat
      7 import sys
      8 import unittest
      9 from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree,
     10                                is_jython, check_warnings, EnvironmentVarGuard)
     11 import textwrap
     12 from test import script_helper
     13 
     14 def remove_files(name):
     15     for f in (name + os.extsep + "py",
     16               name + os.extsep + "pyc",
     17               name + os.extsep + "pyo",
     18               name + os.extsep + "pyw",
     19               name + "$py.class"):
     20         unlink(f)
     21 
     22 
     23 class ImportTests(unittest.TestCase):
     24 
     25     def tearDown(self):
     26         unload(TESTFN)
     27     setUp = tearDown
     28 
     29     def test_case_sensitivity(self):
     30         # Brief digression to test that import is case-sensitive:  if we got

     31         # this far, we know for sure that "random" exists.

     32         try:
     33             import RAnDoM
     34         except ImportError:
     35             pass
     36         else:
     37             self.fail("import of RAnDoM should have failed (case mismatch)")
     38 
     39     def test_double_const(self):
     40         # Another brief digression to test the accuracy of manifest float

     41         # constants.

     42         from test import double_const  # don't blink -- that *was* the test

     43 
     44     def test_import(self):
     45         def test_with_extension(ext):
     46             # The extension is normally ".py", perhaps ".pyw".

     47             source = TESTFN + ext
     48             pyo = TESTFN + os.extsep + "pyo"
     49             if is_jython:
     50                 pyc = TESTFN + "$py.class"
     51             else:
     52                 pyc = TESTFN + os.extsep + "pyc"
     53 
     54             with open(source, "w") as f:
     55                 print >> f, ("# This tests Python's ability to import a", ext,
     56                              "file.")
     57                 a = random.randrange(1000)
     58                 b = random.randrange(1000)
     59                 print >> f, "a =", a
     60                 print >> f, "b =", b
     61 
     62             try:
     63                 mod = __import__(TESTFN)
     64             except ImportError, err:
     65                 self.fail("import from %s failed: %s" % (ext, err))
     66             else:
     67                 self.assertEqual(mod.a, a,
     68                     "module loaded (%s) but contents invalid" % mod)
     69                 self.assertEqual(mod.b, b,
     70                     "module loaded (%s) but contents invalid" % mod)
     71             finally:
     72                 unlink(source)
     73 
     74             try:
     75                 imp.reload(mod)
     76             except ImportError, err:
     77                 self.fail("import from .pyc/.pyo failed: %s" % err)
     78             finally:
     79                 unlink(pyc)
     80                 unlink(pyo)
     81                 unload(TESTFN)
     82 
     83         sys.path.insert(0, os.curdir)
     84         try:
     85             test_with_extension(os.extsep + "py")
     86             if sys.platform.startswith("win"):
     87                 for ext in [".PY", ".Py", ".pY", ".pyw", ".PYW", ".pYw"]:
     88                     test_with_extension(ext)
     89         finally:
     90             del sys.path[0]
     91 
     92     @unittest.skipUnless(os.name == 'posix', "test meaningful only on posix systems")
     93     def test_execute_bit_not_copied(self):
     94         # Issue 6070: under posix .pyc files got their execute bit set if

     95         # the .py file had the execute bit set, but they aren't executable.

     96         oldmask = os.umask(022)
     97         sys.path.insert(0, os.curdir)
     98         try:
     99             fname = TESTFN + os.extsep + "py"
    100             f = open(fname, 'w').close()
    101             os.chmod(fname, (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH |
    102                              stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH))
    103             __import__(TESTFN)
    104             fn = fname + 'c'
    105             if not os.path.exists(fn):
    106                 fn = fname + 'o'
    107                 if not os.path.exists(fn):
    108                     self.fail("__import__ did not result in creation of "
    109                               "either a .pyc or .pyo file")
    110             s = os.stat(fn)
    111             self.assertEqual(stat.S_IMODE(s.st_mode),
    112                              stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
    113         finally:
    114             os.umask(oldmask)
    115             remove_files(TESTFN)
    116             unload(TESTFN)
    117             del sys.path[0]
    118 
    119     def test_imp_module(self):
    120         # Verify that the imp module can correctly load and find .py files

    121 
    122         # XXX (ncoghlan): It would be nice to use test_support.CleanImport

    123         # here, but that breaks because the os module registers some

    124         # handlers in copy_reg on import. Since CleanImport doesn't

    125         # revert that registration, the module is left in a broken

    126         # state after reversion. Reinitialising the module contents

    127         # and just reverting os.environ to its previous state is an OK

    128         # workaround

    129         orig_path = os.path
    130         orig_getenv = os.getenv
    131         with EnvironmentVarGuard():
    132             x = imp.find_module("os")
    133             new_os = imp.load_module("os", *x)
    134             self.assertIs(os, new_os)
    135             self.assertIs(orig_path, new_os.path)
    136             self.assertIsNot(orig_getenv, new_os.getenv)
    137 
    138     def test_module_with_large_stack(self, module='longlist'):
    139         # Regression test for http://bugs.python.org/issue561858.

    140         filename = module + os.extsep + 'py'
    141 
    142         # Create a file with a list of 65000 elements.

    143         with open(filename, 'w+') as f:
    144             f.write('d = [\n')
    145             for i in range(65000):
    146                 f.write('"",\n')
    147             f.write(']')
    148 
    149         # Compile & remove .py file, we only need .pyc (or .pyo).

    150         with open(filename, 'r') as f:
    151             py_compile.compile(filename)
    152         unlink(filename)
    153 
    154         # Need to be able to load from current dir.

    155         sys.path.append('')
    156 
    157         # This used to crash.

    158         exec 'import ' + module
    159 
    160         # Cleanup.

    161         del sys.path[-1]
    162         unlink(filename + 'c')
    163         unlink(filename + 'o')
    164 
    165     def test_failing_import_sticks(self):
    166         source = TESTFN + os.extsep + "py"
    167         with open(source, "w") as f:
    168             print >> f, "a = 1 // 0"
    169 
    170         # New in 2.4, we shouldn't be able to import that no matter how often

    171         # we try.

    172         sys.path.insert(0, os.curdir)
    173         try:
    174             for i in [1, 2, 3]:
    175                 self.assertRaises(ZeroDivisionError, __import__, TESTFN)
    176                 self.assertNotIn(TESTFN, sys.modules,
    177                                  "damaged module in sys.modules on %i try" % i)
    178         finally:
    179             del sys.path[0]
    180             remove_files(TESTFN)
    181 
    182     def test_failing_reload(self):
    183         # A failing reload should leave the module object in sys.modules.

    184         source = TESTFN + os.extsep + "py"
    185         with open(source, "w") as f:
    186             print >> f, "a = 1"
    187             print >> f, "b = 2"
    188 
    189         sys.path.insert(0, os.curdir)
    190         try:
    191             mod = __import__(TESTFN)
    192             self.assertIn(TESTFN, sys.modules)
    193             self.assertEqual(mod.a, 1, "module has wrong attribute values")
    194             self.assertEqual(mod.b, 2, "module has wrong attribute values")
    195 
    196             # On WinXP, just replacing the .py file wasn't enough to

    197             # convince reload() to reparse it.  Maybe the timestamp didn't

    198             # move enough.  We force it to get reparsed by removing the

    199             # compiled file too.

    200             remove_files(TESTFN)
    201 
    202             # Now damage the module.

    203             with open(source, "w") as f:
    204                 print >> f, "a = 10"
    205                 print >> f, "b = 20//0"
    206 
    207             self.assertRaises(ZeroDivisionError, imp.reload, mod)
    208 
    209             # But we still expect the module to be in sys.modules.

    210             mod = sys.modules.get(TESTFN)
    211             self.assertIsNot(mod, None, "expected module to be in sys.modules")
    212 
    213             # We should have replaced a w/ 10, but the old b value should

    214             # stick.

    215             self.assertEqual(mod.a, 10, "module has wrong attribute values")
    216             self.assertEqual(mod.b, 2, "module has wrong attribute values")
    217 
    218         finally:
    219             del sys.path[0]
    220             remove_files(TESTFN)
    221             unload(TESTFN)
    222 
    223     def test_infinite_reload(self):
    224         # http://bugs.python.org/issue742342 reports that Python segfaults

    225         # (infinite recursion in C) when faced with self-recursive reload()ing.

    226 
    227         sys.path.insert(0, os.path.dirname(__file__))
    228         try:
    229             import infinite_reload
    230         finally:
    231             del sys.path[0]
    232 
    233     def test_import_name_binding(self):
    234         # import x.y.z binds x in the current namespace.

    235         import test as x
    236         import test.test_support
    237         self.assertIs(x, test, x.__name__)
    238         self.assertTrue(hasattr(test.test_support, "__file__"))
    239 
    240         # import x.y.z as w binds z as w.

    241         import test.test_support as y
    242         self.assertIs(y, test.test_support, y.__name__)
    243 
    244     def test_import_initless_directory_warning(self):
    245         with check_warnings(('', ImportWarning)):
    246             # Just a random non-package directory we always expect to be

    247             # somewhere in sys.path...

    248             self.assertRaises(ImportError, __import__, "site-packages")
    249 
    250     def test_import_by_filename(self):
    251         path = os.path.abspath(TESTFN)
    252         with self.assertRaises(ImportError) as c:
    253             __import__(path)
    254         self.assertEqual("Import by filename is not supported.",
    255                          c.exception.args[0])
    256 
    257     def test_import_in_del_does_not_crash(self):
    258         # Issue 4236

    259         testfn = script_helper.make_script('', TESTFN, textwrap.dedent("""\
    260             import sys
    261             class C:
    262                def __del__(self):
    263                   import imp
    264             sys.argv.insert(0, C())
    265             """))
    266         script_helper.assert_python_ok(testfn)
    267 
    268 
    269 class PycRewritingTests(unittest.TestCase):
    270     # Test that the `co_filename` attribute on code objects always points

    271     # to the right file, even when various things happen (e.g. both the .py

    272     # and the .pyc file are renamed).

    273 
    274     module_name = "unlikely_module_name"
    275     module_source = """
    276 import sys
    277 code_filename = sys._getframe().f_code.co_filename
    278 module_filename = __file__
    279 constant = 1
    280 def func():
    281     pass
    282 func_filename = func.func_code.co_filename
    283 """
    284     dir_name = os.path.abspath(TESTFN)
    285     file_name = os.path.join(dir_name, module_name) + os.extsep + "py"
    286     compiled_name = file_name + ("c" if __debug__ else "o")
    287 
    288     def setUp(self):
    289         self.sys_path = sys.path[:]
    290         self.orig_module = sys.modules.pop(self.module_name, None)
    291         os.mkdir(self.dir_name)
    292         with open(self.file_name, "w") as f:
    293             f.write(self.module_source)
    294         sys.path.insert(0, self.dir_name)
    295 
    296     def tearDown(self):
    297         sys.path[:] = self.sys_path
    298         if self.orig_module is not None:
    299             sys.modules[self.module_name] = self.orig_module
    300         else:
    301             unload(self.module_name)
    302         unlink(self.file_name)
    303         unlink(self.compiled_name)
    304         rmtree(self.dir_name)
    305 
    306     def import_module(self):
    307         ns = globals()
    308         __import__(self.module_name, ns, ns)
    309         return sys.modules[self.module_name]
    310 
    311     def test_basics(self):
    312         mod = self.import_module()
    313         self.assertEqual(mod.module_filename, self.file_name)
    314         self.assertEqual(mod.code_filename, self.file_name)
    315         self.assertEqual(mod.func_filename, self.file_name)
    316         del sys.modules[self.module_name]
    317         mod = self.import_module()
    318         self.assertEqual(mod.module_filename, self.compiled_name)
    319         self.assertEqual(mod.code_filename, self.file_name)
    320         self.assertEqual(mod.func_filename, self.file_name)
    321 
    322     def test_incorrect_code_name(self):
    323         py_compile.compile(self.file_name, dfile="another_module.py")
    324         mod = self.import_module()
    325         self.assertEqual(mod.module_filename, self.compiled_name)
    326         self.assertEqual(mod.code_filename, self.file_name)
    327         self.assertEqual(mod.func_filename, self.file_name)
    328 
    329     def test_module_without_source(self):
    330         target = "another_module.py"
    331         py_compile.compile(self.file_name, dfile=target)
    332         os.remove(self.file_name)
    333         mod = self.import_module()
    334         self.assertEqual(mod.module_filename, self.compiled_name)
    335         self.assertEqual(mod.code_filename, target)
    336         self.assertEqual(mod.func_filename, target)
    337 
    338     def test_foreign_code(self):
    339         py_compile.compile(self.file_name)
    340         with open(self.compiled_name, "rb") as f:
    341             header = f.read(8)
    342             code = marshal.load(f)
    343         constants = list(code.co_consts)
    344         foreign_code = test_main.func_code
    345         pos = constants.index(1)
    346         constants[pos] = foreign_code
    347         code = type(code)(code.co_argcount, code.co_nlocals, code.co_stacksize,
    348                           code.co_flags, code.co_code, tuple(constants),
    349                           code.co_names, code.co_varnames, code.co_filename,
    350                           code.co_name, code.co_firstlineno, code.co_lnotab,
    351                           code.co_freevars, code.co_cellvars)
    352         with open(self.compiled_name, "wb") as f:
    353             f.write(header)
    354             marshal.dump(code, f)
    355         mod = self.import_module()
    356         self.assertEqual(mod.constant.co_filename, foreign_code.co_filename)
    357 
    358 
    359 class PathsTests(unittest.TestCase):
    360     path = TESTFN
    361 
    362     def setUp(self):
    363         os.mkdir(self.path)
    364         self.syspath = sys.path[:]
    365 
    366     def tearDown(self):
    367         rmtree(self.path)
    368         sys.path[:] = self.syspath
    369 
    370     # Regression test for http://bugs.python.org/issue1293.

    371     def test_trailing_slash(self):
    372         with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f:
    373             f.write("testdata = 'test_trailing_slash'")
    374         sys.path.append(self.path+'/')
    375         mod = __import__("test_trailing_slash")
    376         self.assertEqual(mod.testdata, 'test_trailing_slash')
    377         unload("test_trailing_slash")
    378 
    379     # Regression test for http://bugs.python.org/issue3677.

    380     def _test_UNC_path(self):
    381         with open(os.path.join(self.path, 'test_trailing_slash.py'), 'w') as f:
    382             f.write("testdata = 'test_trailing_slash'")
    383         # Create the UNC path, like \\myhost\c$\foo\bar.

    384         path = os.path.abspath(self.path)
    385         import socket
    386         hn = socket.gethostname()
    387         drive = path[0]
    388         unc = "\\\\%s\\%s$"%(hn, drive)
    389         unc += path[2:]
    390         sys.path.append(path)
    391         mod = __import__("test_trailing_slash")
    392         self.assertEqual(mod.testdata, 'test_trailing_slash')
    393         unload("test_trailing_slash")
    394 
    395     if sys.platform == "win32":
    396         test_UNC_path = _test_UNC_path
    397 
    398 
    399 class RelativeImportTests(unittest.TestCase):
    400 
    401     def tearDown(self):
    402         unload("test.relimport")
    403     setUp = tearDown
    404 
    405     def test_relimport_star(self):
    406         # This will import * from .test_import.

    407         from . import relimport
    408         self.assertTrue(hasattr(relimport, "RelativeImportTests"))
    409 
    410     def test_issue3221(self):
    411         # Regression test for http://bugs.python.org/issue3221.

    412         def check_absolute():
    413             exec "from os import path" in ns
    414         def check_relative():
    415             exec "from . import relimport" in ns
    416 
    417         # Check both OK with __package__ and __name__ correct

    418         ns = dict(__package__='test', __name__='test.notarealmodule')
    419         check_absolute()
    420         check_relative()
    421 
    422         # Check both OK with only __name__ wrong

    423         ns = dict(__package__='test', __name__='notarealpkg.notarealmodule')
    424         check_absolute()
    425         check_relative()
    426 
    427         # Check relative fails with only __package__ wrong

    428         ns = dict(__package__='foo', __name__='test.notarealmodule')
    429         with check_warnings(('.+foo', RuntimeWarning)):
    430             check_absolute()
    431         self.assertRaises(SystemError, check_relative)
    432 
    433         # Check relative fails with __package__ and __name__ wrong

    434         ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule')
    435         with check_warnings(('.+foo', RuntimeWarning)):
    436             check_absolute()
    437         self.assertRaises(SystemError, check_relative)
    438 
    439         # Check both fail with package set to a non-string

    440         ns = dict(__package__=object())
    441         self.assertRaises(ValueError, check_absolute)
    442         self.assertRaises(ValueError, check_relative)
    443 
    444     def test_absolute_import_without_future(self):
    445         # If explicit relative import syntax is used, then do not try

    446         # to perform an absolute import in the face of failure.

    447         # Issue #7902.

    448         with self.assertRaises(ImportError):
    449             from .os import sep
    450             self.fail("explicit relative import triggered an "
    451                       "implicit absolute import")
    452 
    453 
    454 def test_main(verbose=None):
    455     run_unittest(ImportTests, PycRewritingTests, PathsTests, RelativeImportTests)
    456 
    457 if __name__ == '__main__':
    458     # Test needs to be a package, so we can do relative imports.

    459     from test.test_import import test_main
    460     test_main()
    461