/Lib/test/test_import.py

http://unladen-swallow.googlecode.com/ · Python · 470 lines · 357 code · 66 blank · 47 comment · 77 complexity · 1de78128b6d63d6f65e3ce71a28fbaf1 MD5 · raw file

  1. import __builtin__
  2. import os
  3. import stat
  4. import random
  5. import shutil
  6. import sys
  7. import unittest
  8. import py_compile
  9. import warnings
  10. import marshal
  11. from test import test_support
  12. from test.test_support import (unlink, TESTFN, unload, run_unittest,
  13. check_warnings, TestFailed)
  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. if os.path.exists(f):
  21. os.remove(f)
  22. class ImportTests(unittest.TestCase):
  23. def test_case_sensitivity(self):
  24. # Brief digression to test that import is case-sensitive: if we got
  25. # this far, we know for sure that "random" exists.
  26. try:
  27. import RAnDoM
  28. except ImportError:
  29. pass
  30. else:
  31. self.fail("import of RAnDoM should have failed (case mismatch)")
  32. def test_double_const(self):
  33. # Another brief digression to test the accuracy of manifest float
  34. # constants.
  35. from test import double_const # Don't blink -- that *was* the test.
  36. def test_import(self):
  37. def test_with_extension(ext):
  38. # The extension is normally ".py"; perhaps ".pyw".
  39. source = test_support.TESTFN + ext
  40. pyo = test_support.TESTFN + os.extsep + "pyo"
  41. if sys.platform.startswith('java'):
  42. pyc = test_support.TESTFN + "$py.class"
  43. else:
  44. pyc = test_support.TESTFN + os.extsep + "pyc"
  45. f = open(source, "w")
  46. try:
  47. print >> f, "# This tests importing a", ext, "file"
  48. a = random.randrange(1000)
  49. b = random.randrange(1000)
  50. print >> f, "a =", a
  51. print >> f, "b =", b
  52. finally:
  53. f.close()
  54. try:
  55. try:
  56. mod = __import__(test_support.TESTFN)
  57. except ImportError, err:
  58. self.fail("import from %s failed: %s" % (ext, err))
  59. self.assertEquals(mod.a, a,
  60. "module loaded (%s) but contents invalid" % mod)
  61. self.assertEquals(mod.b, b,
  62. "module loaded (%s) but contents invalid" % mod)
  63. finally:
  64. os.unlink(source)
  65. try:
  66. reload(mod)
  67. except ImportError, err:
  68. self.fail("import from .pyc/.pyo failed: %s" % err)
  69. finally:
  70. try:
  71. os.unlink(pyc)
  72. except OSError:
  73. pass
  74. try:
  75. os.unlink(pyo)
  76. except OSError:
  77. pass
  78. del sys.modules[test_support.TESTFN]
  79. sys.path.insert(0, os.curdir)
  80. try:
  81. test_with_extension(os.extsep + "py")
  82. if sys.platform.startswith("win"):
  83. for ext in [".PY", ".Py", ".pY", ".pyw", ".PYW", ".pYw"]:
  84. test_with_extension(ext)
  85. finally:
  86. del sys.path[0]
  87. if os.name == 'posix':
  88. def test_execute_bit_not_copied(self):
  89. # Issue 6070: under posix .pyc files got their execute bit set if
  90. # the .py file had the execute bit set, but they aren't executable.
  91. oldmask = os.umask(022)
  92. sys.path.insert(0, os.curdir)
  93. try:
  94. fname = TESTFN + os.extsep + "py"
  95. f = open(fname, 'w').close()
  96. os.chmod(fname, (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH |
  97. stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH))
  98. __import__(TESTFN)
  99. fn = fname + 'c'
  100. if not os.path.exists(fn):
  101. fn = fname + 'o'
  102. if not os.path.exists(fn): raise TestFailed("__import__ did "
  103. "not result in creation of either a .pyc or .pyo file")
  104. s = os.stat(fn)
  105. self.assertEquals(stat.S_IMODE(s.st_mode),
  106. stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
  107. finally:
  108. os.umask(oldmask)
  109. remove_files(TESTFN)
  110. if TESTFN in sys.modules: del sys.modules[TESTFN]
  111. del sys.path[0]
  112. def test_imp_module(self):
  113. # Verify that the imp module can correctly load and find .py files
  114. import imp
  115. x = imp.find_module("os")
  116. os = imp.load_module("os", *x)
  117. def test_module_with_large_stack(self, module='longlist'):
  118. # Regression test for http://bugs.python.org/issue561858.
  119. filename = module + os.extsep + 'py'
  120. # Create a file with a list of 65000 elements.
  121. f = open(filename, 'w+')
  122. try:
  123. f.write('d = [\n')
  124. for i in range(65000):
  125. f.write('"",\n')
  126. f.write(']')
  127. finally:
  128. f.close()
  129. # Compile & remove .py file, we only need .pyc (or .pyo).
  130. f = open(filename, 'r')
  131. try:
  132. py_compile.compile(filename)
  133. finally:
  134. f.close()
  135. os.unlink(filename)
  136. # Need to be able to load from current dir.
  137. sys.path.append('')
  138. # This used to crash.
  139. exec 'import ' + module
  140. # Cleanup.
  141. del sys.path[-1]
  142. for ext in 'pyc', 'pyo':
  143. fname = module + os.extsep + ext
  144. if os.path.exists(fname):
  145. os.unlink(fname)
  146. def test_failing_import_sticks(self):
  147. source = test_support.TESTFN + os.extsep + "py"
  148. f = open(source, "w")
  149. try:
  150. print >> f, "a = 1/0"
  151. finally:
  152. f.close()
  153. # New in 2.4, we shouldn't be able to import that no matter how often
  154. # we try.
  155. sys.path.insert(0, os.curdir)
  156. try:
  157. for _ in range(3):
  158. try:
  159. mod = __import__(test_support.TESTFN)
  160. except ZeroDivisionError:
  161. if test_support.TESTFN in sys.modules:
  162. self.fail("damaged module in sys.modules")
  163. else:
  164. self.fail("was able to import a damaged module")
  165. finally:
  166. sys.path.pop(0)
  167. remove_files(test_support.TESTFN)
  168. def test_failing_reload(self):
  169. # A failing reload should leave the module object in sys.modules.
  170. source = test_support.TESTFN + os.extsep + "py"
  171. f = open(source, "w")
  172. try:
  173. print >> f, "a = 1"
  174. print >> f, "b = 2"
  175. finally:
  176. f.close()
  177. sys.path.insert(0, os.curdir)
  178. try:
  179. mod = __import__(test_support.TESTFN)
  180. self.assert_(test_support.TESTFN in sys.modules)
  181. self.assertEquals(mod.a, 1, "module has wrong attribute values")
  182. self.assertEquals(mod.b, 2, "module has wrong attribute values")
  183. # On WinXP, just replacing the .py file wasn't enough to
  184. # convince reload() to reparse it. Maybe the timestamp didn't
  185. # move enough. We force it to get reparsed by removing the
  186. # compiled file too.
  187. remove_files(test_support.TESTFN)
  188. # Now damage the module.
  189. f = open(source, "w")
  190. try:
  191. print >> f, "a = 10"
  192. print >> f, "b = 20//0"
  193. finally:
  194. f.close()
  195. self.assertRaises(ZeroDivisionError, reload, mod)
  196. # But we still expect the module to be in sys.modules.
  197. mod = sys.modules.get(test_support.TESTFN)
  198. self.failIf(mod is None, "expected module to be in sys.modules")
  199. # We should have replaced a w/ 10, but the old b value should
  200. # stick.
  201. self.assertEquals(mod.a, 10, "module has wrong attribute values")
  202. self.assertEquals(mod.b, 2, "module has wrong attribute values")
  203. finally:
  204. sys.path.pop(0)
  205. remove_files(test_support.TESTFN)
  206. if test_support.TESTFN in sys.modules:
  207. del sys.modules[test_support.TESTFN]
  208. def test_infinite_reload(self):
  209. # http://bugs.python.org/issue742342 reports that Python segfaults
  210. # (infinite recursion in C) when faced with self-recursive reload()ing.
  211. sys.path.insert(0, os.path.dirname(__file__))
  212. try:
  213. import infinite_reload
  214. finally:
  215. sys.path.pop(0)
  216. def test_import_name_binding(self):
  217. # import x.y.z binds x in the current namespace.
  218. import test as x
  219. import test.test_support
  220. self.assert_(x is test, x.__name__)
  221. self.assert_(hasattr(test.test_support, "__file__"))
  222. # import x.y.z as w binds z as w.
  223. import test.test_support as y
  224. self.assert_(y is test.test_support, y.__name__)
  225. def test_import_initless_directory_warning(self):
  226. with warnings.catch_warnings():
  227. # Just a random non-package directory we always expect to be
  228. # somewhere in sys.path...
  229. warnings.simplefilter('error', ImportWarning)
  230. self.assertRaises(ImportWarning, __import__, "site-packages")
  231. def test_import_by_filename(self):
  232. path = os.path.abspath(test_support.TESTFN)
  233. try:
  234. __import__(path)
  235. except ImportError, err:
  236. self.assertEqual("Import by filename is not supported.",
  237. err.args[0])
  238. else:
  239. self.fail("import by path didn't raise an exception")
  240. class TestPycRewriting(unittest.TestCase):
  241. # Test that the `co_filename` attribute on code objects always points
  242. # to the right file, even when various things happen (e.g. both the .py
  243. # and the .pyc file are renamed).
  244. module_name = "unlikely_module_name"
  245. module_source = """
  246. import sys
  247. code_filename = sys._getframe().f_code.co_filename
  248. module_filename = __file__
  249. constant = 1
  250. def func():
  251. pass
  252. func_filename = func.func_code.co_filename
  253. """
  254. dir_name = os.path.abspath(TESTFN)
  255. file_name = os.path.join(dir_name, module_name) + os.extsep + "py"
  256. compiled_name = file_name + ("c" if __debug__ else "o")
  257. def setUp(self):
  258. self.sys_path = sys.path[:]
  259. self.orig_module = sys.modules.pop(self.module_name, None)
  260. os.mkdir(self.dir_name)
  261. with open(self.file_name, "w") as f:
  262. f.write(self.module_source)
  263. sys.path.insert(0, self.dir_name)
  264. def tearDown(self):
  265. sys.path[:] = self.sys_path
  266. if self.orig_module is not None:
  267. sys.modules[self.module_name] = self.orig_module
  268. else:
  269. del sys.modules[self.module_name]
  270. for file_name in self.file_name, self.compiled_name:
  271. if os.path.exists(file_name):
  272. os.remove(file_name)
  273. if os.path.exists(self.dir_name):
  274. shutil.rmtree(self.dir_name)
  275. def import_module(self):
  276. ns = globals()
  277. __import__(self.module_name, ns, ns)
  278. return sys.modules[self.module_name]
  279. def test_basics(self):
  280. mod = self.import_module()
  281. self.assertEqual(mod.module_filename, self.file_name)
  282. self.assertEqual(mod.code_filename, self.file_name)
  283. self.assertEqual(mod.func_filename, self.file_name)
  284. del sys.modules[self.module_name]
  285. mod = self.import_module()
  286. self.assertEqual(mod.module_filename, self.compiled_name)
  287. self.assertEqual(mod.code_filename, self.file_name)
  288. self.assertEqual(mod.func_filename, self.file_name)
  289. def test_incorrect_code_name(self):
  290. py_compile.compile(self.file_name, dfile="another_module.py")
  291. mod = self.import_module()
  292. self.assertEqual(mod.module_filename, self.compiled_name)
  293. self.assertEqual(mod.code_filename, self.file_name)
  294. self.assertEqual(mod.func_filename, self.file_name)
  295. def test_module_without_source(self):
  296. target = "another_module.py"
  297. py_compile.compile(self.file_name, dfile=target)
  298. os.remove(self.file_name)
  299. mod = self.import_module()
  300. self.assertEqual(mod.module_filename, self.compiled_name)
  301. self.assertEqual(mod.code_filename, target)
  302. self.assertEqual(mod.func_filename, target)
  303. def test_foreign_code(self):
  304. py_compile.compile(self.file_name)
  305. with open(self.compiled_name, "rb") as f:
  306. header = f.read(8)
  307. code = marshal.load(f)
  308. constants = list(code.co_consts)
  309. foreign_code = test_main.func_code
  310. pos = constants.index(1)
  311. constants[pos] = foreign_code
  312. code = type(code)(code.co_argcount, code.co_nlocals, code.co_stacksize,
  313. code.co_flags, code.co_code, tuple(constants),
  314. code.co_names, code.co_varnames, code.co_filename,
  315. code.co_name, code.co_firstlineno, code.co_lnotab,
  316. code.co_freevars, code.co_cellvars)
  317. with open(self.compiled_name, "wb") as f:
  318. f.write(header)
  319. marshal.dump(code, f)
  320. mod = self.import_module()
  321. self.assertEqual(mod.constant.co_filename, foreign_code.co_filename)
  322. class PathsTests(unittest.TestCase):
  323. path = test_support.TESTFN
  324. def setUp(self):
  325. os.mkdir(self.path)
  326. self.syspath = sys.path[:]
  327. def tearDown(self):
  328. shutil.rmtree(self.path)
  329. sys.path = self.syspath
  330. def test_trailing_slash(self):
  331. # Regression test for http://bugs.python.org/issue1293.
  332. f = open(os.path.join(self.path, 'test_trailing_slash.py'), 'w')
  333. try:
  334. f.write("testdata = 'test_trailing_slash'")
  335. finally:
  336. f.close()
  337. sys.path.append(self.path+'/')
  338. mod = __import__("test_trailing_slash")
  339. self.assertEqual(mod.testdata, 'test_trailing_slash')
  340. test_support.unload("test_trailing_slash")
  341. class RelativeImportTests(unittest.TestCase):
  342. def tearDown(self):
  343. try:
  344. del sys.modules["test.relimport"]
  345. except:
  346. pass
  347. def test_relimport_star(self):
  348. # This will import * from .test_import.
  349. from . import relimport
  350. self.assertTrue(hasattr(relimport, "RelativeImportTests"))
  351. def test_issue3221(self):
  352. # Regression test for http://bugs.python.org/issue3221.
  353. def check_absolute():
  354. exec "from os import path" in ns
  355. def check_relative():
  356. exec "from . import relimport" in ns
  357. # Check both OK with __package__ and __name__ correct
  358. ns = dict(__package__='test', __name__='test.notarealmodule')
  359. check_absolute()
  360. check_relative()
  361. # Check both OK with only __name__ wrong
  362. ns = dict(__package__='test', __name__='notarealpkg.notarealmodule')
  363. check_absolute()
  364. check_relative()
  365. # Check relative fails with only __package__ wrong
  366. ns = dict(__package__='foo', __name__='test.notarealmodule')
  367. with test_support.check_warnings() as w:
  368. check_absolute()
  369. self.assert_('foo' in str(w.message))
  370. self.assertEqual(w.category, RuntimeWarning)
  371. self.assertRaises(SystemError, check_relative)
  372. # Check relative fails with __package__ and __name__ wrong
  373. ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule')
  374. with test_support.check_warnings() as w:
  375. check_absolute()
  376. self.assert_('foo' in str(w.message))
  377. self.assertEqual(w.category, RuntimeWarning)
  378. self.assertRaises(SystemError, check_relative)
  379. # Check both fail with package set to a non-string
  380. ns = dict(__package__=object())
  381. self.assertRaises(ValueError, check_absolute)
  382. self.assertRaises(ValueError, check_relative)
  383. class OverridingImportBuiltinTests(unittest.TestCase):
  384. def test_override_builtin(self):
  385. # Test that overriding __builtin__.__import__ can bypass sys.modules.
  386. import os
  387. def foo():
  388. import os
  389. return os
  390. self.assertEqual(foo(), os) # Quick sanity check.
  391. with test_support.swap_attr(__builtin__, "__import__", lambda *x: 5):
  392. self.assertEqual(foo(), 5)
  393. # Test what happens when we shadow __import__ in globals(); this
  394. # currently does not impact the import process, but if this changes,
  395. # other code will need to change, so keep this test as a tripwire.
  396. with test_support.swap_item(globals(), "__import__", lambda *x: 5):
  397. self.assertEqual(foo(), os)
  398. def test_main(verbose=None):
  399. test_support.run_unittest(ImportTests, PathsTests, RelativeImportTests,
  400. TestPycRewriting, OverridingImportBuiltinTests)
  401. if __name__ == '__main__':
  402. # Test needs to be a package, so we can do relative import.
  403. from test.test_import import test_main
  404. test_main()