Patch #448474: Add support for tell() and seek() to gzip.GzipFile.
diff --git a/Doc/lib/libgzip.tex b/Doc/lib/libgzip.tex
index 34ec897..aab70a1 100644
--- a/Doc/lib/libgzip.tex
+++ b/Doc/lib/libgzip.tex
@@ -21,8 +21,8 @@
 \begin{classdesc}{GzipFile}{\optional{filename\optional{, mode\optional{,
                             compresslevel\optional{, fileobj}}}}}
 Constructor for the \class{GzipFile} class, which simulates most of
-the methods of a file object, with the exception of the
-\method{seek()} and \method{tell()} methods.  At least one of
+the methods of a file object, with the exception of the \method{readinto()},
+\method{truncate()}, and \method{xreadlines()} methods.  At least one of
 \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
diff --git a/Lib/gzip.py b/Lib/gzip.py
index 79ca205..9df8e5d 100644
--- a/Lib/gzip.py
+++ b/Lib/gzip.py
@@ -64,6 +64,7 @@
             raise ValueError, "Mode " + mode + " not supported"
 
         self.fileobj = fileobj
+        self.offset = 0
 
         if self.mode == WRITE:
             self._write_gzip_header()
@@ -138,6 +139,7 @@
             self.size = self.size + len(data)
             self.crc = zlib.crc32(data, self.crc)
             self.fileobj.write( self.compress.compress(data) )
+            self.offset += len(data)
 
     def writelines(self,lines):
         self.write(" ".join(lines))
@@ -167,11 +169,13 @@
         self.extrabuf = self.extrabuf[size:]
         self.extrasize = self.extrasize - size
 
+        self.offset += size
         return chunk
 
     def _unread(self, buf):
         self.extrabuf = buf + self.extrabuf
         self.extrasize = len(buf) + self.extrasize
+        self.offset -= len(buf)
 
     def _read(self, size=1024):
         if self.fileobj is None: raise EOFError, "Reached EOF"
@@ -185,7 +189,6 @@
             pos = self.fileobj.tell()   # Save current position
             self.fileobj.seek(0, 2)     # Seek to end of file
             if pos == self.fileobj.tell():
-                self.fileobj = None
                 raise EOFError, "Reached EOF"
             else:
                 self.fileobj.seek( pos ) # Return to original position
@@ -204,7 +207,6 @@
         if buf == "":
             uncompress = self.decompress.flush()
             self._read_eof()
-            self.fileobj = None
             self._add_read_data( uncompress )
             raise EOFError, 'Reached EOF'
 
@@ -270,6 +272,36 @@
     def isatty(self):
         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):
         if size < 0: size = sys.maxint
         bufs = []
diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py
index 8ff8c33..6d69c3f 100644
--- a/Lib/test/test_gzip.py
+++ b/Lib/test/test_gzip.py
@@ -50,5 +50,29 @@
     if L == []: break
 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)