Index: python/dist/src/Doc/lib/libzipfile.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libzipfile.tex,v retrieving revision 1.16 diff -c -r1.16 libzipfile.tex *** python/dist/src/Doc/lib/libzipfile.tex 25 Aug 2003 04:28:05 -0000 1.16 --- python/dist/src/Doc/lib/libzipfile.tex 27 Sep 2003 08:03:30 -0000 *************** *** 77,83 **** \subsection{ZipFile Objects \label{zipfile-objects}} ! \begin{classdesc}{ZipFile}{file\optional{, mode\optional{, compression}}} Open a ZIP file, where \var{file} can be either a path to a file (a string) or a file-like object. The \var{mode} parameter should be \code{'r'} to read an existing file, \code{'w'} to --- 77,83 ---- \subsection{ZipFile Objects \label{zipfile-objects}} ! \begin{classdesc}{ZipFile}{file\optional{, mode\optional{, compression\optional{, differed}}}} Open a ZIP file, where \var{file} can be either a path to a file (a string) or a file-like object. The \var{mode} parameter should be \code{'r'} to read an existing file, \code{'w'} to *************** *** 100,105 **** --- 100,109 ---- is specified but the \refmodule{zlib} module is not available, \exception{RuntimeError} is also raised. The default is \constant{ZIP_STORED}. + \var{differed} is a bool indicating if the loading of the headers must + be carried out in a on-demand way. For a ZIP file containing many files + ($>10000$) it is necessary to activate differed loading. The default is + \constant{False}. \end{classdesc} \begin{methoddesc}{close}{} Index: python/dist/src/Lib/zipfile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/zipfile.py,v retrieving revision 1.31 diff -c -r1.31 zipfile.py *** python/dist/src/Lib/zipfile.py 27 Jun 2003 22:25:03 -0000 1.31 --- python/dist/src/Lib/zipfile.py 27 Sep 2003 08:03:30 -0000 *************** *** 179,185 **** fp = None # Set here since __del__ checks it ! def __init__(self, file, mode="r", compression=ZIP_STORED): """Open the ZIP file with mode read "r", write "w" or append "a".""" if compression == ZIP_STORED: pass --- 179,185 ---- fp = None # Set here since __del__ checks it ! def __init__(self, file, mode="r", compression=ZIP_STORED, differed=False): """Open the ZIP file with mode read "r", write "w" or append "a".""" if compression == ZIP_STORED: pass *************** *** 194,199 **** --- 194,200 ---- self.filelist = [] # List of ZipInfo instances for archive self.compression = compression # Method of compression self.mode = key = mode[0] + self.differed = differed # Bool to check for differed loading # Check if we were passed a file-like object if isinstance(file, basestring): *************** *** 284,306 **** self.NameToInfo[x.filename] = x if self.debug > 2: print "total", total ! for data in self.filelist: ! fp.seek(data.header_offset, 0) ! fheader = fp.read(30) ! if fheader[0:4] != stringFileHeader: ! raise BadZipfile, "Bad magic number for file header" ! fheader = struct.unpack(structFileHeader, fheader) ! # file_offset is computed here, since the extra field for ! # the central directory and for the local file header ! # refer to different fields, and they can have different ! # lengths ! data.file_offset = (data.header_offset + 30 ! + fheader[_FH_FILENAME_LENGTH] ! + fheader[_FH_EXTRA_FIELD_LENGTH]) ! fname = fp.read(fheader[_FH_FILENAME_LENGTH]) ! if fname != data.orig_filename: ! raise RuntimeError, \ ! 'File name in directory "%s" and header "%s" differ.' % ( data.orig_filename, fname) def namelist(self): --- 285,308 ---- self.NameToInfo[x.filename] = x if self.debug > 2: print "total", total ! if not self.differed: # If the loading is not differed, load normally ! for data in self.filelist: ! fp.seek(data.header_offset, 0) ! fheader = fp.read(30) ! if fheader[0:4] != stringFileHeader: ! raise BadZipfile, "Bad magic number for file header" ! fheader = struct.unpack(structFileHeader, fheader) ! # file_offset is computed here, since the extra field for ! # the central directory and for the local file header ! # refer to different fields, and they can have different ! # lengths ! data.file_offset = (data.header_offset + 30 ! + fheader[_FH_FILENAME_LENGTH] ! + fheader[_FH_EXTRA_FIELD_LENGTH]) ! fname = fp.read(fheader[_FH_FILENAME_LENGTH]) ! if fname != data.orig_filename: ! raise RuntimeError, \ ! 'File name in directory "%s" and header "%s" differ.' % ( data.orig_filename, fname) def namelist(self): *************** *** 343,348 **** --- 345,374 ---- "Attempt to read ZIP archive that was already closed" zinfo = self.getinfo(name) filepos = self.fp.tell() + + # check if the current file has been preloaded + # This check is useless if the loading is not differed + if self.differed and not hasattr(zinfo, 'file_offset'): + self.fp.seek(zinfo.header_offset, 0) + fheader = self.fp.read(30) + if fheader[0:4] != stringFileHeader: + # The exception here is RuntimeError and not + # BadZipFile + raise RuntimeError, "Bad magic number for file header" + fheader = struct.unpack(structFileHeader, fheader) + # file_offset is computed here, since the extra field for + # the central directory and for the local file header + # refer to different fields, and they can have different + # lengths + zinfo.file_offset = (zinfo.header_offset + 30 + + fheader[_FH_FILENAME_LENGTH] + + fheader[_FH_EXTRA_FIELD_LENGTH]) + fname = self.fp.read(fheader[_FH_FILENAME_LENGTH]) + if fname != zinfo.orig_filename: + raise RuntimeError, \ + 'File name in directory "%s" and header "%s" differ.' % ( + data.orig_filename, fname) + self.fp.seek(zinfo.file_offset, 0) bytes = self.fp.read(zinfo.compress_size) self.fp.seek(filepos, 0)