diff options
author | Georg Brandl <georg@python.org> | 2006-05-15 19:30:35 (GMT) |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2006-05-15 19:30:35 (GMT) |
commit | 49c8f4cf36926d40951fd3a151ddf45caf06cfdb (patch) | |
tree | b6d8d5a7c83dcbeaedd94d91d7343999145e7231 /Lib/tarfile.py | |
parent | 2a0ad4db3ad31909f33b4ae17b5927be4abb2330 (diff) | |
download | cpython-49c8f4cf36926d40951fd3a151ddf45caf06cfdb.zip cpython-49c8f4cf36926d40951fd3a151ddf45caf06cfdb.tar.gz cpython-49c8f4cf36926d40951fd3a151ddf45caf06cfdb.tar.bz2 |
[ 1488881 ] tarfile.py: support for file-objects and bz2 (cp. #1488634)
Diffstat (limited to 'Lib/tarfile.py')
-rw-r--r-- | Lib/tarfile.py | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 8987ca7..6c29783 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -556,6 +556,69 @@ class _StreamProxy(object): self.fileobj.close() # class StreamProxy +class _BZ2Proxy(object): + """Small proxy class that enables external file object + support for "r:bz2" and "w:bz2" modes. This is actually + a workaround for a limitation in bz2 module's BZ2File + class which (unlike gzip.GzipFile) has no support for + a file object argument. + """ + + blocksize = 16 * 1024 + + def __init__(self, fileobj, mode): + self.fileobj = fileobj + self.mode = mode + self.init() + + def init(self): + import bz2 + self.pos = 0 + if self.mode == "r": + self.bz2obj = bz2.BZ2Decompressor() + self.fileobj.seek(0) + self.buf = "" + else: + self.bz2obj = bz2.BZ2Compressor() + + def read(self, size): + b = [self.buf] + x = len(self.buf) + while x < size: + try: + raw = self.fileobj.read(self.blocksize) + data = self.bz2obj.decompress(raw) + b.append(data) + except EOFError: + break + x += len(data) + self.buf = "".join(b) + + buf = self.buf[:size] + self.buf = self.buf[size:] + self.pos += len(buf) + return buf + + def seek(self, pos): + if pos < self.pos: + self.init() + self.read(pos - self.pos) + + def tell(self): + return self.pos + + def write(self, data): + self.pos += len(data) + raw = self.bz2obj.compress(data) + self.fileobj.write(raw) + + def close(self): + if self.mode == "w": + raw = self.bz2obj.flush() + self.fileobj.write(raw) + self.fileobj.close() +# class _BZ2Proxy + #------------------------ # Extraction file object #------------------------ @@ -1057,10 +1120,12 @@ class TarFile(object): tarname = pre + ext if fileobj is not None: - raise ValueError, "no support for external file objects" + fileobj = _BZ2Proxy(fileobj, mode) + else: + fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) try: - t = cls.taropen(tarname, mode, bz2.BZ2File(name, mode, compresslevel=compresslevel)) + t = cls.taropen(tarname, mode, fileobj) except IOError: raise ReadError, "not a bzip2 file" t._extfileobj = False |