blob: 55d448dd1d7905c29f485eed62025612cf7b3afd [file] [log] [blame]
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +00001"""Functions that read and write gzipped files.
2
Guido van Rossum54f22ed2000-02-04 15:10:34 +00003The user of the file doesn't have to worry about the compression,
4but random access is not allowed."""
5
6# based on Andrew Kuchling's minigzip.py distributed with the zlib module
7
Eric S. Raymondee5e61d2001-02-09 09:10:35 +00008import struct, sys, time
Guido van Rossum15262191997-04-30 16:04:57 +00009import zlib
Guido van Rossum68de3791997-07-19 20:22:23 +000010import __builtin__
Guido van Rossum15262191997-04-30 16:04:57 +000011
Skip Montanaro2dd42762001-01-23 15:35:05 +000012__all__ = ["GzipFile","open"]
13
Guido van Rossum15262191997-04-30 16:04:57 +000014FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
15
16READ, WRITE = 1, 2
17
18def write32(output, value):
Jeremy Hyltonc19f9971999-03-23 23:05:34 +000019 output.write(struct.pack("<l", value))
Tim Peters07e99cb2001-01-14 23:47:14 +000020
Guido van Rossum95bdd0b1999-04-12 14:34:16 +000021def write32u(output, value):
Jack Jansen2d0589b2001-02-21 10:39:35 +000022 if value < 0:
23 value = value + 0x100000000L
Guido van Rossum95bdd0b1999-04-12 14:34:16 +000024 output.write(struct.pack("<L", value))
25
Guido van Rossum15262191997-04-30 16:04:57 +000026def read32(input):
Jeremy Hyltonc19f9971999-03-23 23:05:34 +000027 return struct.unpack("<l", input.read(4))[0]
Guido van Rossum15262191997-04-30 16:04:57 +000028
Fred Drakefa1591c1999-04-05 18:37:59 +000029def open(filename, mode="rb", compresslevel=9):
Raymond Hettingeraef22fb2002-05-29 16:18:42 +000030 """Shorthand for GzipFile(filename, mode, compresslevel).
31
32 The filename argument is required; mode defaults to 'rb'
33 and compresslevel defaults to 9.
34
35 """
Guido van Rossum15262191997-04-30 16:04:57 +000036 return GzipFile(filename, mode, compresslevel)
37
38class GzipFile:
Raymond Hettingeraef22fb2002-05-29 16:18:42 +000039 """The GzipFile class simulates most of the methods of a file object with
Guido van Rossum97c5fcc2002-08-06 17:03:25 +000040 the exception of the readinto() and truncate() methods.
Raymond Hettingeraef22fb2002-05-29 16:18:42 +000041
42 """
Guido van Rossum15262191997-04-30 16:04:57 +000043
Guido van Rossum68de3791997-07-19 20:22:23 +000044 myfileobj = None
45
Tim Peters07e99cb2001-01-14 23:47:14 +000046 def __init__(self, filename=None, mode=None,
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000047 compresslevel=9, fileobj=None):
Raymond Hettingeraef22fb2002-05-29 16:18:42 +000048 """Constructor for the GzipFile class.
49
50 At least one of fileobj and filename must be given a
51 non-trivial value.
52
53 The new class instance is based on fileobj, which can be a regular
54 file, a StringIO object, or any other object which simulates a file.
55 It defaults to None, in which case filename is opened to provide
56 a file object.
57
58 When fileobj is not None, the filename argument is only used to be
59 included in the gzip file header, which may includes the original
60 filename of the uncompressed file. It defaults to the filename of
61 fileobj, if discernible; otherwise, it defaults to the empty string,
62 and in this case the original filename is not included in the header.
63
64 The mode argument can be any of 'r', 'rb', 'a', 'ab', 'w', or 'wb',
65 depending on whether the file will be read or written. The default
66 is the mode of fileobj if discernible; otherwise, the default is 'rb'.
67 Be aware that only the 'rb', 'ab', and 'wb' values should be used
68 for cross-platform portability.
69
70 The compresslevel argument is an integer from 1 to 9 controlling the
71 level of compression; 1 is fastest and produces the least compression,
72 and 9 is slowest and produces the most compression. The default is 9.
73
74 """
75
Skip Montanaro12424bc2002-05-23 01:43:05 +000076 # guarantee the file is opened in binary mode on platforms
77 # that care about that sort of thing
78 if mode and 'b' not in mode:
79 mode += 'b'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000080 if fileobj is None:
Fred Drake9bb76d11999-04-05 18:33:40 +000081 fileobj = self.myfileobj = __builtin__.open(filename, mode or 'rb')
Guido van Rossum68de3791997-07-19 20:22:23 +000082 if filename is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000083 if hasattr(fileobj, 'name'): filename = fileobj.name
84 else: filename = ''
Guido van Rossum68de3791997-07-19 20:22:23 +000085 if mode is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000086 if hasattr(fileobj, 'mode'): mode = fileobj.mode
Fred Drake9bb76d11999-04-05 18:33:40 +000087 else: mode = 'rb'
Guido van Rossum68de3791997-07-19 20:22:23 +000088
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000089 if mode[0:1] == 'r':
90 self.mode = READ
Tim Peters07e99cb2001-01-14 23:47:14 +000091 # Set flag indicating start of a new member
Guido van Rossum8ca162f2002-04-07 06:36:23 +000092 self._new_member = True
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +000093 self.extrabuf = ""
94 self.extrasize = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000095 self.filename = filename
Guido van Rossum15262191997-04-30 16:04:57 +000096
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +000097 elif mode[0:1] == 'w' or mode[0:1] == 'a':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000098 self.mode = WRITE
99 self._init_write(filename)
100 self.compress = zlib.compressobj(compresslevel,
Tim Peters07e99cb2001-01-14 23:47:14 +0000101 zlib.DEFLATED,
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000102 -zlib.MAX_WBITS,
103 zlib.DEF_MEM_LEVEL,
104 0)
105 else:
Martin v. Löwisdb044892002-03-11 06:46:52 +0000106 raise IOError, "Mode " + mode + " not supported"
Guido van Rossum15262191997-04-30 16:04:57 +0000107
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000108 self.fileobj = fileobj
Martin v. Löwis8cc965c2001-08-09 07:21:56 +0000109 self.offset = 0
Guido van Rossum15262191997-04-30 16:04:57 +0000110
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000111 if self.mode == WRITE:
112 self._write_gzip_header()
Guido van Rossum15262191997-04-30 16:04:57 +0000113
114 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000115 s = repr(self.fileobj)
116 return '<gzip ' + s[1:-1] + ' ' + hex(id(self)) + '>'
Guido van Rossum15262191997-04-30 16:04:57 +0000117
118 def _init_write(self, filename):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000119 if filename[-3:] != '.gz':
120 filename = filename + '.gz'
121 self.filename = filename
122 self.crc = zlib.crc32("")
123 self.size = 0
124 self.writebuf = []
125 self.bufsize = 0
Guido van Rossum15262191997-04-30 16:04:57 +0000126
127 def _write_gzip_header(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 self.fileobj.write('\037\213') # magic header
129 self.fileobj.write('\010') # compression method
130 fname = self.filename[:-3]
131 flags = 0
132 if fname:
133 flags = FNAME
134 self.fileobj.write(chr(flags))
Guido van Rossum95bdd0b1999-04-12 14:34:16 +0000135 write32u(self.fileobj, long(time.time()))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000136 self.fileobj.write('\002')
137 self.fileobj.write('\377')
138 if fname:
139 self.fileobj.write(fname + '\000')
Guido van Rossum15262191997-04-30 16:04:57 +0000140
141 def _init_read(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000142 self.crc = zlib.crc32("")
143 self.size = 0
Guido van Rossum15262191997-04-30 16:04:57 +0000144
145 def _read_gzip_header(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000146 magic = self.fileobj.read(2)
147 if magic != '\037\213':
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000148 raise IOError, 'Not a gzipped file'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000149 method = ord( self.fileobj.read(1) )
150 if method != 8:
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000151 raise IOError, 'Unknown compression method'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000152 flag = ord( self.fileobj.read(1) )
153 # modtime = self.fileobj.read(4)
154 # extraflag = self.fileobj.read(1)
155 # os = self.fileobj.read(1)
156 self.fileobj.read(6)
Guido van Rossum15262191997-04-30 16:04:57 +0000157
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000158 if flag & FEXTRA:
159 # Read & discard the extra field, if present
Tim Peters07e99cb2001-01-14 23:47:14 +0000160 xlen=ord(self.fileobj.read(1))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000161 xlen=xlen+256*ord(self.fileobj.read(1))
162 self.fileobj.read(xlen)
163 if flag & FNAME:
164 # Read and discard a null-terminated string containing the filename
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000165 while True:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000166 s=self.fileobj.read(1)
167 if not s or s=='\000': break
168 if flag & FCOMMENT:
169 # Read and discard a null-terminated string containing a comment
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000170 while True:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000171 s=self.fileobj.read(1)
172 if not s or s=='\000': break
173 if flag & FHCRC:
174 self.fileobj.read(2) # Read & discard the 16-bit header CRC
Guido van Rossum15262191997-04-30 16:04:57 +0000175
176
177 def write(self,data):
Martin v. Löwisdb044892002-03-11 06:46:52 +0000178 if self.mode != WRITE:
179 import errno
180 raise IOError(errno.EBADF, "write() on read-only GzipFile object")
Tim Peters863ac442002-04-16 01:38:40 +0000181
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000182 if self.fileobj is None:
183 raise ValueError, "write() on closed GzipFile object"
184 if len(data) > 0:
185 self.size = self.size + len(data)
186 self.crc = zlib.crc32(data, self.crc)
187 self.fileobj.write( self.compress.compress(data) )
Martin v. Löwis8cc965c2001-08-09 07:21:56 +0000188 self.offset += len(data)
Guido van Rossum15262191997-04-30 16:04:57 +0000189
Guido van Rossum56068012000-02-02 16:51:06 +0000190 def read(self, size=-1):
Martin v. Löwisdb044892002-03-11 06:46:52 +0000191 if self.mode != READ:
192 import errno
193 raise IOError(errno.EBADF, "write() on read-only GzipFile object")
Tim Peters863ac442002-04-16 01:38:40 +0000194
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000195 if self.extrasize <= 0 and self.fileobj is None:
196 return ''
Guido van Rossumb16a3b81998-01-27 19:29:45 +0000197
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000198 readsize = 1024
Guido van Rossum56068012000-02-02 16:51:06 +0000199 if size < 0: # get the whole thing
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000200 try:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000201 while True:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000202 self._read(readsize)
203 readsize = readsize * 2
204 except EOFError:
205 size = self.extrasize
206 else: # just get some more of it
207 try:
208 while size > self.extrasize:
209 self._read(readsize)
210 readsize = readsize * 2
211 except EOFError:
Guido van Rossum84c6fc91998-08-03 15:41:39 +0000212 if size > self.extrasize:
213 size = self.extrasize
Tim Peters07e99cb2001-01-14 23:47:14 +0000214
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000215 chunk = self.extrabuf[:size]
216 self.extrabuf = self.extrabuf[size:]
217 self.extrasize = self.extrasize - size
Guido van Rossum15262191997-04-30 16:04:57 +0000218
Martin v. Löwis8cc965c2001-08-09 07:21:56 +0000219 self.offset += size
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000220 return chunk
Guido van Rossum15262191997-04-30 16:04:57 +0000221
Guido van Rossumb16a3b81998-01-27 19:29:45 +0000222 def _unread(self, buf):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000223 self.extrabuf = buf + self.extrabuf
Guido van Rossum84c6fc91998-08-03 15:41:39 +0000224 self.extrasize = len(buf) + self.extrasize
Martin v. Löwis8cc965c2001-08-09 07:21:56 +0000225 self.offset -= len(buf)
Guido van Rossumb16a3b81998-01-27 19:29:45 +0000226
227 def _read(self, size=1024):
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000228 if self.fileobj is None: raise EOFError, "Reached EOF"
Tim Peters07e99cb2001-01-14 23:47:14 +0000229
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000230 if self._new_member:
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000231 # If the _new_member flag is set, we have to
232 # jump to the next member, if there is one.
Tim Peters07e99cb2001-01-14 23:47:14 +0000233 #
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000234 # First, check if we're at the end of the file;
235 # if so, it's time to stop; no more members to read.
236 pos = self.fileobj.tell() # Save current position
237 self.fileobj.seek(0, 2) # Seek to end of file
238 if pos == self.fileobj.tell():
Andrew M. Kuchling2d813e51999-09-06 16:34:51 +0000239 raise EOFError, "Reached EOF"
Tim Peters07e99cb2001-01-14 23:47:14 +0000240 else:
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000241 self.fileobj.seek( pos ) # Return to original position
Tim Peters07e99cb2001-01-14 23:47:14 +0000242
243 self._init_read()
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000244 self._read_gzip_header()
245 self.decompress = zlib.decompressobj(-zlib.MAX_WBITS)
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000246 self._new_member = False
Tim Peters07e99cb2001-01-14 23:47:14 +0000247
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000248 # Read a chunk of data from the file
249 buf = self.fileobj.read(size)
Tim Peters07e99cb2001-01-14 23:47:14 +0000250
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000251 # If the EOF has been reached, flush the decompression object
252 # and mark this object as finished.
Tim Peters07e99cb2001-01-14 23:47:14 +0000253
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000254 if buf == "":
255 uncompress = self.decompress.flush()
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000256 self._read_eof()
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000257 self._add_read_data( uncompress )
258 raise EOFError, 'Reached EOF'
Tim Peters07e99cb2001-01-14 23:47:14 +0000259
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000260 uncompress = self.decompress.decompress(buf)
261 self._add_read_data( uncompress )
262
263 if self.decompress.unused_data != "":
264 # Ending case: we've come to the end of a member in the file,
265 # so seek back to the start of the unused data, finish up
266 # this member, and read a new gzip header.
267 # (The number of bytes to seek back is the length of the unused
268 # data, minus 8 because _read_eof() will rewind a further 8 bytes)
269 self.fileobj.seek( -len(self.decompress.unused_data)+8, 1)
270
271 # Check the CRC and file size, and set the flag so we read
Tim Peters07e99cb2001-01-14 23:47:14 +0000272 # a new member on the next call
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000273 self._read_eof()
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000274 self._new_member = True
Tim Peters07e99cb2001-01-14 23:47:14 +0000275
276 def _add_read_data(self, data):
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000277 self.crc = zlib.crc32(data, self.crc)
278 self.extrabuf = self.extrabuf + data
279 self.extrasize = self.extrasize + len(data)
280 self.size = self.size + len(data)
Guido van Rossum15262191997-04-30 16:04:57 +0000281
282 def _read_eof(self):
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000283 # We've read to the end of the file, so we have to rewind in order
Tim Peters07e99cb2001-01-14 23:47:14 +0000284 # to reread the 8 bytes containing the CRC and the file size.
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000285 # We check the that the computed CRC and size of the
286 # uncompressed data matches the stored values.
287 self.fileobj.seek(-8, 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000288 crc32 = read32(self.fileobj)
289 isize = read32(self.fileobj)
Guido van Rossum95bdd0b1999-04-12 14:34:16 +0000290 if crc32%0x100000000L != self.crc%0x100000000L:
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000291 raise ValueError, "CRC check failed"
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000292 elif isize != self.size:
Andrew M. Kuchlingf4f119c1999-03-25 21:49:14 +0000293 raise ValueError, "Incorrect length of data produced"
Tim Peters07e99cb2001-01-14 23:47:14 +0000294
Guido van Rossum15262191997-04-30 16:04:57 +0000295 def close(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000296 if self.mode == WRITE:
297 self.fileobj.write(self.compress.flush())
298 write32(self.fileobj, self.crc)
299 write32(self.fileobj, self.size)
300 self.fileobj = None
301 elif self.mode == READ:
302 self.fileobj = None
303 if self.myfileobj:
304 self.myfileobj.close()
305 self.myfileobj = None
Guido van Rossum15262191997-04-30 16:04:57 +0000306
Andrew M. Kuchling916fcc31999-08-10 13:19:30 +0000307 def __del__(self):
Jeremy Hyltone298c302000-05-08 16:59:59 +0000308 try:
309 if (self.myfileobj is None and
310 self.fileobj is None):
311 return
312 except AttributeError:
313 return
314 self.close()
Tim Peters07e99cb2001-01-14 23:47:14 +0000315
Guido van Rossum15262191997-04-30 16:04:57 +0000316 def flush(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000317 self.fileobj.flush()
Guido van Rossum15262191997-04-30 16:04:57 +0000318
Guido van Rossum15262191997-04-30 16:04:57 +0000319 def isatty(self):
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000320 return False
Guido van Rossum15262191997-04-30 16:04:57 +0000321
Martin v. Löwis8cc965c2001-08-09 07:21:56 +0000322 def tell(self):
323 return self.offset
324
325 def rewind(self):
326 '''Return the uncompressed stream file position indicator to the
Tim Petersab9ba272001-08-09 21:40:30 +0000327 beginning of the file'''
Martin v. Löwis8cc965c2001-08-09 07:21:56 +0000328 if self.mode != READ:
329 raise IOError("Can't rewind in write mode")
330 self.fileobj.seek(0)
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000331 self._new_member = True
Martin v. Löwis8cc965c2001-08-09 07:21:56 +0000332 self.extrabuf = ""
333 self.extrasize = 0
334 self.offset = 0
335
336 def seek(self, offset):
337 if self.mode == WRITE:
338 if offset < self.offset:
339 raise IOError('Negative seek in write mode')
340 count = offset - self.offset
Tim Petersab9ba272001-08-09 21:40:30 +0000341 for i in range(count/1024):
Fred Drake95b0eb72001-10-13 18:33:51 +0000342 self.write(1024*'\0')
Martin v. Löwis8cc965c2001-08-09 07:21:56 +0000343 self.write((count%1024)*'\0')
344 elif self.mode == READ:
345 if offset < self.offset:
346 # for negative seek, rewind and do positive seek
347 self.rewind()
348 count = offset - self.offset
349 for i in range(count/1024): self.read(1024)
350 self.read(count % 1024)
351
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000352 def readline(self, size=-1):
353 if size < 0: size = sys.maxint
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000354 bufs = []
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000355 readsize = min(100, size) # Read from the file in small chunks
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000356 while True:
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000357 if size == 0:
Eric S. Raymondee5e61d2001-02-09 09:10:35 +0000358 return "".join(bufs) # Return resulting line
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000359
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000360 c = self.read(readsize)
Eric S. Raymondee5e61d2001-02-09 09:10:35 +0000361 i = c.find('\n')
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000362 if size is not None:
363 # We set i=size to break out of the loop under two
Tim Peters07e99cb2001-01-14 23:47:14 +0000364 # conditions: 1) there's no newline, and the chunk is
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000365 # larger than size, or 2) there is a newline, but the
366 # resulting line would be longer than 'size'.
367 if i==-1 and len(c) > size: i=size-1
368 elif size <= i: i = size -1
Guido van Rossum15262191997-04-30 16:04:57 +0000369
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000370 if i >= 0 or c == '':
371 bufs.append(c[:i+1]) # Add portion of last chunk
372 self._unread(c[i+1:]) # Push back rest of chunk
Eric S. Raymondee5e61d2001-02-09 09:10:35 +0000373 return ''.join(bufs) # Return resulting line
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000374
375 # Append chunk to list, decrease 'size',
376 bufs.append(c)
377 size = size - len(c)
378 readsize = min(size, readsize * 2)
Tim Peters07e99cb2001-01-14 23:47:14 +0000379
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000380 def readlines(self, sizehint=0):
381 # Negative numbers result in reading all the lines
382 if sizehint <= 0: sizehint = sys.maxint
383 L = []
384 while sizehint > 0:
385 line = self.readline()
386 if line == "": break
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000387 L.append(line)
Andrew M. Kuchling41616ee2000-07-29 20:15:26 +0000388 sizehint = sizehint - len(line)
389
390 return L
Guido van Rossum15262191997-04-30 16:04:57 +0000391
Guido van Rossum68de3791997-07-19 20:22:23 +0000392 def writelines(self, L):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000393 for line in L:
394 self.write(line)
Guido van Rossum51ca6e31997-12-30 20:09:08 +0000395
Neil Schemenauercacbdf62002-03-20 18:36:00 +0000396 def __iter__(self):
397 return self
398
399 def next(self):
400 line = self.readline()
401 if line:
402 return line
403 else:
404 raise StopIteration
405
Guido van Rossum51ca6e31997-12-30 20:09:08 +0000406
407def _test():
408 # Act like gzip; with -d, act like gunzip.
409 # The input file is not deleted, however, nor are any other gzip
410 # options or features supported.
Guido van Rossum51ca6e31997-12-30 20:09:08 +0000411 args = sys.argv[1:]
412 decompress = args and args[0] == "-d"
413 if decompress:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000414 args = args[1:]
Guido van Rossum51ca6e31997-12-30 20:09:08 +0000415 if not args:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000416 args = ["-"]
Guido van Rossum51ca6e31997-12-30 20:09:08 +0000417 for arg in args:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000418 if decompress:
419 if arg == "-":
420 f = GzipFile(filename="", mode="rb", fileobj=sys.stdin)
421 g = sys.stdout
422 else:
423 if arg[-3:] != ".gz":
424 print "filename doesn't end in .gz:", `arg`
425 continue
426 f = open(arg, "rb")
427 g = __builtin__.open(arg[:-3], "wb")
428 else:
429 if arg == "-":
430 f = sys.stdin
431 g = GzipFile(filename="", mode="wb", fileobj=sys.stdout)
432 else:
433 f = __builtin__.open(arg, "rb")
434 g = open(arg + ".gz", "wb")
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000435 while True:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000436 chunk = f.read(1024)
437 if not chunk:
438 break
439 g.write(chunk)
440 if g is not sys.stdout:
441 g.close()
442 if f is not sys.stdin:
443 f.close()
Guido van Rossum51ca6e31997-12-30 20:09:08 +0000444
445if __name__ == '__main__':
446 _test()