Ticket #5766: zipstream-5766.patch

File zipstream-5766.patch, 15.1 KB (added by thijs, 4 years ago)
  • twisted/python/test/test_zipstream.py

     
    22# See LICENSE for details.
    33
    44"""
    5 Tests for L{twisted.python.zipstream}
     5Tests for L{twisted.python.zipstream}.
    66"""
     7
    78import sys
    89import random
    910import zipfile
     
    1112from twisted.python.compat import set
    1213from twisted.python import zipstream, filepath
    1314from twisted.python.hashlib import md5
    14 from twisted.trial import unittest, util
     15from twisted.trial import unittest
     16
    1517
    1618class FileEntryMixin:
    1719    """
    18     File entry classes should behave as file-like objects
     20    File entry classes should behave as file-like objects.
    1921    """
    2022    def getFileEntry(self, contents):
    2123        """
     
    3133
    3234    def test_isatty(self):
    3335        """
    34         zip files should not be ttys, so isatty() should be false
     36        zip files should not be ttys, so isatty() should be false.
    3537        """
    3638        self.assertEqual(self.getFileEntry('').isatty(), False)
    3739
     
    122124
    123125class DeflatedZipFileEntryTest(FileEntryMixin, unittest.TestCase):
    124126    """
    125     DeflatedZipFileEntry should be file-like
     127    DeflatedZipFileEntry should be file-like.
    126128    """
    127129    compression = zipfile.ZIP_DEFLATED
    128130
     
    130132
    131133class ZipFileEntryTest(FileEntryMixin, unittest.TestCase):
    132134   """
    133    ZipFileEntry should be file-like
     135   ZipFileEntry should be file-like.
    134136   """
    135137   compression = zipfile.ZIP_STORED
    136138
     
    138140
    139141class ZipstreamTest(unittest.TestCase):
    140142    """
    141     Tests for twisted.python.zipstream
     143    Tests for twisted.python.zipstream.
    142144    """
    143145    def setUp(self):
    144146        """
     
    167169        return zpfilename
    168170
    169171
    170     def test_countEntries(self):
    171         """
    172         Make sure the deprecated L{countZipFileEntries} returns the correct
    173         number of entries for a zip file.
    174         """
    175         name = self.makeZipFile(["one", "two", "three", "four", "five"])
    176         result = self.assertWarns(DeprecationWarning,
    177                                   "countZipFileEntries is deprecated.",
    178                                   __file__, lambda :
    179                                       zipstream.countZipFileEntries(name))
    180         self.assertEqual(result, 5)
    181 
    182 
    183172    def test_invalidMode(self):
    184173        """
    185174        A ChunkingZipFile opened in write-mode should not allow .readfile(),
     
    283272        self.assertEqual(czf.readfile("0").read(), "the real data")
    284273
    285274
    286     def test_unzipIter(self):
    287         """
    288         L{twisted.python.zipstream.unzipIter} should unzip a file for each
    289         iteration and yield the number of files left to unzip after that
    290         iteration
    291         """
    292         numfiles = 10
    293         contents = ['This is test file %d!' % i for i in range(numfiles)]
    294         zpfilename = self.makeZipFile(contents)
    295         uziter = zipstream.unzipIter(zpfilename, self.unzipdir.path)
    296         for i in range(numfiles):
    297             self.assertEqual(len(list(self.unzipdir.children())), i)
    298             self.assertEqual(uziter.next(), numfiles - i - 1)
    299         self.assertEqual(len(list(self.unzipdir.children())), numfiles)
    300 
    301         for child in self.unzipdir.children():
    302             num = int(child.basename())
    303             self.assertEqual(child.open().read(), contents[num])
    304     test_unzipIter.suppress = [
    305         util.suppress(message="zipstream.unzipIter is deprecated")]
    306 
    307 
    308     def test_unzipIterDeprecated(self):
    309         """
    310         Use of C{twisted.python.zipstream.unzipIter} will emit a
    311         deprecated warning.
    312         """
    313         zpfilename = self.makeZipFile('foo')
    314 
    315         self.assertEqual(len(self.flushWarnings()), 0)
    316 
    317         for f in zipstream.unzipIter(zpfilename, self.unzipdir.path):
    318             pass
    319 
    320         warnings = self.flushWarnings()
    321         self.assertEqual(len(warnings), 1)
    322         self.assertEqual(warnings[0]['category'], DeprecationWarning)
    323         self.assertEqual(
    324             warnings[0]['message'],
    325             "zipstream.unzipIter is deprecated since Twisted 11.0.0 for "
    326             "security reasons.  Use Python's zipfile instead.")
    327 
    328 
    329275    def test_unzipIterChunky(self):
    330276        """
    331277        L{twisted.python.zipstream.unzipIterChunky} returns an iterator which
     
    363309            self.assertEqual(child.getContent(), contents[num])
    364310
    365311
    366     def test_unzip(self):
    367         """
    368         L{twisted.python.zipstream.unzip} should extract all files from a zip
    369         archive
    370         """
    371         numfiles = 3
    372         zpfilename = self.makeZipFile([str(i) for i in range(numfiles)])
    373         zipstream.unzip(zpfilename, self.unzipdir.path)
    374         self.assertEqual(
    375             set(self.unzipdir.listdir()),
    376             set(map(str, range(numfiles))))
    377         for i in range(numfiles):
    378             self.assertEqual(self.unzipdir.child(str(i)).getContent(), str(i))
    379     test_unzip.suppress = [
    380         util.suppress(message="zipstream.unzip is deprecated")]
    381 
    382 
    383     def test_unzipDeprecated(self):
    384         """
    385         Use of C{twisted.python.zipstream.unzip} will emit a deprecated warning.
    386         """
    387         zpfilename = self.makeZipFile('foo')
    388 
    389         self.assertEqual(len(self.flushWarnings()), 0)
    390 
    391         zipstream.unzip(zpfilename, self.unzipdir.path)
    392 
    393         warnings = self.flushWarnings()
    394         self.assertEqual(len(warnings), 1)
    395         self.assertEqual(warnings[0]['category'], DeprecationWarning)
    396         self.assertEqual(
    397             warnings[0]['message'],
    398             "zipstream.unzip is deprecated since Twisted 11.0.0 for "
    399             "security reasons.  Use Python's zipfile instead.")
    400 
    401 
    402     def test_unzipDirectory(self):
    403         """
    404         The path to which a file is extracted by L{zipstream.unzip} is
    405         determined by joining the C{directory} argument to C{unzip} with the
    406         path within the archive of the file being extracted.
    407         """
    408         numfiles = 3
    409         zpfilename = self.makeZipFile([str(i) for i in range(numfiles)], 'foo')
    410         zipstream.unzip(zpfilename, self.unzipdir.path)
    411         self.assertEqual(
    412             set(self.unzipdir.child('foo').listdir()),
    413             set(map(str, range(numfiles))))
    414         for i in range(numfiles):
    415             self.assertEqual(
    416                 self.unzipdir.child('foo').child(str(i)).getContent(), str(i))
    417     test_unzipDirectory.suppress = [
    418         util.suppress(message="zipstream.unzip is deprecated")]
    419 
    420 
    421     def test_overwrite(self):
    422         """
    423         L{twisted.python.zipstream.unzip} and
    424         L{twisted.python.zipstream.unzipIter} shouldn't overwrite files unless
    425         the 'overwrite' flag is passed
    426         """
    427         testfile = self.unzipdir.child('0')
    428         zpfilename = self.makeZipFile(['OVERWRITTEN'])
    429 
    430         testfile.setContent('NOT OVERWRITTEN')
    431         zipstream.unzip(zpfilename, self.unzipdir.path)
    432         self.assertEqual(testfile.open().read(), 'NOT OVERWRITTEN')
    433         zipstream.unzip(zpfilename, self.unzipdir.path, overwrite=True)
    434         self.assertEqual(testfile.open().read(), 'OVERWRITTEN')
    435 
    436         testfile.setContent('NOT OVERWRITTEN')
    437         uziter = zipstream.unzipIter(zpfilename, self.unzipdir.path)
    438         uziter.next()
    439         self.assertEqual(testfile.open().read(), 'NOT OVERWRITTEN')
    440         uziter = zipstream.unzipIter(zpfilename, self.unzipdir.path,
    441                                      overwrite=True)
    442         uziter.next()
    443         self.assertEqual(testfile.open().read(), 'OVERWRITTEN')
    444     test_overwrite.suppress = [
    445         util.suppress(message="zipstream.unzip is deprecated"),
    446         util.suppress(message="zipstream.unzipIter is deprecated")]
    447 
    448 
    449312    # XXX these tests are kind of gross and old, but I think unzipIterChunky is
    450313    # kind of a gross function anyway.  We should really write an abstract
    451314    # copyTo/moveTo that operates on FilePath and make sure ZipPath can support
  • twisted/python/zipstream.py

     
    77bit of a file at a time, which means you can report progress as a file unzips.
    88"""
    99
    10 import warnings
    1110import zipfile
    1211import os.path
    1312import zlib
    1413import struct
    1514
     15
    1616_fileHeaderSize = struct.calcsize(zipfile.structFileHeader)
    1717
    1818class ChunkingZipFile(zipfile.ZipFile):
    1919    """
    20     A ZipFile object which, with readfile(), also gives you access to a
    21     filelike object for each entry.
     20    A C{ZipFile} object which, with L{readfile}, also gives you access to a
     21    file-like object for each entry.
    2222    """
    2323
    2424    def readfile(self, name):
     
    6565    Abstract superclass of both compressed and uncompressed variants of
    6666    file-like objects within a zip archive.
    6767
    68     @ivar chunkingZipFile: a chunking zip file.
     68    @ivar chunkingZipFile: A chunking zip file.
    6969    @type chunkingZipFile: L{ChunkingZipFile}
    7070
    7171    @ivar length: The number of bytes within the zip file that represent this
    7272    file.  (This is the size on disk, not the number of decompressed bytes
    7373    which will result from reading it.)
    7474
    75     @ivar fp: the underlying file object (that contains pkzip data).  Do not
     75    @ivar fp: The underlying file object (that contains pkzip data).  Do not
    7676    touch this, please.  It will quite likely move or go away.
    7777
    7878    @ivar closed: File-like 'closed' attribute; True before this file has been
    7979    closed, False after.
    80     @type closed: L{bool}
     80    @type closed: C{bool}
    8181
    8282    @ivar finished: An older, broken synonym for 'closed'.  Do not touch this,
    8383    please.
    84     @type finished: L{int}
     84    @type finished: C{int}
    8585    """
    8686    def __init__(self, chunkingZipFile, length):
    8787        """
     
    9696
    9797    def isatty(self):
    9898        """
    99         Returns false because zip files should not be ttys
     99        Returns C{False} because zip files should not be ttys.
    100100        """
    101101        return False
    102102
    103103
    104104    def close(self):
    105105        """
    106         Close self (file-like object)
     106        Close self (file-like object).
    107107        """
    108108        self.closed = True
    109109        self.finished = 1
     
    124124
    125125    def next(self):
    126126        """
    127         Implement next as file does (like readline, except raises StopIteration
    128         at EOF)
     127        Implement next as file does (like L{readline}, except raises
     128        C{StopIteration} at EOF).
    129129        """
    130130        nextline = self.readline()
    131131        if nextline:
     
    135135
    136136    def readlines(self):
    137137        """
    138         Returns a list of all the lines
     138        Returns a list of all the lines.
    139139        """
    140140        return list(self)
    141141
    142142
    143143    def xreadlines(self):
    144144        """
    145         Returns an iterator (so self)
     145        Returns an iterator (so self).
    146146        """
    147147        return self
    148148
    149149
    150150    def __iter__(self):
    151151        """
    152         Returns an iterator (so self)
     152        Returns an iterator (so self).
    153153        """
    154154        return self
    155155
     
    157157
    158158class ZipFileEntry(_FileEntry):
    159159    """
    160     File-like object used to read an uncompressed entry in a ZipFile
     160    File-like object used to read an uncompressed entry in a C{ZipFile}.
    161161    """
    162162
    163163    def __init__(self, chunkingZipFile, length):
     
    185185
    186186class DeflatedZipFileEntry(_FileEntry):
    187187    """
    188     File-like object used to read a deflated entry in a ZipFile
     188    File-like object used to read a deflated entry in a C{ZipFile}.
    189189    """
    190190
    191191    def __init__(self, chunkingZipFile, length):
     
    238238
    239239
    240240
    241 def unzip(filename, directory=".", overwrite=0):
    242     """
    243     Unzip the file
    244 
    245     @param filename: the name of the zip file
    246     @param directory: the directory into which the files will be
    247     extracted
    248     @param overwrite: if on, overwrite files when they exist.  You can
    249     still get an error if you try to create a directory over a file
    250     with the same name or vice-versa.
    251     """
    252     warnings.warn("zipstream.unzip is deprecated since Twisted 11.0.0 for " +
    253                   "security reasons.  Use Python's zipfile instead.",
    254                   category=DeprecationWarning, stacklevel=2)
    255 
    256     for i in unzipIter(filename, directory, overwrite, suppressWarning=True):
    257         pass
    258 
    259241DIR_BIT = 16
    260242
    261 def unzipIter(filename, directory='.', overwrite=0, suppressWarning=False):
    262     """
    263     Return a generator for the zipfile.  This implementation will yield
    264     after every file.
    265 
    266     The value it yields is the number of files left to unzip.
    267     """
    268     if not suppressWarning:
    269         warnings.warn("zipstream.unzipIter is deprecated since Twisted " +
    270                       "11.0.0 for security reasons.  Use Python's " +
    271                       "zipfile instead.",
    272                       category=DeprecationWarning, stacklevel=2)
    273 
    274     zf = zipfile.ZipFile(filename, 'r')
    275     names = zf.namelist()
    276     if not os.path.exists(directory):
    277         os.makedirs(directory)
    278     remaining = len(zf.namelist())
    279     for entry in names:
    280         remaining -= 1
    281         isdir = zf.getinfo(entry).external_attr & DIR_BIT
    282         f = os.path.join(directory, entry)
    283         if isdir:
    284             # overwrite flag only applies to files
    285             if not os.path.exists(f):
    286                 os.makedirs(f)
    287         else:
    288             # create the directory the file will be in first,
    289             # since we can't guarantee it exists
    290             fdir = os.path.split(f)[0]
    291             if not os.path.exists(fdir):
    292                 os.makedirs(fdir)
    293             if overwrite or not os.path.exists(f):
    294                 outfile = file(f, 'wb')
    295                 outfile.write(zf.read(entry))
    296                 outfile.close()
    297         yield remaining
    298 
    299243
    300244def countZipFileChunks(filename, chunksize):
    301245    """
     
    311255
    312256def countFileChunks(zipinfo, chunksize):
    313257    """
    314     Count the number of chunks that will result from the given L{ZipInfo}.
     258    Count the number of chunks that will result from the given C{ZipInfo}.
    315259
    316     @param zipinfo: a L{zipfile.ZipInfo} instance describing an entry in a zip
     260    @param zipinfo: a C{zipfile.ZipInfo} instance describing an entry in a zip
    317261    archive to be counted.
    318262
    319263    @return: the number of chunks present in the zip file.  (Even an empty file
    320264    counts as one chunk.)
    321     @rtype: L{int}
     265    @rtype: C{int}
    322266    """
    323267    count, extra = divmod(zipinfo.file_size, chunksize)
    324268    if extra > 0:
     
    326270    return count or 1
    327271
    328272
    329 def countZipFileEntries(filename):
    330     """
    331     Count the number of entries in a zip archive.  (Don't use this function.)
    332 
    333     @param filename: The filename of a zip archive.
    334     @type filename: L{str}
    335     """
    336     warnings.warn("countZipFileEntries is deprecated.",
    337                   DeprecationWarning, 2)
    338     zf = zipfile.ZipFile(filename)
    339     return len(zf.namelist())
    340 
    341273
    342274def unzipIterChunky(filename, directory='.', overwrite=0,
    343275                    chunksize=4096):
  • twisted/topfiles/5766.removal

     
     1unzip, unzipIter, and countZipFileEntries in twisted.python.zipstream (deprecated in Twisted 11.0) are removed now.