Ticket #5766: zipstream-5766.patch
| File zipstream-5766.patch, 15.1 KB (added by thijs, 11 months ago) |
|---|
-
twisted/python/test/test_zipstream.py
2 2 # See LICENSE for details. 3 3 4 4 """ 5 Tests for L{twisted.python.zipstream} 5 Tests for L{twisted.python.zipstream}. 6 6 """ 7 7 8 import sys 8 9 import random 9 10 import zipfile … … 11 12 from twisted.python.compat import set 12 13 from twisted.python import zipstream, filepath 13 14 from twisted.python.hashlib import md5 14 from twisted.trial import unittest, util 15 from twisted.trial import unittest 16 15 17 16 18 class FileEntryMixin: 17 19 """ 18 File entry classes should behave as file-like objects 20 File entry classes should behave as file-like objects. 19 21 """ 20 22 def getFileEntry(self, contents): 21 23 """ … … 31 33 32 34 def test_isatty(self): 33 35 """ 34 zip files should not be ttys, so isatty() should be false 36 zip files should not be ttys, so isatty() should be false. 35 37 """ 36 38 self.assertEqual(self.getFileEntry('').isatty(), False) 37 39 … … 122 124 123 125 class DeflatedZipFileEntryTest(FileEntryMixin, unittest.TestCase): 124 126 """ 125 DeflatedZipFileEntry should be file-like 127 DeflatedZipFileEntry should be file-like. 126 128 """ 127 129 compression = zipfile.ZIP_DEFLATED 128 130 … … 130 132 131 133 class ZipFileEntryTest(FileEntryMixin, unittest.TestCase): 132 134 """ 133 ZipFileEntry should be file-like 135 ZipFileEntry should be file-like. 134 136 """ 135 137 compression = zipfile.ZIP_STORED 136 138 … … 138 140 139 141 class ZipstreamTest(unittest.TestCase): 140 142 """ 141 Tests for twisted.python.zipstream 143 Tests for twisted.python.zipstream. 142 144 """ 143 145 def setUp(self): 144 146 """ … … 167 169 return zpfilename 168 170 169 171 170 def test_countEntries(self):171 """172 Make sure the deprecated L{countZipFileEntries} returns the correct173 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 183 172 def test_invalidMode(self): 184 173 """ 185 174 A ChunkingZipFile opened in write-mode should not allow .readfile(), … … 283 272 self.assertEqual(czf.readfile("0").read(), "the real data") 284 273 285 274 286 def test_unzipIter(self):287 """288 L{twisted.python.zipstream.unzipIter} should unzip a file for each289 iteration and yield the number of files left to unzip after that290 iteration291 """292 numfiles = 10293 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 a311 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 pass319 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 329 275 def test_unzipIterChunky(self): 330 276 """ 331 277 L{twisted.python.zipstream.unzipIterChunky} returns an iterator which … … 363 309 self.assertEqual(child.getContent(), contents[num]) 364 310 365 311 366 def test_unzip(self):367 """368 L{twisted.python.zipstream.unzip} should extract all files from a zip369 archive370 """371 numfiles = 3372 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} is405 determined by joining the C{directory} argument to C{unzip} with the406 path within the archive of the file being extracted.407 """408 numfiles = 3409 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} and424 L{twisted.python.zipstream.unzipIter} shouldn't overwrite files unless425 the 'overwrite' flag is passed426 """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 449 312 # XXX these tests are kind of gross and old, but I think unzipIterChunky is 450 313 # kind of a gross function anyway. We should really write an abstract 451 314 # copyTo/moveTo that operates on FilePath and make sure ZipPath can support -
twisted/python/zipstream.py
7 7 bit of a file at a time, which means you can report progress as a file unzips. 8 8 """ 9 9 10 import warnings11 10 import zipfile 12 11 import os.path 13 12 import zlib 14 13 import struct 15 14 15 16 16 _fileHeaderSize = struct.calcsize(zipfile.structFileHeader) 17 17 18 18 class ChunkingZipFile(zipfile.ZipFile): 19 19 """ 20 A ZipFile object which, with readfile(), also gives you access to a21 file like 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. 22 22 """ 23 23 24 24 def readfile(self, name): … … 65 65 Abstract superclass of both compressed and uncompressed variants of 66 66 file-like objects within a zip archive. 67 67 68 @ivar chunkingZipFile: achunking zip file.68 @ivar chunkingZipFile: A chunking zip file. 69 69 @type chunkingZipFile: L{ChunkingZipFile} 70 70 71 71 @ivar length: The number of bytes within the zip file that represent this 72 72 file. (This is the size on disk, not the number of decompressed bytes 73 73 which will result from reading it.) 74 74 75 @ivar fp: the underlying file object (that contains pkzip data). Do not75 @ivar fp: The underlying file object (that contains pkzip data). Do not 76 76 touch this, please. It will quite likely move or go away. 77 77 78 78 @ivar closed: File-like 'closed' attribute; True before this file has been 79 79 closed, False after. 80 @type closed: L{bool}80 @type closed: C{bool} 81 81 82 82 @ivar finished: An older, broken synonym for 'closed'. Do not touch this, 83 83 please. 84 @type finished: L{int}84 @type finished: C{int} 85 85 """ 86 86 def __init__(self, chunkingZipFile, length): 87 87 """ … … 96 96 97 97 def isatty(self): 98 98 """ 99 Returns false because zip files should not be ttys99 Returns C{False} because zip files should not be ttys. 100 100 """ 101 101 return False 102 102 103 103 104 104 def close(self): 105 105 """ 106 Close self (file-like object) 106 Close self (file-like object). 107 107 """ 108 108 self.closed = True 109 109 self.finished = 1 … … 124 124 125 125 def next(self): 126 126 """ 127 Implement next as file does (like readline, except raises StopIteration128 at EOF)127 Implement next as file does (like L{readline}, except raises 128 C{StopIteration} at EOF). 129 129 """ 130 130 nextline = self.readline() 131 131 if nextline: … … 135 135 136 136 def readlines(self): 137 137 """ 138 Returns a list of all the lines 138 Returns a list of all the lines. 139 139 """ 140 140 return list(self) 141 141 142 142 143 143 def xreadlines(self): 144 144 """ 145 Returns an iterator (so self) 145 Returns an iterator (so self). 146 146 """ 147 147 return self 148 148 149 149 150 150 def __iter__(self): 151 151 """ 152 Returns an iterator (so self) 152 Returns an iterator (so self). 153 153 """ 154 154 return self 155 155 … … 157 157 158 158 class ZipFileEntry(_FileEntry): 159 159 """ 160 File-like object used to read an uncompressed entry in a ZipFile160 File-like object used to read an uncompressed entry in a C{ZipFile}. 161 161 """ 162 162 163 163 def __init__(self, chunkingZipFile, length): … … 185 185 186 186 class DeflatedZipFileEntry(_FileEntry): 187 187 """ 188 File-like object used to read a deflated entry in a ZipFile188 File-like object used to read a deflated entry in a C{ZipFile}. 189 189 """ 190 190 191 191 def __init__(self, chunkingZipFile, length): … … 238 238 239 239 240 240 241 def unzip(filename, directory=".", overwrite=0):242 """243 Unzip the file244 245 @param filename: the name of the zip file246 @param directory: the directory into which the files will be247 extracted248 @param overwrite: if on, overwrite files when they exist. You can249 still get an error if you try to create a directory over a file250 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 pass258 259 241 DIR_BIT = 16 260 242 261 def unzipIter(filename, directory='.', overwrite=0, suppressWarning=False):262 """263 Return a generator for the zipfile. This implementation will yield264 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 -= 1281 isdir = zf.getinfo(entry).external_attr & DIR_BIT282 f = os.path.join(directory, entry)283 if isdir:284 # overwrite flag only applies to files285 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 exists290 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 remaining298 299 243 300 244 def countZipFileChunks(filename, chunksize): 301 245 """ … … 311 255 312 256 def countFileChunks(zipinfo, chunksize): 313 257 """ 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}. 315 259 316 @param zipinfo: a L{zipfile.ZipInfo} instance describing an entry in a zip260 @param zipinfo: a C{zipfile.ZipInfo} instance describing an entry in a zip 317 261 archive to be counted. 318 262 319 263 @return: the number of chunks present in the zip file. (Even an empty file 320 264 counts as one chunk.) 321 @rtype: L{int}265 @rtype: C{int} 322 266 """ 323 267 count, extra = divmod(zipinfo.file_size, chunksize) 324 268 if extra > 0: … … 326 270 return count or 1 327 271 328 272 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 341 273 342 274 def unzipIterChunky(filename, directory='.', overwrite=0, 343 275 chunksize=4096): -
twisted/topfiles/5766.removal
1 unzip, unzipIter, and countZipFileEntries in twisted.python.zipstream (deprecated in Twisted 11.0) are removed now.
