Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8cc965c

Browse files
committed
Patch #448474: Add support for tell() and seek() to gzip.GzipFile.
1 parent f30f1fc commit 8cc965c

3 files changed

Lines changed: 60 additions & 4 deletions

File tree

Doc/lib/libgzip.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ \section{\module{gzip} ---
2121
\begin{classdesc}{GzipFile}{\optional{filename\optional{, mode\optional{,
2222
compresslevel\optional{, fileobj}}}}}
2323
Constructor for the \class{GzipFile} class, which simulates most of
24-
the methods of a file object, with the exception of the
25-
\method{seek()} and \method{tell()} methods. At least one of
24+
the methods of a file object, with the exception of the \method{readinto()},
25+
\method{truncate()}, and \method{xreadlines()} methods. At least one of
2626
\var{fileobj} and \var{filename} must be given a non-trivial value.
2727

2828
The new class instance is based on \var{fileobj}, which can be a

Lib/gzip.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def __init__(self, filename=None, mode=None,
6464
raise ValueError, "Mode " + mode + " not supported"
6565

6666
self.fileobj = fileobj
67+
self.offset = 0
6768

6869
if self.mode == WRITE:
6970
self._write_gzip_header()
@@ -138,6 +139,7 @@ def write(self,data):
138139
self.size = self.size + len(data)
139140
self.crc = zlib.crc32(data, self.crc)
140141
self.fileobj.write( self.compress.compress(data) )
142+
self.offset += len(data)
141143

142144
def writelines(self,lines):
143145
self.write(" ".join(lines))
@@ -167,11 +169,13 @@ def read(self, size=-1):
167169
self.extrabuf = self.extrabuf[size:]
168170
self.extrasize = self.extrasize - size
169171

172+
self.offset += size
170173
return chunk
171174

172175
def _unread(self, buf):
173176
self.extrabuf = buf + self.extrabuf
174177
self.extrasize = len(buf) + self.extrasize
178+
self.offset -= len(buf)
175179

176180
def _read(self, size=1024):
177181
if self.fileobj is None: raise EOFError, "Reached EOF"
@@ -185,7 +189,6 @@ def _read(self, size=1024):
185189
pos = self.fileobj.tell() # Save current position
186190
self.fileobj.seek(0, 2) # Seek to end of file
187191
if pos == self.fileobj.tell():
188-
self.fileobj = None
189192
raise EOFError, "Reached EOF"
190193
else:
191194
self.fileobj.seek( pos ) # Return to original position
@@ -204,7 +207,6 @@ def _read(self, size=1024):
204207
if buf == "":
205208
uncompress = self.decompress.flush()
206209
self._read_eof()
207-
self.fileobj = None
208210
self._add_read_data( uncompress )
209211
raise EOFError, 'Reached EOF'
210212

@@ -270,6 +272,36 @@ def flush(self):
270272
def isatty(self):
271273
return 0
272274

275+
def tell(self):
276+
return self.offset
277+
278+
def rewind(self):
279+
'''Return the uncompressed stream file position indicator to the
280+
beginning of the file'''
281+
if self.mode != READ:
282+
raise IOError("Can't rewind in write mode")
283+
self.fileobj.seek(0)
284+
self._new_member = 1
285+
self.extrabuf = ""
286+
self.extrasize = 0
287+
self.offset = 0
288+
289+
def seek(self, offset):
290+
if self.mode == WRITE:
291+
if offset < self.offset:
292+
raise IOError('Negative seek in write mode')
293+
count = offset - self.offset
294+
for i in range(count/1024):
295+
f.write(1024*'\0')
296+
self.write((count%1024)*'\0')
297+
elif self.mode == READ:
298+
if offset < self.offset:
299+
# for negative seek, rewind and do positive seek
300+
self.rewind()
301+
count = offset - self.offset
302+
for i in range(count/1024): self.read(1024)
303+
self.read(count % 1024)
304+
273305
def readline(self, size=-1):
274306
if size < 0: size = sys.maxint
275307
bufs = []

Lib/test/test_gzip.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,29 @@
5050
if L == []: break
5151
f.close()
5252

53+
# Try seek, read test
54+
55+
f = gzip.GzipFile(filename)
56+
while 1:
57+
oldpos = f.tell()
58+
line1 = f.readline()
59+
if not line1: break
60+
newpos = f.tell()
61+
f.seek(oldpos) # negative seek
62+
if len(line1)>10:
63+
amount = 10
64+
else:
65+
amount = len(line1)
66+
line2 = f.read(amount)
67+
verify(line1[:amount] == line2)
68+
f.seek(newpos) # positive seek
69+
f.close()
70+
71+
# Try seek, write test
72+
f = gzip.GzipFile(filename, 'w')
73+
for pos in range(0, 256, 16):
74+
f.seek(pos)
75+
f.write('GZ\n')
76+
f.close()
5377

5478
os.unlink(filename)

0 commit comments

Comments
 (0)