This commit is contained in:
Faik Uygur
2006-04-20 16:29:13 +00:00
parent 240269ea8b
commit ecb6f87bbb
+75 -59
View File
@@ -9,11 +9,10 @@
# #
# Please read the COPYING file. # Please read the COPYING file.
# #
# Authors: Eray Ozkural <eray at pardus.org.tr> # Authors: Eray Ozkural <eray@pardus.org.tr>
# Faik Uygur <faik at pardus.org.tr> # Faik Uygur <faik@pardus.org.tr>
# #
# Extends zipfile module with lzma and bzip2 support
"""Extends zipfile module with lzma and bzip2 support"""
# python standard library modules # python standard library modules
import os import os
@@ -29,9 +28,9 @@ except ImportError:
zlib = None zlib = None
try: try:
import bz2 import bzip2
except ImportError: except ImportError:
bz2 = None bzip2 = None
try: try:
import pylzma import pylzma
@@ -43,8 +42,7 @@ ZIP_LZMA = 255
compression_methods = [ZIP_STORED, ZIP_DEFLATED, ZIP_BZIP2, ZIP_LZMA] compression_methods = [ZIP_STORED, ZIP_DEFLATED, ZIP_BZIP2, ZIP_LZMA]
class FileEntry:
class ZipFileEntry:
"""File-like object used to access entries in a ZipFile""" """File-like object used to access entries in a ZipFile"""
def __init__(self, fp, length): def __init__(self, fp, length):
@@ -53,6 +51,13 @@ class ZipFileEntry:
self.returnedBytes = 0 self.returnedBytes = 0
self.length = length self.length = length
self.finished = 0 self.finished = 0
class LzmaFileEntry(FileEntry):
"""File-like object used to read a LZMA entry in a ZipFile"""
def __init__(self, fp, length):
FileEntry.__init__(self, fp, length)
self.decomp = pylzma.decompressobj()
self.buffer = "" self.buffer = ""
def tell(self): def tell(self):
@@ -63,8 +68,8 @@ class ZipFileEntry:
return "" return ""
if n is None: if n is None:
result = [self.buffer,] result = [self.buffer,]
compr_data = self.fp.read(self.length - self.readBytes) result.append(self.decomp.decompress(self.fp.read(self.length - self.readBytes)))
result.append(self.decompress(compr_data)) result.append(self.decomp.flush())
self.buffer = "" self.buffer = ""
self.finished = 1 self.finished = 1
result = "".join(result) result = "".join(result)
@@ -72,16 +77,16 @@ class ZipFileEntry:
return result return result
else: else:
while len(self.buffer) < n: while len(self.buffer) < n:
compr_data = self.fp.read(min(n, 8192, self.length - self.readBytes)) data = self.fp.read(min(n, 1024, self.length - self.readBytes))
self.readBytes += len(compr_data) self.readBytes += len(data)
if not data: if not data:
result = self.buffer # + self.flush_decompressor() result = self.buffer + self.decomp.decompress() + self.decomp.flush()
self.finished = 1 self.finished = 1
self.buffer = "" self.buffer = ""
self.returnedBytes += len(result) self.returnedBytes += len(result)
return result return result
else: else:
self.buffer += self.decompress(data) self.buffer += self.decomp.decompress(data)
result = self.buffer[:n] result = self.buffer[:n]
self.buffer = self.buffer[n:] self.buffer = self.buffer[n:]
self.returnedBytes += len(result) self.returnedBytes += len(result)
@@ -91,45 +96,11 @@ class ZipFileEntry:
self.finished = 1 self.finished = 1
del self.fp del self.fp
class ZipFileEntry(FileEntry):
class DeflatedZipFileEntry(ZipFileEntry):
"""File-like object used to read a deflated entry in a ZipFile"""
def __init__(self, fp, length):
ZipFileEntry.__init__(self, fp, length)
self.decomp = zlib.decompressobj(-15)
def decompress(self, compr_data):
return self.decomp.decompress(compr_data) + self.decomp.decompress("Z") + self.decomp.flush()
class Bzip2ZipFileEntry(ZipFileEntry):
"""File-like object used to read a deflated entry in a ZipFile"""
def __init__(self, fp, length):
ZipFileEntry.__init__(self, fp, length)
self.decomp = bz2.Decompressor()
def decompress(self, compr_data):
return self.decomp.decompress(compr_data)
class LzmaZipFileEntry(ZipFileEntry):
"""File-like object used to read a LZMA entry in a ZipFile"""
def __init__(self, fp, length):
ZipFileEntry.__init__(self, fp, length)
self.decompressor = pylzma.decompressobj()
def decompress(self, compr_data):
return self.decomp.decompress(compr_data) + self.decomp(flush)
class StoredZipFileEntry(ZipFileEntry):
"""File-like object used to read an uncompressed entry in a ZipFile""" """File-like object used to read an uncompressed entry in a ZipFile"""
def __init__(self, fp, length): def __init__(self, fp, length):
ZipFileEntry.__init__(self, fp, length) FileEntry.__init__(self, fp, length)
def tell(self): def tell(self):
return self.readBytes return self.readBytes
@@ -151,6 +122,51 @@ class StoredZipFileEntry(ZipFileEntry):
del self.fp del self.fp
class DeflatedZipFileEntry(FileEntry):
"""File-like object used to read a deflated entry in a ZipFile"""
def __init__(self, fp, length):
FileEntry.__init__(self, fp, length)
self.decomp = zlib.decompressobj(-15)
self.buffer = ""
def tell(self):
return self.returnedBytes
def read(self, n=None):
if self.finished:
return ""
if n is None:
result = [self.buffer,]
result.append(self.decomp.decompress(self.fp.read(self.length - self.readBytes)))
result.append(self.decomp.decompress("Z"))
result.append(self.decomp.flush())
self.buffer = ""
self.finished = 1
result = "".join(result)
self.returnedBytes += len(result)
return result
else:
while len(self.buffer) < n:
data = self.fp.read(min(n, 1024, self.length - self.readBytes))
self.readBytes += len(data)
if not data:
result = self.buffer + self.decomp.decompress("Z") + self.decomp.flush()
self.finished = 1
self.buffer = ""
self.returnedBytes += len(result)
return result
else:
self.buffer += self.decomp.decompress(data)
result = self.buffer[:n]
self.buffer = self.buffer[n:]
self.returnedBytes += len(result)
return result
def close(self):
self.finished = 1
del self.fp
class ZipFileExt(ZipFile): class ZipFileExt(ZipFile):
def _writecheck(self, zinfo): def _writecheck(self, zinfo):
@@ -169,9 +185,9 @@ class ZipFileExt(ZipFile):
if zinfo.compress_type == ZIP_DEFLATED and not zlib: if zinfo.compress_type == ZIP_DEFLATED and not zlib:
raise RuntimeError, \ raise RuntimeError, \
"Compression requires the (missing) zlib module" "Compression requires the (missing) zlib module"
if zinfo.compress_type == ZIP_BZIP2 and not bz2: if zinfo.compress_type == ZIP_BZIP2 and not bzip2:
raise RuntimeError, \ raise RuntimeError, \
"Compression requires the (missing) bz2 module" "Compression requires the (missing) bzip2 module"
if zinfo.compress_type == ZIP_LZMA and not pylzma: if zinfo.compress_type == ZIP_LZMA and not pylzma:
raise RuntimeError, \ raise RuntimeError, \
"Compression requires the (missing) pylzma module" "Compression requires the (missing) pylzma module"
@@ -261,22 +277,22 @@ class ZipFileExt(ZipFile):
zinfo = self.getinfo(name) zinfo = self.getinfo(name)
self.fp.seek(zinfo.file_offset, 0) self.fp.seek(zinfo.file_offset, 0)
if zinfo.compress_type == ZIP_STORED: if zinfo.compress_type == ZIP_STORED:
return StoredZipFileEntry(self.fp, zinfo.compress_size) return ZipFileEntry(self.fp, zinfo.compress_size)
elif zinfo.compress_type == ZIP_DEFLATED: elif zinfo.compress_type == ZIP_DEFLATED:
if not zlib: if not zlib:
raise RuntimeError, \ raise RuntimeError, \
"De-compression requires the (missing) zlib module" "De-compression requires the (missing) zlib module"
return DeflatedZipFileEntry(self.fp, zinfo.compress_size) return DeflatedZipFileEntry(self.fp, zinfo.compress_size)
elif zinfo.compress_type == ZIP_BZIP2: ## elif zinfo.compress_type == ZIP_BZIP2:
if not bzip2: ## if not bzip2:
raise RuntimeError, \ ## raise RuntimeError, \
"De-compression requires the (missing) bzip2 module" ## "De-compression requires the (missing) bzip2 module"
return Bzip2ZipFileEntry(self.fp, zinfo.compress_size) ## return LZMAFileEntry(self.fp, zinfo.compress_size)
elif zinfo.compress_type == ZIP_LZMA: elif zinfo.compress_type == ZIP_LZMA:
if not pylzma: if not pylzma:
raise RuntimeError, \ raise RuntimeError, \
"De-compression requires the (missing) pylzma module" "De-compression requires the (missing) pylzma module"
return LzmaZipFileEntry(self.fp, zinfo.compress_size) return LzmaFileEntry(self.fp, zinfo.compress_size)
else: else:
raise BadZipfile, \ raise BadZipfile, \
"Unsupported compression method %d for file %s" % \ "Unsupported compression method %d for file %s" % \