PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/lib-python/2.7/test/test_zipimport.py

https://bitbucket.org/yrttyr/pypy
Python | 472 lines | 423 code | 27 blank | 22 comment | 20 complexity | 77d9f3e294b677be05a7a7b6a584bb06 MD5 | raw file
  1. import sys
  2. import os
  3. import marshal
  4. import imp
  5. import struct
  6. import time
  7. import unittest
  8. from test import test_support
  9. from test.test_importhooks import ImportHooksBaseTestCase, test_src, test_co
  10. # some tests can be ran even without zlib
  11. try:
  12. import zlib
  13. except ImportError:
  14. zlib = None
  15. from zipfile import ZipFile, ZipInfo, ZIP_STORED, ZIP_DEFLATED
  16. import zipimport
  17. import linecache
  18. import doctest
  19. import inspect
  20. import StringIO
  21. from traceback import extract_tb, extract_stack, print_tb
  22. raise_src = 'def do_raise(): raise TypeError\n'
  23. def make_pyc(co, mtime):
  24. data = marshal.dumps(co)
  25. if type(mtime) is type(0.0):
  26. # Mac mtimes need a bit of special casing
  27. if mtime < 0x7fffffff:
  28. mtime = int(mtime)
  29. else:
  30. mtime = int(-0x100000000L + long(mtime))
  31. pyc = imp.get_magic() + struct.pack("<i", int(mtime)) + data
  32. return pyc
  33. def module_path_to_dotted_name(path):
  34. return path.replace(os.sep, '.')
  35. NOW = time.time()
  36. test_pyc = make_pyc(test_co, NOW)
  37. if __debug__:
  38. pyc_ext = ".pyc"
  39. else:
  40. pyc_ext = ".pyo"
  41. TESTMOD = "ziptestmodule"
  42. TESTPACK = "ziptestpackage"
  43. TESTPACK2 = "ziptestpackage2"
  44. TEMP_ZIP = os.path.abspath("junk95142" + os.extsep + "zip")
  45. class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
  46. compression = ZIP_STORED
  47. def setUp(self):
  48. # We're reusing the zip archive path, so we must clear the
  49. # cached directory info and linecache
  50. linecache.clearcache()
  51. zipimport._zip_directory_cache.clear()
  52. ImportHooksBaseTestCase.setUp(self)
  53. def doTest(self, expected_ext, files, *modules, **kw):
  54. z = ZipFile(TEMP_ZIP, "w")
  55. try:
  56. for name, (mtime, data) in files.items():
  57. zinfo = ZipInfo(name, time.localtime(mtime))
  58. zinfo.compress_type = self.compression
  59. z.writestr(zinfo, data)
  60. z.close()
  61. stuff = kw.get("stuff", None)
  62. if stuff is not None:
  63. # Prepend 'stuff' to the start of the zipfile
  64. f = open(TEMP_ZIP, "rb")
  65. data = f.read()
  66. f.close()
  67. f = open(TEMP_ZIP, "wb")
  68. f.write(stuff)
  69. f.write(data)
  70. f.close()
  71. sys.path.insert(0, TEMP_ZIP)
  72. mod = __import__(".".join(modules), globals(), locals(),
  73. ["__dummy__"])
  74. call = kw.get('call')
  75. if call is not None:
  76. call(mod)
  77. if expected_ext:
  78. file = mod.get_file()
  79. self.assertEqual(file, os.path.join(TEMP_ZIP,
  80. *modules) + expected_ext)
  81. finally:
  82. z.close()
  83. os.remove(TEMP_ZIP)
  84. def testAFakeZlib(self):
  85. #
  86. # This could cause a stack overflow before: importing zlib.py
  87. # from a compressed archive would cause zlib to be imported
  88. # which would find zlib.py in the archive, which would... etc.
  89. #
  90. # This test *must* be executed first: it must be the first one
  91. # to trigger zipimport to import zlib (zipimport caches the
  92. # zlib.decompress function object, after which the problem being
  93. # tested here wouldn't be a problem anymore...
  94. # (Hence the 'A' in the test method name: to make it the first
  95. # item in a list sorted by name, like unittest.makeSuite() does.)
  96. #
  97. # This test fails on platforms on which the zlib module is
  98. # statically linked, but the problem it tests for can't
  99. # occur in that case (builtin modules are always found first),
  100. # so we'll simply skip it then. Bug #765456.
  101. #
  102. if "zlib" in sys.builtin_module_names:
  103. return
  104. if "zlib" in sys.modules:
  105. del sys.modules["zlib"]
  106. files = {"zlib.py": (NOW, test_src)}
  107. try:
  108. self.doTest(".py", files, "zlib")
  109. except ImportError:
  110. if self.compression != ZIP_DEFLATED:
  111. self.fail("expected test to not raise ImportError")
  112. else:
  113. if self.compression != ZIP_STORED:
  114. self.fail("expected test to raise ImportError")
  115. def testPy(self):
  116. files = {TESTMOD + ".py": (NOW, test_src)}
  117. self.doTest(".py", files, TESTMOD)
  118. def testPyc(self):
  119. files = {TESTMOD + pyc_ext: (NOW, test_pyc)}
  120. self.doTest(pyc_ext, files, TESTMOD)
  121. def testBoth(self):
  122. files = {TESTMOD + ".py": (NOW, test_src),
  123. TESTMOD + pyc_ext: (NOW, test_pyc)}
  124. self.doTest(pyc_ext, files, TESTMOD)
  125. def testEmptyPy(self):
  126. files = {TESTMOD + ".py": (NOW, "")}
  127. self.doTest(None, files, TESTMOD)
  128. def testBadMagic(self):
  129. # make pyc magic word invalid, forcing loading from .py
  130. m0 = ord(test_pyc[0])
  131. m0 ^= 0x04 # flip an arbitrary bit
  132. badmagic_pyc = chr(m0) + test_pyc[1:]
  133. files = {TESTMOD + ".py": (NOW, test_src),
  134. TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
  135. self.doTest(".py", files, TESTMOD)
  136. def testBadMagic2(self):
  137. # make pyc magic word invalid, causing an ImportError
  138. m0 = ord(test_pyc[0])
  139. m0 ^= 0x04 # flip an arbitrary bit
  140. badmagic_pyc = chr(m0) + test_pyc[1:]
  141. files = {TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
  142. try:
  143. self.doTest(".py", files, TESTMOD)
  144. except ImportError:
  145. pass
  146. else:
  147. self.fail("expected ImportError; import from bad pyc")
  148. def testBadMTime(self):
  149. t3 = ord(test_pyc[7])
  150. t3 ^= 0x02 # flip the second bit -- not the first as that one
  151. # isn't stored in the .py's mtime in the zip archive.
  152. badtime_pyc = test_pyc[:7] + chr(t3) + test_pyc[8:]
  153. files = {TESTMOD + ".py": (NOW, test_src),
  154. TESTMOD + pyc_ext: (NOW, badtime_pyc)}
  155. self.doTest(".py", files, TESTMOD)
  156. def testPackage(self):
  157. packdir = TESTPACK + os.sep
  158. files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
  159. packdir + TESTMOD + pyc_ext: (NOW, test_pyc)}
  160. self.doTest(pyc_ext, files, TESTPACK, TESTMOD)
  161. def testDeepPackage(self):
  162. packdir = TESTPACK + os.sep
  163. packdir2 = packdir + TESTPACK2 + os.sep
  164. files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
  165. packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
  166. packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
  167. self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
  168. def testZipImporterMethods(self):
  169. packdir = TESTPACK + os.sep
  170. packdir2 = packdir + TESTPACK2 + os.sep
  171. files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
  172. packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
  173. packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
  174. z = ZipFile(TEMP_ZIP, "w")
  175. try:
  176. for name, (mtime, data) in files.items():
  177. zinfo = ZipInfo(name, time.localtime(mtime))
  178. zinfo.compress_type = self.compression
  179. z.writestr(zinfo, data)
  180. z.close()
  181. zi = zipimport.zipimporter(TEMP_ZIP)
  182. self.assertEqual(zi.archive, TEMP_ZIP)
  183. self.assertEqual(zi.is_package(TESTPACK), True)
  184. mod = zi.load_module(TESTPACK)
  185. self.assertEqual(zi.get_filename(TESTPACK), mod.__file__)
  186. self.assertEqual(zi.is_package(packdir + '__init__'), False)
  187. self.assertEqual(zi.is_package(packdir + TESTPACK2), True)
  188. self.assertEqual(zi.is_package(packdir2 + TESTMOD), False)
  189. mod_path = packdir2 + TESTMOD
  190. mod_name = module_path_to_dotted_name(mod_path)
  191. __import__(mod_name)
  192. mod = sys.modules[mod_name]
  193. self.assertEqual(zi.get_source(TESTPACK), None)
  194. self.assertEqual(zi.get_source(mod_path), None)
  195. self.assertEqual(zi.get_filename(mod_path), mod.__file__)
  196. # To pass in the module name instead of the path, we must use the right importer
  197. loader = mod.__loader__
  198. self.assertEqual(loader.get_source(mod_name), None)
  199. self.assertEqual(loader.get_filename(mod_name), mod.__file__)
  200. # test prefix and archivepath members
  201. zi2 = zipimport.zipimporter(TEMP_ZIP + os.sep + TESTPACK)
  202. self.assertEqual(zi2.archive, TEMP_ZIP)
  203. self.assertEqual(zi2.prefix, TESTPACK + os.sep)
  204. finally:
  205. z.close()
  206. os.remove(TEMP_ZIP)
  207. def testZipImporterMethodsInSubDirectory(self):
  208. packdir = TESTPACK + os.sep
  209. packdir2 = packdir + TESTPACK2 + os.sep
  210. files = {packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
  211. packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
  212. z = ZipFile(TEMP_ZIP, "w")
  213. try:
  214. for name, (mtime, data) in files.items():
  215. zinfo = ZipInfo(name, time.localtime(mtime))
  216. zinfo.compress_type = self.compression
  217. z.writestr(zinfo, data)
  218. z.close()
  219. zi = zipimport.zipimporter(TEMP_ZIP + os.sep + packdir)
  220. self.assertEqual(zi.archive, TEMP_ZIP)
  221. self.assertEqual(zi.prefix, packdir)
  222. self.assertEqual(zi.is_package(TESTPACK2), True)
  223. mod = zi.load_module(TESTPACK2)
  224. self.assertEqual(zi.get_filename(TESTPACK2), mod.__file__)
  225. self.assertEqual(zi.is_package(TESTPACK2 + os.sep + '__init__'), False)
  226. self.assertEqual(zi.is_package(TESTPACK2 + os.sep + TESTMOD), False)
  227. mod_path = TESTPACK2 + os.sep + TESTMOD
  228. mod_name = module_path_to_dotted_name(mod_path)
  229. __import__(mod_name)
  230. mod = sys.modules[mod_name]
  231. self.assertEqual(zi.get_source(TESTPACK2), None)
  232. self.assertEqual(zi.get_source(mod_path), None)
  233. self.assertEqual(zi.get_filename(mod_path), mod.__file__)
  234. # To pass in the module name instead of the path, we must use the right importer
  235. loader = mod.__loader__
  236. self.assertEqual(loader.get_source(mod_name), None)
  237. self.assertEqual(loader.get_filename(mod_name), mod.__file__)
  238. finally:
  239. z.close()
  240. os.remove(TEMP_ZIP)
  241. def testGetData(self):
  242. z = ZipFile(TEMP_ZIP, "w")
  243. z.compression = self.compression
  244. try:
  245. name = "testdata.dat"
  246. data = "".join([chr(x) for x in range(256)]) * 500
  247. z.writestr(name, data)
  248. z.close()
  249. zi = zipimport.zipimporter(TEMP_ZIP)
  250. self.assertEqual(data, zi.get_data(name))
  251. self.assertIn('zipimporter object', repr(zi))
  252. finally:
  253. z.close()
  254. os.remove(TEMP_ZIP)
  255. def testImporterAttr(self):
  256. src = """if 1: # indent hack
  257. def get_file():
  258. return __file__
  259. if __loader__.get_data("some.data") != "some data":
  260. raise AssertionError, "bad data"\n"""
  261. pyc = make_pyc(compile(src, "<???>", "exec"), NOW)
  262. files = {TESTMOD + pyc_ext: (NOW, pyc),
  263. "some.data": (NOW, "some data")}
  264. self.doTest(pyc_ext, files, TESTMOD)
  265. def testImport_WithStuff(self):
  266. # try importing from a zipfile which contains additional
  267. # stuff at the beginning of the file
  268. files = {TESTMOD + ".py": (NOW, test_src)}
  269. self.doTest(".py", files, TESTMOD,
  270. stuff="Some Stuff"*31)
  271. def assertModuleSource(self, module):
  272. self.assertEqual(inspect.getsource(module), test_src)
  273. def testGetSource(self):
  274. files = {TESTMOD + ".py": (NOW, test_src)}
  275. self.doTest(".py", files, TESTMOD, call=self.assertModuleSource)
  276. def testGetCompiledSource(self):
  277. pyc = make_pyc(compile(test_src, "<???>", "exec"), NOW)
  278. files = {TESTMOD + ".py": (NOW, test_src),
  279. TESTMOD + pyc_ext: (NOW, pyc)}
  280. self.doTest(pyc_ext, files, TESTMOD, call=self.assertModuleSource)
  281. def runDoctest(self, callback):
  282. files = {TESTMOD + ".py": (NOW, test_src),
  283. "xyz.txt": (NOW, ">>> log.append(True)\n")}
  284. self.doTest(".py", files, TESTMOD, call=callback)
  285. def doDoctestFile(self, module):
  286. log = []
  287. old_master, doctest.master = doctest.master, None
  288. try:
  289. doctest.testfile(
  290. 'xyz.txt', package=module, module_relative=True,
  291. globs=locals()
  292. )
  293. finally:
  294. doctest.master = old_master
  295. self.assertEqual(log,[True])
  296. def testDoctestFile(self):
  297. self.runDoctest(self.doDoctestFile)
  298. def doDoctestSuite(self, module):
  299. log = []
  300. doctest.DocFileTest(
  301. 'xyz.txt', package=module, module_relative=True,
  302. globs=locals()
  303. ).run()
  304. self.assertEqual(log,[True])
  305. def testDoctestSuite(self):
  306. self.runDoctest(self.doDoctestSuite)
  307. def doTraceback(self, module):
  308. try:
  309. module.do_raise()
  310. except:
  311. tb = sys.exc_info()[2].tb_next
  312. f,lno,n,line = extract_tb(tb, 1)[0]
  313. self.assertEqual(line, raise_src.strip())
  314. f,lno,n,line = extract_stack(tb.tb_frame, 1)[0]
  315. self.assertEqual(line, raise_src.strip())
  316. s = StringIO.StringIO()
  317. print_tb(tb, 1, s)
  318. self.assertTrue(s.getvalue().endswith(raise_src))
  319. else:
  320. raise AssertionError("This ought to be impossible")
  321. def testTraceback(self):
  322. files = {TESTMOD + ".py": (NOW, raise_src)}
  323. self.doTest(None, files, TESTMOD, call=self.doTraceback)
  324. @unittest.skipUnless(zlib, "requires zlib")
  325. class CompressedZipImportTestCase(UncompressedZipImportTestCase):
  326. compression = ZIP_DEFLATED
  327. class BadFileZipImportTestCase(unittest.TestCase):
  328. def assertZipFailure(self, filename):
  329. self.assertRaises(zipimport.ZipImportError,
  330. zipimport.zipimporter, filename)
  331. def testNoFile(self):
  332. self.assertZipFailure('AdfjdkFJKDFJjdklfjs')
  333. def testEmptyFilename(self):
  334. self.assertZipFailure('')
  335. def testBadArgs(self):
  336. self.assertRaises(TypeError, zipimport.zipimporter, None)
  337. self.assertRaises(TypeError, zipimport.zipimporter, TESTMOD, kwd=None)
  338. def testFilenameTooLong(self):
  339. self.assertZipFailure('A' * 33000)
  340. def testEmptyFile(self):
  341. test_support.unlink(TESTMOD)
  342. open(TESTMOD, 'w+').close()
  343. self.assertZipFailure(TESTMOD)
  344. def testFileUnreadable(self):
  345. test_support.unlink(TESTMOD)
  346. fd = os.open(TESTMOD, os.O_CREAT, 000)
  347. try:
  348. os.close(fd)
  349. self.assertZipFailure(TESTMOD)
  350. finally:
  351. # If we leave "the read-only bit" set on Windows, nothing can
  352. # delete TESTMOD, and later tests suffer bogus failures.
  353. os.chmod(TESTMOD, 0666)
  354. test_support.unlink(TESTMOD)
  355. def testNotZipFile(self):
  356. test_support.unlink(TESTMOD)
  357. fp = open(TESTMOD, 'w+')
  358. fp.write('a' * 22)
  359. fp.close()
  360. self.assertZipFailure(TESTMOD)
  361. # XXX: disabled until this works on Big-endian machines
  362. def _testBogusZipFile(self):
  363. test_support.unlink(TESTMOD)
  364. fp = open(TESTMOD, 'w+')
  365. fp.write(struct.pack('=I', 0x06054B50))
  366. fp.write('a' * 18)
  367. fp.close()
  368. z = zipimport.zipimporter(TESTMOD)
  369. try:
  370. self.assertRaises(TypeError, z.find_module, None)
  371. self.assertRaises(TypeError, z.load_module, None)
  372. self.assertRaises(TypeError, z.is_package, None)
  373. self.assertRaises(TypeError, z.get_code, None)
  374. self.assertRaises(TypeError, z.get_data, None)
  375. self.assertRaises(TypeError, z.get_source, None)
  376. error = zipimport.ZipImportError
  377. self.assertEqual(z.find_module('abc'), None)
  378. self.assertRaises(error, z.load_module, 'abc')
  379. self.assertRaises(error, z.get_code, 'abc')
  380. self.assertRaises(IOError, z.get_data, 'abc')
  381. self.assertRaises(error, z.get_source, 'abc')
  382. self.assertRaises(error, z.is_package, 'abc')
  383. finally:
  384. zipimport._zip_directory_cache.clear()
  385. def test_main():
  386. try:
  387. test_support.run_unittest(
  388. UncompressedZipImportTestCase,
  389. CompressedZipImportTestCase,
  390. BadFileZipImportTestCase,
  391. )
  392. finally:
  393. test_support.unlink(TESTMOD)
  394. if __name__ == "__main__":
  395. test_main()