blob: 0da5906f2833519615c53d5c097d2af3398cd908 [file] [log] [blame]
Just van Rossum52e14d62002-12-30 22:08:05 +00001import sys
2import os
3import marshal
Brett Cannon56aae8f2016-01-15 11:22:19 -08004import importlib
Brett Cannon9529fbf2013-06-15 17:11:25 -04005import importlib.util
Just van Rossum52e14d62002-12-30 22:08:05 +00006import struct
7import time
Neal Norwitzb155b622006-01-23 07:52:13 +00008import unittest
Just van Rossum52e14d62002-12-30 22:08:05 +00009
Benjamin Petersonee8712c2008-05-20 21:35:26 +000010from test import support
Just van Rossum52e14d62002-12-30 22:08:05 +000011
Ezio Melotti78ea2022009-09-12 18:41:20 +000012from zipfile import ZipFile, ZipInfo, ZIP_STORED, ZIP_DEFLATED
13
Just van Rossum52e14d62002-12-30 22:08:05 +000014import zipimport
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000015import linecache
16import doctest
17import inspect
Guido van Rossum34d19282007-08-09 01:03:29 +000018import io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000019from traceback import extract_tb, extract_stack, print_tb
Brett Cannon638ce072013-06-12 15:57:01 -040020
21test_src = """\
22def get_name():
23 return __name__
24def get_file():
25 return __file__
26"""
27test_co = compile(test_src, "<???>", "exec")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000028raise_src = 'def do_raise(): raise TypeError\n'
Just van Rossum52e14d62002-12-30 22:08:05 +000029
Antoine Pitrou5136ac02012-01-13 18:52:16 +010030def make_pyc(co, mtime, size):
Just van Rossum52e14d62002-12-30 22:08:05 +000031 data = marshal.dumps(co)
Jack Jansen472e7db2003-01-08 16:37:03 +000032 if type(mtime) is type(0.0):
Tim Petersf2715e02003-02-19 02:35:07 +000033 # Mac mtimes need a bit of special casing
34 if mtime < 0x7fffffff:
35 mtime = int(mtime)
36 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +000037 mtime = int(-0x100000000 + int(mtime))
Brett Cannon9529fbf2013-06-15 17:11:25 -040038 pyc = (importlib.util.MAGIC_NUMBER +
39 struct.pack("<ii", int(mtime), size & 0xFFFFFFFF) + data)
Just van Rossum52e14d62002-12-30 22:08:05 +000040 return pyc
41
Tim Peters68f2d002006-01-23 22:19:24 +000042def module_path_to_dotted_name(path):
43 return path.replace(os.sep, '.')
44
Just van Rossum52e14d62002-12-30 22:08:05 +000045NOW = time.time()
Antoine Pitrou5136ac02012-01-13 18:52:16 +010046test_pyc = make_pyc(test_co, NOW, len(test_src))
Just van Rossum52e14d62002-12-30 22:08:05 +000047
48
Just van Rossum52e14d62002-12-30 22:08:05 +000049TESTMOD = "ziptestmodule"
50TESTPACK = "ziptestpackage"
Just van Rossumd35c6db2003-01-02 12:55:48 +000051TESTPACK2 = "ziptestpackage2"
Brett Cannon56aae8f2016-01-15 11:22:19 -080052TEMP_DIR = os.path.abspath("junk95142")
Skip Montanaro7a98be22007-08-16 14:35:24 +000053TEMP_ZIP = os.path.abspath("junk95142.zip")
Just van Rossum52e14d62002-12-30 22:08:05 +000054
Brett Cannon9529fbf2013-06-15 17:11:25 -040055pyc_file = importlib.util.cache_from_source(TESTMOD + '.py')
Brett Cannonf299abd2015-04-13 14:21:02 -040056pyc_ext = '.pyc'
Barry Warsaw28a691b2010-04-17 00:19:56 +000057
Ezio Melotti78ea2022009-09-12 18:41:20 +000058
Brett Cannon638ce072013-06-12 15:57:01 -040059class ImportHooksBaseTestCase(unittest.TestCase):
60
61 def setUp(self):
62 self.path = sys.path[:]
63 self.meta_path = sys.meta_path[:]
64 self.path_hooks = sys.path_hooks[:]
65 sys.path_importer_cache.clear()
66 self.modules_before = support.modules_setup()
67
68 def tearDown(self):
69 sys.path[:] = self.path
70 sys.meta_path[:] = self.meta_path
71 sys.path_hooks[:] = self.path_hooks
72 sys.path_importer_cache.clear()
73 support.modules_cleanup(*self.modules_before)
74
75
Just van Rossum52e14d62002-12-30 22:08:05 +000076class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
77
78 compression = ZIP_STORED
79
80 def setUp(self):
81 # We're reusing the zip archive path, so we must clear the
Brett Cannon56aae8f2016-01-15 11:22:19 -080082 # cached directory info and linecache.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000083 linecache.clearcache()
Just van Rossum52e14d62002-12-30 22:08:05 +000084 zipimport._zip_directory_cache.clear()
85 ImportHooksBaseTestCase.setUp(self)
86
Brett Cannon56aae8f2016-01-15 11:22:19 -080087 def makeTree(self, files, dirName=TEMP_DIR):
88 # Create a filesystem based set of modules/packages
89 # defined by files under the directory dirName.
90 self.addCleanup(support.rmtree, dirName)
91
92 for name, (mtime, data) in files.items():
93 path = os.path.join(dirName, name)
94 if path[-1] == os.sep:
95 if not os.path.isdir(path):
96 os.makedirs(path)
97 else:
98 dname = os.path.dirname(path)
99 if not os.path.isdir(dname):
100 os.makedirs(dname)
101 with open(path, 'wb') as fp:
102 fp.write(data)
103
104 def makeZip(self, files, zipName=TEMP_ZIP, **kw):
105 # Create a zip archive based set of modules/packages
106 # defined by files in the zip file zipName. If the
107 # key 'stuff' exists in kw it is prepended to the archive.
108 self.addCleanup(support.unlink, zipName)
109
110 with ZipFile(zipName, "w") as z:
Benjamin Petersoneb437362014-02-16 14:12:57 -0500111 for name, (mtime, data) in files.items():
112 zinfo = ZipInfo(name, time.localtime(mtime))
113 zinfo.compress_type = self.compression
114 z.writestr(zinfo, data)
Benjamin Petersoneb437362014-02-16 14:12:57 -0500115
Brett Cannon56aae8f2016-01-15 11:22:19 -0800116 stuff = kw.get("stuff", None)
117 if stuff is not None:
118 # Prepend 'stuff' to the start of the zipfile
119 with open(zipName, "rb") as f:
120 data = f.read()
121 with open(zipName, "wb") as f:
122 f.write(stuff)
123 f.write(data)
Benjamin Petersoneb437362014-02-16 14:12:57 -0500124
Brett Cannon56aae8f2016-01-15 11:22:19 -0800125 def doTest(self, expected_ext, files, *modules, **kw):
126 self.makeZip(files, **kw)
Just van Rossum52e14d62002-12-30 22:08:05 +0000127
Brett Cannon56aae8f2016-01-15 11:22:19 -0800128 sys.path.insert(0, TEMP_ZIP)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000129
Brett Cannon56aae8f2016-01-15 11:22:19 -0800130 mod = importlib.import_module(".".join(modules))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000131
Brett Cannon56aae8f2016-01-15 11:22:19 -0800132 call = kw.get('call')
133 if call is not None:
134 call(mod)
135
136 if expected_ext:
137 file = mod.get_file()
138 self.assertEqual(file, os.path.join(TEMP_ZIP,
Ezio Melottib3aedd42010-11-20 19:04:17 +0000139 *modules) + expected_ext)
Just van Rossum52e14d62002-12-30 22:08:05 +0000140
141 def testAFakeZlib(self):
142 #
143 # This could cause a stack overflow before: importing zlib.py
144 # from a compressed archive would cause zlib to be imported
145 # which would find zlib.py in the archive, which would... etc.
146 #
147 # This test *must* be executed first: it must be the first one
148 # to trigger zipimport to import zlib (zipimport caches the
149 # zlib.decompress function object, after which the problem being
150 # tested here wouldn't be a problem anymore...
151 # (Hence the 'A' in the test method name: to make it the first
152 # item in a list sorted by name, like unittest.makeSuite() does.)
153 #
Just van Rossum59498542003-11-18 23:00:55 +0000154 # This test fails on platforms on which the zlib module is
155 # statically linked, but the problem it tests for can't
156 # occur in that case (builtin modules are always found first),
157 # so we'll simply skip it then. Bug #765456.
158 #
159 if "zlib" in sys.builtin_module_names:
Zachary Ware9fe6d862013-12-08 00:20:35 -0600160 self.skipTest('zlib is a builtin module')
Just van Rossum52e14d62002-12-30 22:08:05 +0000161 if "zlib" in sys.modules:
162 del sys.modules["zlib"]
163 files = {"zlib.py": (NOW, test_src)}
164 try:
165 self.doTest(".py", files, "zlib")
166 except ImportError:
167 if self.compression != ZIP_DEFLATED:
168 self.fail("expected test to not raise ImportError")
169 else:
170 if self.compression != ZIP_STORED:
171 self.fail("expected test to raise ImportError")
172
173 def testPy(self):
174 files = {TESTMOD + ".py": (NOW, test_src)}
175 self.doTest(".py", files, TESTMOD)
176
177 def testPyc(self):
178 files = {TESTMOD + pyc_ext: (NOW, test_pyc)}
179 self.doTest(pyc_ext, files, TESTMOD)
180
181 def testBoth(self):
182 files = {TESTMOD + ".py": (NOW, test_src),
183 TESTMOD + pyc_ext: (NOW, test_pyc)}
184 self.doTest(pyc_ext, files, TESTMOD)
185
Just van Rossum9a3129c2003-01-03 11:18:56 +0000186 def testEmptyPy(self):
187 files = {TESTMOD + ".py": (NOW, "")}
188 self.doTest(None, files, TESTMOD)
189
Just van Rossum52e14d62002-12-30 22:08:05 +0000190 def testBadMagic(self):
191 # make pyc magic word invalid, forcing loading from .py
Guido van Rossum254348e2007-11-21 19:29:53 +0000192 badmagic_pyc = bytearray(test_pyc)
Guido van Rossumad8d3002007-08-03 18:40:49 +0000193 badmagic_pyc[0] ^= 0x04 # flip an arbitrary bit
Just van Rossum52e14d62002-12-30 22:08:05 +0000194 files = {TESTMOD + ".py": (NOW, test_src),
195 TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
196 self.doTest(".py", files, TESTMOD)
197
198 def testBadMagic2(self):
199 # make pyc magic word invalid, causing an ImportError
Guido van Rossum254348e2007-11-21 19:29:53 +0000200 badmagic_pyc = bytearray(test_pyc)
Guido van Rossumad8d3002007-08-03 18:40:49 +0000201 badmagic_pyc[0] ^= 0x04 # flip an arbitrary bit
Just van Rossum52e14d62002-12-30 22:08:05 +0000202 files = {TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
203 try:
204 self.doTest(".py", files, TESTMOD)
205 except ImportError:
206 pass
207 else:
208 self.fail("expected ImportError; import from bad pyc")
209
210 def testBadMTime(self):
Guido van Rossum254348e2007-11-21 19:29:53 +0000211 badtime_pyc = bytearray(test_pyc)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000212 # flip the second bit -- not the first as that one isn't stored in the
213 # .py's mtime in the zip archive.
214 badtime_pyc[7] ^= 0x02
Just van Rossum52e14d62002-12-30 22:08:05 +0000215 files = {TESTMOD + ".py": (NOW, test_src),
216 TESTMOD + pyc_ext: (NOW, badtime_pyc)}
217 self.doTest(".py", files, TESTMOD)
218
219 def testPackage(self):
220 packdir = TESTPACK + os.sep
221 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
222 packdir + TESTMOD + pyc_ext: (NOW, test_pyc)}
223 self.doTest(pyc_ext, files, TESTPACK, TESTMOD)
224
Brett Cannon56aae8f2016-01-15 11:22:19 -0800225 def testSubPackage(self):
226 # Test that subpackages function when loaded from zip
227 # archives.
Just van Rossum52e14d62002-12-30 22:08:05 +0000228 packdir = TESTPACK + os.sep
Just van Rossumd35c6db2003-01-02 12:55:48 +0000229 packdir2 = packdir + TESTPACK2 + os.sep
Just van Rossum52e14d62002-12-30 22:08:05 +0000230 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
231 packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
232 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
Just van Rossumd35c6db2003-01-02 12:55:48 +0000233 self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
Just van Rossum52e14d62002-12-30 22:08:05 +0000234
Brett Cannon56aae8f2016-01-15 11:22:19 -0800235 def testSubNamespacePackage(self):
236 # Test that implicit namespace subpackages function
237 # when loaded from zip archives.
238 packdir = TESTPACK + os.sep
239 packdir2 = packdir + TESTPACK2 + os.sep
240 # The first two files are just directory entries (so have no data).
241 files = {packdir: (NOW, ""),
242 packdir2: (NOW, ""),
243 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
244 self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
245
246 def testMixedNamespacePackage(self):
247 # Test implicit namespace packages spread between a
248 # real filesystem and a zip archive.
249 packdir = TESTPACK + os.sep
250 packdir2 = packdir + TESTPACK2 + os.sep
251 packdir3 = packdir2 + TESTPACK + '3' + os.sep
252 files1 = {packdir: (NOW, ""),
253 packdir + TESTMOD + pyc_ext: (NOW, test_pyc),
254 packdir2: (NOW, ""),
255 packdir3: (NOW, ""),
256 packdir3 + TESTMOD + pyc_ext: (NOW, test_pyc),
257 packdir2 + TESTMOD + '3' + pyc_ext: (NOW, test_pyc),
258 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
259 files2 = {packdir: (NOW, ""),
260 packdir + TESTMOD + '2' + pyc_ext: (NOW, test_pyc),
261 packdir2: (NOW, ""),
262 packdir2 + TESTMOD + '2' + pyc_ext: (NOW, test_pyc),
263 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
264
265 zip1 = os.path.abspath("path1.zip")
266 self.makeZip(files1, zip1)
267
268 zip2 = TEMP_DIR
269 self.makeTree(files2, zip2)
270
271 # zip2 should override zip1.
272 sys.path.insert(0, zip1)
273 sys.path.insert(0, zip2)
274
275 mod = importlib.import_module(TESTPACK)
276
277 # if TESTPACK is functioning as a namespace pkg then
278 # there should be two entries in the __path__.
279 # First should be path2 and second path1.
280 self.assertEqual(2, len(mod.__path__))
281 p1, p2 = mod.__path__
282 self.assertEqual(os.path.basename(TEMP_DIR), p1.split(os.sep)[-2])
283 self.assertEqual("path1.zip", p2.split(os.sep)[-2])
284
285 # packdir3 should import as a namespace package.
286 # Its __path__ is an iterable of 1 element from zip1.
287 mod = importlib.import_module(packdir3.replace(os.sep, '.')[:-1])
288 self.assertEqual(1, len(mod.__path__))
289 mpath = list(mod.__path__)[0].split('path1.zip' + os.sep)[1]
290 self.assertEqual(packdir3[:-1], mpath)
291
292 # TESTPACK/TESTMOD only exists in path1.
293 mod = importlib.import_module('.'.join((TESTPACK, TESTMOD)))
294 self.assertEqual("path1.zip", mod.__file__.split(os.sep)[-3])
295
296 # And TESTPACK/(TESTMOD + '2') only exists in path2.
297 mod = importlib.import_module('.'.join((TESTPACK, TESTMOD + '2')))
298 self.assertEqual(os.path.basename(TEMP_DIR),
299 mod.__file__.split(os.sep)[-3])
300
301 # One level deeper...
302 subpkg = '.'.join((TESTPACK, TESTPACK2))
303 mod = importlib.import_module(subpkg)
304 self.assertEqual(2, len(mod.__path__))
305 p1, p2 = mod.__path__
306 self.assertEqual(os.path.basename(TEMP_DIR), p1.split(os.sep)[-3])
307 self.assertEqual("path1.zip", p2.split(os.sep)[-3])
308
309 # subpkg.TESTMOD exists in both zips should load from zip2.
310 mod = importlib.import_module('.'.join((subpkg, TESTMOD)))
311 self.assertEqual(os.path.basename(TEMP_DIR),
312 mod.__file__.split(os.sep)[-4])
313
314 # subpkg.TESTMOD + '2' only exists in zip2.
315 mod = importlib.import_module('.'.join((subpkg, TESTMOD + '2')))
316 self.assertEqual(os.path.basename(TEMP_DIR),
317 mod.__file__.split(os.sep)[-4])
318
319 # Finally subpkg.TESTMOD + '3' only exists in zip1.
320 mod = importlib.import_module('.'.join((subpkg, TESTMOD + '3')))
321 self.assertEqual('path1.zip', mod.__file__.split(os.sep)[-4])
322
323 def testNamespacePackage(self):
324 # Test implicit namespace packages spread between multiple zip
325 # archives.
326 packdir = TESTPACK + os.sep
327 packdir2 = packdir + TESTPACK2 + os.sep
328 packdir3 = packdir2 + TESTPACK + '3' + os.sep
329 files1 = {packdir: (NOW, ""),
330 packdir + TESTMOD + pyc_ext: (NOW, test_pyc),
331 packdir2: (NOW, ""),
332 packdir3: (NOW, ""),
333 packdir3 + TESTMOD + pyc_ext: (NOW, test_pyc),
334 packdir2 + TESTMOD + '3' + pyc_ext: (NOW, test_pyc),
335 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
336 zip1 = os.path.abspath("path1.zip")
337 self.makeZip(files1, zip1)
338
339 files2 = {packdir: (NOW, ""),
340 packdir + TESTMOD + '2' + pyc_ext: (NOW, test_pyc),
341 packdir2: (NOW, ""),
342 packdir2 + TESTMOD + '2' + pyc_ext: (NOW, test_pyc),
343 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
344 zip2 = os.path.abspath("path2.zip")
345 self.makeZip(files2, zip2)
346
347 # zip2 should override zip1.
348 sys.path.insert(0, zip1)
349 sys.path.insert(0, zip2)
350
351 mod = importlib.import_module(TESTPACK)
352
353 # if TESTPACK is functioning as a namespace pkg then
354 # there should be two entries in the __path__.
355 # First should be path2 and second path1.
356 self.assertEqual(2, len(mod.__path__))
357 p1, p2 = mod.__path__
358 self.assertEqual("path2.zip", p1.split(os.sep)[-2])
359 self.assertEqual("path1.zip", p2.split(os.sep)[-2])
360
361 # packdir3 should import as a namespace package.
362 # Tts __path__ is an iterable of 1 element from zip1.
363 mod = importlib.import_module(packdir3.replace(os.sep, '.')[:-1])
364 self.assertEqual(1, len(mod.__path__))
365 mpath = list(mod.__path__)[0].split('path1.zip' + os.sep)[1]
366 self.assertEqual(packdir3[:-1], mpath)
367
368 # TESTPACK/TESTMOD only exists in path1.
369 mod = importlib.import_module('.'.join((TESTPACK, TESTMOD)))
370 self.assertEqual("path1.zip", mod.__file__.split(os.sep)[-3])
371
372 # And TESTPACK/(TESTMOD + '2') only exists in path2.
373 mod = importlib.import_module('.'.join((TESTPACK, TESTMOD + '2')))
374 self.assertEqual("path2.zip", mod.__file__.split(os.sep)[-3])
375
376 # One level deeper...
377 subpkg = '.'.join((TESTPACK, TESTPACK2))
378 mod = importlib.import_module(subpkg)
379 self.assertEqual(2, len(mod.__path__))
380 p1, p2 = mod.__path__
381 self.assertEqual("path2.zip", p1.split(os.sep)[-3])
382 self.assertEqual("path1.zip", p2.split(os.sep)[-3])
383
384 # subpkg.TESTMOD exists in both zips should load from zip2.
385 mod = importlib.import_module('.'.join((subpkg, TESTMOD)))
386 self.assertEqual('path2.zip', mod.__file__.split(os.sep)[-4])
387
388 # subpkg.TESTMOD + '2' only exists in zip2.
389 mod = importlib.import_module('.'.join((subpkg, TESTMOD + '2')))
390 self.assertEqual('path2.zip', mod.__file__.split(os.sep)[-4])
391
392 # Finally subpkg.TESTMOD + '3' only exists in zip1.
393 mod = importlib.import_module('.'.join((subpkg, TESTMOD + '3')))
394 self.assertEqual('path1.zip', mod.__file__.split(os.sep)[-4])
395
Neal Norwitzb155b622006-01-23 07:52:13 +0000396 def testZipImporterMethods(self):
397 packdir = TESTPACK + os.sep
398 packdir2 = packdir + TESTPACK2 + os.sep
399 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
400 packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
401 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
402
403 z = ZipFile(TEMP_ZIP, "w")
404 try:
405 for name, (mtime, data) in files.items():
406 zinfo = ZipInfo(name, time.localtime(mtime))
407 zinfo.compress_type = self.compression
Serhiy Storchaka0e6b7b52013-02-16 17:43:45 +0200408 zinfo.comment = b"spam"
Neal Norwitzb155b622006-01-23 07:52:13 +0000409 z.writestr(zinfo, data)
410 z.close()
411
412 zi = zipimport.zipimporter(TEMP_ZIP)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000413 self.assertEqual(zi.archive, TEMP_ZIP)
414 self.assertEqual(zi.is_package(TESTPACK), True)
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000415 mod = zi.load_module(TESTPACK)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000416 self.assertEqual(zi.get_filename(TESTPACK), mod.__file__)
Tim Petersbc29c1a2006-01-23 21:28:42 +0000417
Brett Cannon56aae8f2016-01-15 11:22:19 -0800418 existing_pack_path = importlib.import_module(TESTPACK).__path__[0]
R David Murraya9719052012-03-12 21:16:33 -0400419 expected_path_path = os.path.join(TEMP_ZIP, TESTPACK)
420 self.assertEqual(existing_pack_path, expected_path_path)
421
Ezio Melottib3aedd42010-11-20 19:04:17 +0000422 self.assertEqual(zi.is_package(packdir + '__init__'), False)
423 self.assertEqual(zi.is_package(packdir + TESTPACK2), True)
424 self.assertEqual(zi.is_package(packdir2 + TESTMOD), False)
Neal Norwitzb155b622006-01-23 07:52:13 +0000425
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000426 mod_path = packdir2 + TESTMOD
427 mod_name = module_path_to_dotted_name(mod_path)
Brett Cannon56aae8f2016-01-15 11:22:19 -0800428 mod = importlib.import_module(mod_name)
429 self.assertTrue(mod_name in sys.modules)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000430 self.assertEqual(zi.get_source(TESTPACK), None)
431 self.assertEqual(zi.get_source(mod_path), None)
432 self.assertEqual(zi.get_filename(mod_path), mod.__file__)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000433 # To pass in the module name instead of the path, we must use the
434 # right importer
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000435 loader = mod.__loader__
Ezio Melottib3aedd42010-11-20 19:04:17 +0000436 self.assertEqual(loader.get_source(mod_name), None)
437 self.assertEqual(loader.get_filename(mod_name), mod.__file__)
Christian Heimes7f044312008-01-06 17:05:40 +0000438
439 # test prefix and archivepath members
440 zi2 = zipimport.zipimporter(TEMP_ZIP + os.sep + TESTPACK)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000441 self.assertEqual(zi2.archive, TEMP_ZIP)
442 self.assertEqual(zi2.prefix, TESTPACK + os.sep)
Neal Norwitzb155b622006-01-23 07:52:13 +0000443 finally:
444 z.close()
445 os.remove(TEMP_ZIP)
446
Alexandre Vassalotti8ae3e052008-05-16 00:41:41 +0000447 def testZipImporterMethodsInSubDirectory(self):
448 packdir = TESTPACK + os.sep
449 packdir2 = packdir + TESTPACK2 + os.sep
450 files = {packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
451 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
452
453 z = ZipFile(TEMP_ZIP, "w")
454 try:
455 for name, (mtime, data) in files.items():
456 zinfo = ZipInfo(name, time.localtime(mtime))
457 zinfo.compress_type = self.compression
Serhiy Storchaka0e6b7b52013-02-16 17:43:45 +0200458 zinfo.comment = b"eggs"
Alexandre Vassalotti8ae3e052008-05-16 00:41:41 +0000459 z.writestr(zinfo, data)
460 z.close()
461
462 zi = zipimport.zipimporter(TEMP_ZIP + os.sep + packdir)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000463 self.assertEqual(zi.archive, TEMP_ZIP)
464 self.assertEqual(zi.prefix, packdir)
465 self.assertEqual(zi.is_package(TESTPACK2), True)
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000466 mod = zi.load_module(TESTPACK2)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000467 self.assertEqual(zi.get_filename(TESTPACK2), mod.__file__)
Alexandre Vassalotti8ae3e052008-05-16 00:41:41 +0000468
Ezio Melottib3aedd42010-11-20 19:04:17 +0000469 self.assertEqual(
Barry Warsaw28a691b2010-04-17 00:19:56 +0000470 zi.is_package(TESTPACK2 + os.sep + '__init__'), False)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000471 self.assertEqual(
Barry Warsaw28a691b2010-04-17 00:19:56 +0000472 zi.is_package(TESTPACK2 + os.sep + TESTMOD), False)
Alexandre Vassalotti8ae3e052008-05-16 00:41:41 +0000473
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000474 mod_path = TESTPACK2 + os.sep + TESTMOD
475 mod_name = module_path_to_dotted_name(mod_path)
Brett Cannon56aae8f2016-01-15 11:22:19 -0800476 mod = importlib.import_module(mod_name)
477 self.assertTrue(mod_name in sys.modules)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000478 self.assertEqual(zi.get_source(TESTPACK2), None)
479 self.assertEqual(zi.get_source(mod_path), None)
480 self.assertEqual(zi.get_filename(mod_path), mod.__file__)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000481 # To pass in the module name instead of the path, we must use the
Brett Cannon56aae8f2016-01-15 11:22:19 -0800482 # right importer.
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000483 loader = mod.__loader__
Ezio Melottib3aedd42010-11-20 19:04:17 +0000484 self.assertEqual(loader.get_source(mod_name), None)
485 self.assertEqual(loader.get_filename(mod_name), mod.__file__)
Alexandre Vassalotti8ae3e052008-05-16 00:41:41 +0000486 finally:
487 z.close()
488 os.remove(TEMP_ZIP)
489
Just van Rossum52e14d62002-12-30 22:08:05 +0000490 def testGetData(self):
491 z = ZipFile(TEMP_ZIP, "w")
492 z.compression = self.compression
493 try:
494 name = "testdata.dat"
Guido van Rossumad8d3002007-08-03 18:40:49 +0000495 data = bytes(x for x in range(256))
Just van Rossum52e14d62002-12-30 22:08:05 +0000496 z.writestr(name, data)
497 z.close()
498 zi = zipimport.zipimporter(TEMP_ZIP)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000499 self.assertEqual(data, zi.get_data(name))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000500 self.assertIn('zipimporter object', repr(zi))
Just van Rossum52e14d62002-12-30 22:08:05 +0000501 finally:
502 z.close()
503 os.remove(TEMP_ZIP)
504
505 def testImporterAttr(self):
506 src = """if 1: # indent hack
507 def get_file():
508 return __file__
Guido van Rossumad8d3002007-08-03 18:40:49 +0000509 if __loader__.get_data("some.data") != b"some data":
Collin Winter828f04a2007-08-31 00:04:24 +0000510 raise AssertionError("bad data")\n"""
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100511 pyc = make_pyc(compile(src, "<???>", "exec"), NOW, len(src))
Just van Rossum52e14d62002-12-30 22:08:05 +0000512 files = {TESTMOD + pyc_ext: (NOW, pyc),
513 "some.data": (NOW, "some data")}
514 self.doTest(pyc_ext, files, TESTMOD)
515
Thomas Heller354e3d92003-07-22 18:10:15 +0000516 def testImport_WithStuff(self):
517 # try importing from a zipfile which contains additional
518 # stuff at the beginning of the file
519 files = {TESTMOD + ".py": (NOW, test_src)}
520 self.doTest(".py", files, TESTMOD,
Guido van Rossum85825dc2007-08-27 17:03:28 +0000521 stuff=b"Some Stuff"*31)
Just van Rossum52e14d62002-12-30 22:08:05 +0000522
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000523 def assertModuleSource(self, module):
524 self.assertEqual(inspect.getsource(module), test_src)
525
526 def testGetSource(self):
527 files = {TESTMOD + ".py": (NOW, test_src)}
528 self.doTest(".py", files, TESTMOD, call=self.assertModuleSource)
529
530 def testGetCompiledSource(self):
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100531 pyc = make_pyc(compile(test_src, "<???>", "exec"), NOW, len(test_src))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000532 files = {TESTMOD + ".py": (NOW, test_src),
533 TESTMOD + pyc_ext: (NOW, pyc)}
534 self.doTest(pyc_ext, files, TESTMOD, call=self.assertModuleSource)
535
536 def runDoctest(self, callback):
537 files = {TESTMOD + ".py": (NOW, test_src),
538 "xyz.txt": (NOW, ">>> log.append(True)\n")}
539 self.doTest(".py", files, TESTMOD, call=callback)
540
541 def doDoctestFile(self, module):
542 log = []
543 old_master, doctest.master = doctest.master, None
544 try:
545 doctest.testfile(
546 'xyz.txt', package=module, module_relative=True,
547 globs=locals()
548 )
549 finally:
550 doctest.master = old_master
551 self.assertEqual(log,[True])
552
553 def testDoctestFile(self):
554 self.runDoctest(self.doDoctestFile)
555
556 def doDoctestSuite(self, module):
557 log = []
558 doctest.DocFileTest(
559 'xyz.txt', package=module, module_relative=True,
560 globs=locals()
561 ).run()
562 self.assertEqual(log,[True])
563
564 def testDoctestSuite(self):
565 self.runDoctest(self.doDoctestSuite)
566
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000567 def doTraceback(self, module):
568 try:
569 module.do_raise()
570 except:
571 tb = sys.exc_info()[2].tb_next
572
573 f,lno,n,line = extract_tb(tb, 1)[0]
574 self.assertEqual(line, raise_src.strip())
575
576 f,lno,n,line = extract_stack(tb.tb_frame, 1)[0]
577 self.assertEqual(line, raise_src.strip())
578
Guido van Rossum34d19282007-08-09 01:03:29 +0000579 s = io.StringIO()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000580 print_tb(tb, 1, s)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000581 self.assertTrue(s.getvalue().endswith(raise_src))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000582 else:
583 raise AssertionError("This ought to be impossible")
584
585 def testTraceback(self):
586 files = {TESTMOD + ".py": (NOW, raise_src)}
587 self.doTest(None, files, TESTMOD, call=self.doTraceback)
588
Victor Stinner2460a432010-08-16 17:54:28 +0000589 @unittest.skipIf(support.TESTFN_UNENCODABLE is None,
590 "need an unencodable filename")
Victor Stinner36e79112010-08-17 00:44:11 +0000591 def testUnencodable(self):
Victor Stinner2460a432010-08-16 17:54:28 +0000592 filename = support.TESTFN_UNENCODABLE + ".zip"
593 z = ZipFile(filename, "w")
594 zinfo = ZipInfo(TESTMOD + ".py", time.localtime(NOW))
595 zinfo.compress_type = self.compression
596 z.writestr(zinfo, test_src)
597 z.close()
598 try:
599 zipimport.zipimporter(filename)
600 finally:
601 os.remove(filename)
602
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000603
Ezio Melotti975077a2011-05-19 22:03:22 +0300604@support.requires_zlib
Just van Rossum52e14d62002-12-30 22:08:05 +0000605class CompressedZipImportTestCase(UncompressedZipImportTestCase):
606 compression = ZIP_DEFLATED
607
608
Neal Norwitzb155b622006-01-23 07:52:13 +0000609class BadFileZipImportTestCase(unittest.TestCase):
610 def assertZipFailure(self, filename):
Benjamin Petersoneb437362014-02-16 14:12:57 -0500611 self.assertRaises(zipimport.ZipImportError,
612 zipimport.zipimporter, filename)
Neal Norwitzb155b622006-01-23 07:52:13 +0000613
614 def testNoFile(self):
615 self.assertZipFailure('AdfjdkFJKDFJjdklfjs')
616
617 def testEmptyFilename(self):
618 self.assertZipFailure('')
619
620 def testBadArgs(self):
621 self.assertRaises(TypeError, zipimport.zipimporter, None)
622 self.assertRaises(TypeError, zipimport.zipimporter, TESTMOD, kwd=None)
623
624 def testFilenameTooLong(self):
625 self.assertZipFailure('A' * 33000)
626
627 def testEmptyFile(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000628 support.unlink(TESTMOD)
Victor Stinnerbf816222011-06-30 23:25:47 +0200629 support.create_empty_file(TESTMOD)
Neal Norwitzb155b622006-01-23 07:52:13 +0000630 self.assertZipFailure(TESTMOD)
631
632 def testFileUnreadable(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000633 support.unlink(TESTMOD)
Neal Norwitzb155b622006-01-23 07:52:13 +0000634 fd = os.open(TESTMOD, os.O_CREAT, 000)
Tim Peters68f2d002006-01-23 22:19:24 +0000635 try:
636 os.close(fd)
Victor Stinnerfbd6f9e2015-03-20 10:52:25 +0100637
638 with self.assertRaises(zipimport.ZipImportError) as cm:
639 zipimport.zipimporter(TESTMOD)
Tim Peters68f2d002006-01-23 22:19:24 +0000640 finally:
641 # If we leave "the read-only bit" set on Windows, nothing can
642 # delete TESTMOD, and later tests suffer bogus failures.
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000643 os.chmod(TESTMOD, 0o666)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000644 support.unlink(TESTMOD)
Neal Norwitzb155b622006-01-23 07:52:13 +0000645
646 def testNotZipFile(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000647 support.unlink(TESTMOD)
Neal Norwitzb155b622006-01-23 07:52:13 +0000648 fp = open(TESTMOD, 'w+')
649 fp.write('a' * 22)
650 fp.close()
651 self.assertZipFailure(TESTMOD)
652
Neal Norwitzdbc95f42006-01-23 08:48:03 +0000653 # XXX: disabled until this works on Big-endian machines
654 def _testBogusZipFile(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000655 support.unlink(TESTMOD)
Neal Norwitzb155b622006-01-23 07:52:13 +0000656 fp = open(TESTMOD, 'w+')
657 fp.write(struct.pack('=I', 0x06054B50))
658 fp.write('a' * 18)
659 fp.close()
660 z = zipimport.zipimporter(TESTMOD)
661
662 try:
663 self.assertRaises(TypeError, z.find_module, None)
664 self.assertRaises(TypeError, z.load_module, None)
665 self.assertRaises(TypeError, z.is_package, None)
666 self.assertRaises(TypeError, z.get_code, None)
667 self.assertRaises(TypeError, z.get_data, None)
668 self.assertRaises(TypeError, z.get_source, None)
669
670 error = zipimport.ZipImportError
671 self.assertEqual(z.find_module('abc'), None)
672
673 self.assertRaises(error, z.load_module, 'abc')
674 self.assertRaises(error, z.get_code, 'abc')
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200675 self.assertRaises(OSError, z.get_data, 'abc')
Neal Norwitzb155b622006-01-23 07:52:13 +0000676 self.assertRaises(error, z.get_source, 'abc')
677 self.assertRaises(error, z.is_package, 'abc')
678 finally:
679 zipimport._zip_directory_cache.clear()
680
681
Neal Norwitz5c1ba532003-02-17 18:05:20 +0000682def test_main():
Neal Norwitzb155b622006-01-23 07:52:13 +0000683 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000684 support.run_unittest(
Neal Norwitzb155b622006-01-23 07:52:13 +0000685 UncompressedZipImportTestCase,
686 CompressedZipImportTestCase,
687 BadFileZipImportTestCase,
688 )
689 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000690 support.unlink(TESTMOD)
Neal Norwitz5c1ba532003-02-17 18:05:20 +0000691
692if __name__ == "__main__":
693 test_main()