Home | History | Annotate | Download | only in test
      1 import sys
      2 import os
      3 import marshal
      4 import importlib
      5 import importlib.util
      6 import struct
      7 import time
      8 import unittest
      9 
     10 from test import support
     11 
     12 from zipfile import ZipFile, ZipInfo, ZIP_STORED, ZIP_DEFLATED
     13 
     14 import zipimport
     15 import linecache
     16 import doctest
     17 import inspect
     18 import io
     19 from traceback import extract_tb, extract_stack, print_tb
     20 
     21 test_src = """\
     22 def get_name():
     23     return __name__
     24 def get_file():
     25     return __file__
     26 """
     27 test_co = compile(test_src, "<???>", "exec")
     28 raise_src = 'def do_raise(): raise TypeError\n'
     29 
     30 def make_pyc(co, mtime, size):
     31     data = marshal.dumps(co)
     32     if type(mtime) is type(0.0):
     33         # Mac mtimes need a bit of special casing
     34         if mtime < 0x7fffffff:
     35             mtime = int(mtime)
     36         else:
     37             mtime = int(-0x100000000 + int(mtime))
     38     pyc = (importlib.util.MAGIC_NUMBER +
     39         struct.pack("<ii", int(mtime), size & 0xFFFFFFFF) + data)
     40     return pyc
     41 
     42 def module_path_to_dotted_name(path):
     43     return path.replace(os.sep, '.')
     44 
     45 NOW = time.time()
     46 test_pyc = make_pyc(test_co, NOW, len(test_src))
     47 
     48 
     49 TESTMOD = "ziptestmodule"
     50 TESTPACK = "ziptestpackage"
     51 TESTPACK2 = "ziptestpackage2"
     52 TEMP_DIR = os.path.abspath("junk95142")
     53 TEMP_ZIP = os.path.abspath("junk95142.zip")
     54 
     55 pyc_file = importlib.util.cache_from_source(TESTMOD + '.py')
     56 pyc_ext = '.pyc'
     57 
     58 
     59 class 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 
     76 class 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
     82         # cached directory info and linecache.
     83         linecache.clearcache()
     84         zipimport._zip_directory_cache.clear()
     85         ImportHooksBaseTestCase.setUp(self)
     86 
     87     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:
    111             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)
    115 
    116         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)
    124 
    125     def doTest(self, expected_ext, files, *modules, **kw):
    126         self.makeZip(files, **kw)
    127 
    128         sys.path.insert(0, TEMP_ZIP)
    129 
    130         mod = importlib.import_module(".".join(modules))
    131 
    132         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,
    139                                  *modules) + expected_ext)
    140 
    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         #
    154         # 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:
    160             self.skipTest('zlib is a builtin module')
    161         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 
    186     def testEmptyPy(self):
    187         files = {TESTMOD + ".py": (NOW, "")}
    188         self.doTest(None, files, TESTMOD)
    189 
    190     def testBadMagic(self):
    191         # make pyc magic word invalid, forcing loading from .py
    192         badmagic_pyc = bytearray(test_pyc)
    193         badmagic_pyc[0] ^= 0x04  # flip an arbitrary bit
    194         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
    200         badmagic_pyc = bytearray(test_pyc)
    201         badmagic_pyc[0] ^= 0x04  # flip an arbitrary bit
    202         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):
    211         badtime_pyc = bytearray(test_pyc)
    212         # 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
    215         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 
    225     def testSubPackage(self):
    226         # Test that subpackages function when loaded from zip
    227         # archives.
    228         packdir = TESTPACK + os.sep
    229         packdir2 = packdir + TESTPACK2 + os.sep
    230         files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
    231                  packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
    232                  packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
    233         self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
    234 
    235     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 
    396     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                  "spam" + pyc_ext: (NOW, test_pyc)}
    403 
    404         z = ZipFile(TEMP_ZIP, "w")
    405         try:
    406             for name, (mtime, data) in files.items():
    407                 zinfo = ZipInfo(name, time.localtime(mtime))
    408                 zinfo.compress_type = self.compression
    409                 zinfo.comment = b"spam"
    410                 z.writestr(zinfo, data)
    411             z.close()
    412 
    413             zi = zipimport.zipimporter(TEMP_ZIP)
    414             self.assertEqual(zi.archive, TEMP_ZIP)
    415             self.assertEqual(zi.is_package(TESTPACK), True)
    416 
    417             find_mod = zi.find_module('spam')
    418             self.assertIsNotNone(find_mod)
    419             self.assertIsInstance(find_mod, zipimport.zipimporter)
    420             self.assertFalse(find_mod.is_package('spam'))
    421             load_mod = find_mod.load_module('spam')
    422             self.assertEqual(find_mod.get_filename('spam'), load_mod.__file__)
    423 
    424             mod = zi.load_module(TESTPACK)
    425             self.assertEqual(zi.get_filename(TESTPACK), mod.__file__)
    426 
    427             existing_pack_path = importlib.import_module(TESTPACK).__path__[0]
    428             expected_path_path = os.path.join(TEMP_ZIP, TESTPACK)
    429             self.assertEqual(existing_pack_path, expected_path_path)
    430 
    431             self.assertEqual(zi.is_package(packdir + '__init__'), False)
    432             self.assertEqual(zi.is_package(packdir + TESTPACK2), True)
    433             self.assertEqual(zi.is_package(packdir2 + TESTMOD), False)
    434 
    435             mod_path = packdir2 + TESTMOD
    436             mod_name = module_path_to_dotted_name(mod_path)
    437             mod = importlib.import_module(mod_name)
    438             self.assertTrue(mod_name in sys.modules)
    439             self.assertEqual(zi.get_source(TESTPACK), None)
    440             self.assertEqual(zi.get_source(mod_path), None)
    441             self.assertEqual(zi.get_filename(mod_path), mod.__file__)
    442             # To pass in the module name instead of the path, we must use the
    443             # right importer
    444             loader = mod.__loader__
    445             self.assertEqual(loader.get_source(mod_name), None)
    446             self.assertEqual(loader.get_filename(mod_name), mod.__file__)
    447 
    448             # test prefix and archivepath members
    449             zi2 = zipimport.zipimporter(TEMP_ZIP + os.sep + TESTPACK)
    450             self.assertEqual(zi2.archive, TEMP_ZIP)
    451             self.assertEqual(zi2.prefix, TESTPACK + os.sep)
    452         finally:
    453             z.close()
    454             os.remove(TEMP_ZIP)
    455 
    456     def testZipImporterMethodsInSubDirectory(self):
    457         packdir = TESTPACK + os.sep
    458         packdir2 = packdir + TESTPACK2 + os.sep
    459         files = {packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
    460                  packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
    461 
    462         z = ZipFile(TEMP_ZIP, "w")
    463         try:
    464             for name, (mtime, data) in files.items():
    465                 zinfo = ZipInfo(name, time.localtime(mtime))
    466                 zinfo.compress_type = self.compression
    467                 zinfo.comment = b"eggs"
    468                 z.writestr(zinfo, data)
    469             z.close()
    470 
    471             zi = zipimport.zipimporter(TEMP_ZIP + os.sep + packdir)
    472             self.assertEqual(zi.archive, TEMP_ZIP)
    473             self.assertEqual(zi.prefix, packdir)
    474             self.assertEqual(zi.is_package(TESTPACK2), True)
    475             mod = zi.load_module(TESTPACK2)
    476             self.assertEqual(zi.get_filename(TESTPACK2), mod.__file__)
    477 
    478             self.assertEqual(
    479                 zi.is_package(TESTPACK2 + os.sep + '__init__'), False)
    480             self.assertEqual(
    481                 zi.is_package(TESTPACK2 + os.sep + TESTMOD), False)
    482 
    483             pkg_path = TEMP_ZIP + os.sep + packdir + TESTPACK2
    484             zi2 = zipimport.zipimporter(pkg_path)
    485             find_mod_dotted = zi2.find_module(TESTMOD)
    486             self.assertIsNotNone(find_mod_dotted)
    487             self.assertIsInstance(find_mod_dotted, zipimport.zipimporter)
    488             self.assertFalse(zi2.is_package(TESTMOD))
    489             load_mod = find_mod_dotted.load_module(TESTMOD)
    490             self.assertEqual(
    491                 find_mod_dotted.get_filename(TESTMOD), load_mod.__file__)
    492 
    493             mod_path = TESTPACK2 + os.sep + TESTMOD
    494             mod_name = module_path_to_dotted_name(mod_path)
    495             mod = importlib.import_module(mod_name)
    496             self.assertTrue(mod_name in sys.modules)
    497             self.assertEqual(zi.get_source(TESTPACK2), None)
    498             self.assertEqual(zi.get_source(mod_path), None)
    499             self.assertEqual(zi.get_filename(mod_path), mod.__file__)
    500             # To pass in the module name instead of the path, we must use the
    501             # right importer.
    502             loader = mod.__loader__
    503             self.assertEqual(loader.get_source(mod_name), None)
    504             self.assertEqual(loader.get_filename(mod_name), mod.__file__)
    505         finally:
    506             z.close()
    507             os.remove(TEMP_ZIP)
    508 
    509     def testGetData(self):
    510         z = ZipFile(TEMP_ZIP, "w")
    511         z.compression = self.compression
    512         try:
    513             name = "testdata.dat"
    514             data = bytes(x for x in range(256))
    515             z.writestr(name, data)
    516             z.close()
    517             zi = zipimport.zipimporter(TEMP_ZIP)
    518             self.assertEqual(data, zi.get_data(name))
    519             self.assertIn('zipimporter object', repr(zi))
    520         finally:
    521             z.close()
    522             os.remove(TEMP_ZIP)
    523 
    524     def testImporterAttr(self):
    525         src = """if 1:  # indent hack
    526         def get_file():
    527             return __file__
    528         if __loader__.get_data("some.data") != b"some data":
    529             raise AssertionError("bad data")\n"""
    530         pyc = make_pyc(compile(src, "<???>", "exec"), NOW, len(src))
    531         files = {TESTMOD + pyc_ext: (NOW, pyc),
    532                  "some.data": (NOW, "some data")}
    533         self.doTest(pyc_ext, files, TESTMOD)
    534 
    535     def testDefaultOptimizationLevel(self):
    536         # zipimport should use the default optimization level (#28131)
    537         src = """if 1:  # indent hack
    538         def test(val):
    539             assert(val)
    540             return val\n"""
    541         files = {TESTMOD + '.py': (NOW, src)}
    542         self.makeZip(files)
    543         sys.path.insert(0, TEMP_ZIP)
    544         mod = importlib.import_module(TESTMOD)
    545         self.assertEqual(mod.test(1), 1)
    546         self.assertRaises(AssertionError, mod.test, False)
    547 
    548     def testImport_WithStuff(self):
    549         # try importing from a zipfile which contains additional
    550         # stuff at the beginning of the file
    551         files = {TESTMOD + ".py": (NOW, test_src)}
    552         self.doTest(".py", files, TESTMOD,
    553                     stuff=b"Some Stuff"*31)
    554 
    555     def assertModuleSource(self, module):
    556         self.assertEqual(inspect.getsource(module), test_src)
    557 
    558     def testGetSource(self):
    559         files = {TESTMOD + ".py": (NOW, test_src)}
    560         self.doTest(".py", files, TESTMOD, call=self.assertModuleSource)
    561 
    562     def testGetCompiledSource(self):
    563         pyc = make_pyc(compile(test_src, "<???>", "exec"), NOW, len(test_src))
    564         files = {TESTMOD + ".py": (NOW, test_src),
    565                  TESTMOD + pyc_ext: (NOW, pyc)}
    566         self.doTest(pyc_ext, files, TESTMOD, call=self.assertModuleSource)
    567 
    568     def runDoctest(self, callback):
    569         files = {TESTMOD + ".py": (NOW, test_src),
    570                  "xyz.txt": (NOW, ">>> log.append(True)\n")}
    571         self.doTest(".py", files, TESTMOD, call=callback)
    572 
    573     def doDoctestFile(self, module):
    574         log = []
    575         old_master, doctest.master = doctest.master, None
    576         try:
    577             doctest.testfile(
    578                 'xyz.txt', package=module, module_relative=True,
    579                 globs=locals()
    580             )
    581         finally:
    582             doctest.master = old_master
    583         self.assertEqual(log,[True])
    584 
    585     def testDoctestFile(self):
    586         self.runDoctest(self.doDoctestFile)
    587 
    588     def doDoctestSuite(self, module):
    589         log = []
    590         doctest.DocFileTest(
    591             'xyz.txt', package=module, module_relative=True,
    592             globs=locals()
    593         ).run()
    594         self.assertEqual(log,[True])
    595 
    596     def testDoctestSuite(self):
    597         self.runDoctest(self.doDoctestSuite)
    598 
    599     def doTraceback(self, module):
    600         try:
    601             module.do_raise()
    602         except:
    603             tb = sys.exc_info()[2].tb_next
    604 
    605             f,lno,n,line = extract_tb(tb, 1)[0]
    606             self.assertEqual(line, raise_src.strip())
    607 
    608             f,lno,n,line = extract_stack(tb.tb_frame, 1)[0]
    609             self.assertEqual(line, raise_src.strip())
    610 
    611             s = io.StringIO()
    612             print_tb(tb, 1, s)
    613             self.assertTrue(s.getvalue().endswith(raise_src))
    614         else:
    615             raise AssertionError("This ought to be impossible")
    616 
    617     def testTraceback(self):
    618         files = {TESTMOD + ".py": (NOW, raise_src)}
    619         self.doTest(None, files, TESTMOD, call=self.doTraceback)
    620 
    621     @unittest.skipIf(support.TESTFN_UNENCODABLE is None,
    622                      "need an unencodable filename")
    623     def testUnencodable(self):
    624         filename = support.TESTFN_UNENCODABLE + ".zip"
    625         z = ZipFile(filename, "w")
    626         zinfo = ZipInfo(TESTMOD + ".py", time.localtime(NOW))
    627         zinfo.compress_type = self.compression
    628         z.writestr(zinfo, test_src)
    629         z.close()
    630         try:
    631             zipimport.zipimporter(filename).load_module(TESTMOD)
    632         finally:
    633             os.remove(filename)
    634 
    635     def testBytesPath(self):
    636         filename = support.TESTFN + ".zip"
    637         self.addCleanup(support.unlink, filename)
    638         with ZipFile(filename, "w") as z:
    639             zinfo = ZipInfo(TESTMOD + ".py", time.localtime(NOW))
    640             zinfo.compress_type = self.compression
    641             z.writestr(zinfo, test_src)
    642 
    643         zipimport.zipimporter(filename)
    644         zipimport.zipimporter(os.fsencode(filename))
    645         with self.assertWarns(DeprecationWarning):
    646             zipimport.zipimporter(bytearray(os.fsencode(filename)))
    647         with self.assertWarns(DeprecationWarning):
    648             zipimport.zipimporter(memoryview(os.fsencode(filename)))
    649 
    650 
    651 @support.requires_zlib
    652 class CompressedZipImportTestCase(UncompressedZipImportTestCase):
    653     compression = ZIP_DEFLATED
    654 
    655 
    656 class BadFileZipImportTestCase(unittest.TestCase):
    657     def assertZipFailure(self, filename):
    658         self.assertRaises(zipimport.ZipImportError,
    659                           zipimport.zipimporter, filename)
    660 
    661     def testNoFile(self):
    662         self.assertZipFailure('AdfjdkFJKDFJjdklfjs')
    663 
    664     def testEmptyFilename(self):
    665         self.assertZipFailure('')
    666 
    667     def testBadArgs(self):
    668         self.assertRaises(TypeError, zipimport.zipimporter, None)
    669         self.assertRaises(TypeError, zipimport.zipimporter, TESTMOD, kwd=None)
    670         self.assertRaises(TypeError, zipimport.zipimporter,
    671                           list(os.fsencode(TESTMOD)))
    672 
    673     def testFilenameTooLong(self):
    674         self.assertZipFailure('A' * 33000)
    675 
    676     def testEmptyFile(self):
    677         support.unlink(TESTMOD)
    678         support.create_empty_file(TESTMOD)
    679         self.assertZipFailure(TESTMOD)
    680 
    681     def testFileUnreadable(self):
    682         support.unlink(TESTMOD)
    683         fd = os.open(TESTMOD, os.O_CREAT, 000)
    684         try:
    685             os.close(fd)
    686 
    687             with self.assertRaises(zipimport.ZipImportError) as cm:
    688                 zipimport.zipimporter(TESTMOD)
    689         finally:
    690             # If we leave "the read-only bit" set on Windows, nothing can
    691             # delete TESTMOD, and later tests suffer bogus failures.
    692             os.chmod(TESTMOD, 0o666)
    693             support.unlink(TESTMOD)
    694 
    695     def testNotZipFile(self):
    696         support.unlink(TESTMOD)
    697         fp = open(TESTMOD, 'w+')
    698         fp.write('a' * 22)
    699         fp.close()
    700         self.assertZipFailure(TESTMOD)
    701 
    702     # XXX: disabled until this works on Big-endian machines
    703     def _testBogusZipFile(self):
    704         support.unlink(TESTMOD)
    705         fp = open(TESTMOD, 'w+')
    706         fp.write(struct.pack('=I', 0x06054B50))
    707         fp.write('a' * 18)
    708         fp.close()
    709         z = zipimport.zipimporter(TESTMOD)
    710 
    711         try:
    712             self.assertRaises(TypeError, z.find_module, None)
    713             self.assertRaises(TypeError, z.load_module, None)
    714             self.assertRaises(TypeError, z.is_package, None)
    715             self.assertRaises(TypeError, z.get_code, None)
    716             self.assertRaises(TypeError, z.get_data, None)
    717             self.assertRaises(TypeError, z.get_source, None)
    718 
    719             error = zipimport.ZipImportError
    720             self.assertEqual(z.find_module('abc'), None)
    721 
    722             self.assertRaises(error, z.load_module, 'abc')
    723             self.assertRaises(error, z.get_code, 'abc')
    724             self.assertRaises(OSError, z.get_data, 'abc')
    725             self.assertRaises(error, z.get_source, 'abc')
    726             self.assertRaises(error, z.is_package, 'abc')
    727         finally:
    728             zipimport._zip_directory_cache.clear()
    729 
    730 
    731 def test_main():
    732     try:
    733         support.run_unittest(
    734               UncompressedZipImportTestCase,
    735               CompressedZipImportTestCase,
    736               BadFileZipImportTestCase,
    737             )
    738     finally:
    739         support.unlink(TESTMOD)
    740 
    741 if __name__ == "__main__":
    742     test_main()
    743