Patch #448474: Add support for tell() and seek() to gzip.GzipFile.

This commit is contained in:
Martin v. Löwis 2001-08-09 07:21:56 +00:00
parent f30f1fc900
commit 8cc965c1fb
3 changed files with 60 additions and 4 deletions

View File

@ -21,8 +21,8 @@ The module defines the following items:
\begin{classdesc}{GzipFile}{\optional{filename\optional{, mode\optional{, \begin{classdesc}{GzipFile}{\optional{filename\optional{, mode\optional{,
compresslevel\optional{, fileobj}}}}} compresslevel\optional{, fileobj}}}}}
Constructor for the \class{GzipFile} class, which simulates most of Constructor for the \class{GzipFile} class, which simulates most of
the methods of a file object, with the exception of the the methods of a file object, with the exception of the \method{readinto()},
\method{seek()} and \method{tell()} methods. At least one of \method{truncate()}, and \method{xreadlines()} methods. At least one of
\var{fileobj} and \var{filename} must be given a non-trivial value. \var{fileobj} and \var{filename} must be given a non-trivial value.
The new class instance is based on \var{fileobj}, which can be a The new class instance is based on \var{fileobj}, which can be a

View File

@ -64,6 +64,7 @@ class GzipFile:
raise ValueError, "Mode " + mode + " not supported" raise ValueError, "Mode " + mode + " not supported"
self.fileobj = fileobj self.fileobj = fileobj
self.offset = 0
if self.mode == WRITE: if self.mode == WRITE:
self._write_gzip_header() self._write_gzip_header()
@ -138,6 +139,7 @@ class GzipFile:
self.size = self.size + len(data) self.size = self.size + len(data)
self.crc = zlib.crc32(data, self.crc) self.crc = zlib.crc32(data, self.crc)
self.fileobj.write( self.compress.compress(data) ) self.fileobj.write( self.compress.compress(data) )
self.offset += len(data)
def writelines(self,lines): def writelines(self,lines):
self.write(" ".join(lines)) self.write(" ".join(lines))
@ -167,11 +169,13 @@ class GzipFile:
self.extrabuf = self.extrabuf[size:] self.extrabuf = self.extrabuf[size:]
self.extrasize = self.extrasize - size self.extrasize = self.extrasize - size
self.offset += size
return chunk return chunk
def _unread(self, buf): def _unread(self, buf):
self.extrabuf = buf + self.extrabuf self.extrabuf = buf + self.extrabuf
self.extrasize = len(buf) + self.extrasize self.extrasize = len(buf) + self.extrasize
self.offset -= len(buf)
def _read(self, size=1024): def _read(self, size=1024):
if self.fileobj is None: raise EOFError, "Reached EOF" if self.fileobj is None: raise EOFError, "Reached EOF"
@ -185,7 +189,6 @@ class GzipFile:
pos = self.fileobj.tell() # Save current position pos = self.fileobj.tell() # Save current position
self.fileobj.seek(0, 2) # Seek to end of file self.fileobj.seek(0, 2) # Seek to end of file
if pos == self.fileobj.tell(): if pos == self.fileobj.tell():
self.fileobj = None
raise EOFError, "Reached EOF" raise EOFError, "Reached EOF"
else: else:
self.fileobj.seek( pos ) # Return to original position self.fileobj.seek( pos ) # Return to original position
@ -204,7 +207,6 @@ class GzipFile:
if buf == "": if buf == "":
uncompress = self.decompress.flush() uncompress = self.decompress.flush()
self._read_eof() self._read_eof()
self.fileobj = None
self._add_read_data( uncompress ) self._add_read_data( uncompress )
raise EOFError, 'Reached EOF' raise EOFError, 'Reached EOF'
@ -270,6 +272,36 @@ class GzipFile:
def isatty(self): def isatty(self):
return 0 return 0
def tell(self):
return self.offset
def rewind(self):
'''Return the uncompressed stream file position indicator to the
beginning of the file'''
if self.mode != READ:
raise IOError("Can't rewind in write mode")
self.fileobj.seek(0)
self._new_member = 1
self.extrabuf = ""
self.extrasize = 0
self.offset = 0
def seek(self, offset):
if self.mode == WRITE:
if offset < self.offset:
raise IOError('Negative seek in write mode')
count = offset - self.offset
for i in range(count/1024):
f.write(1024*'\0')
self.write((count%1024)*'\0')
elif self.mode == READ:
if offset < self.offset:
# for negative seek, rewind and do positive seek
self.rewind()
count = offset - self.offset
for i in range(count/1024): self.read(1024)
self.read(count % 1024)
def readline(self, size=-1): def readline(self, size=-1):
if size < 0: size = sys.maxint if size < 0: size = sys.maxint
bufs = [] bufs = []

View File

@ -50,5 +50,29 @@ while 1:
if L == []: break if L == []: break
f.close() f.close()
# Try seek, read test
f = gzip.GzipFile(filename)
while 1:
oldpos = f.tell()
line1 = f.readline()
if not line1: break
newpos = f.tell()
f.seek(oldpos) # negative seek
if len(line1)>10:
amount = 10
else:
amount = len(line1)
line2 = f.read(amount)
verify(line1[:amount] == line2)
f.seek(newpos) # positive seek
f.close()
# Try seek, write test
f = gzip.GzipFile(filename, 'w')
for pos in range(0, 256, 16):
f.seek(pos)
f.write('GZ\n')
f.close()
os.unlink(filename) os.unlink(filename)