PageRenderTime 53ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/lib-python/2/zipfile.py

https://bitbucket.org/kcr/pypy
Python | 1459 lines | 1395 code | 27 blank | 37 comment | 21 complexity | 2193106659a10685913371c8b5147c87 MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. """
  2. Read and write ZIP files.
  3. """
  4. import struct, os, time, sys, shutil
  5. import binascii, cStringIO, stat
  6. import io
  7. import re
  8. try:
  9. import zlib # We may need its compression method
  10. crc32 = zlib.crc32
  11. except ImportError:
  12. zlib = None
  13. crc32 = binascii.crc32
  14. __all__ = ["BadZipfile", "error", "ZIP_STORED", "ZIP_DEFLATED", "is_zipfile",
  15. "ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile" ]
  16. class BadZipfile(Exception):
  17. pass
  18. class LargeZipFile(Exception):
  19. """
  20. Raised when writing a zipfile, the zipfile requires ZIP64 extensions
  21. and those extensions are disabled.
  22. """
  23. error = BadZipfile # The exception raised by this module
  24. ZIP64_LIMIT = (1 << 31) - 1
  25. ZIP_FILECOUNT_LIMIT = 1 << 16
  26. ZIP_MAX_COMMENT = (1 << 16) - 1
  27. # constants for Zip file compression methods
  28. ZIP_STORED = 0
  29. ZIP_DEFLATED = 8
  30. # Other ZIP compression methods not supported
  31. # Below are some formats and associated data for reading/writing headers using
  32. # the struct module. The names and structures of headers/records are those used
  33. # in the PKWARE description of the ZIP file format:
  34. # http://www.pkware.com/documents/casestudies/APPNOTE.TXT
  35. # (URL valid as of January 2008)
  36. # The "end of central directory" structure, magic number, size, and indices
  37. # (section V.I in the format document)
  38. structEndArchive = "<4s4H2LH"
  39. stringEndArchive = "PK\005\006"
  40. sizeEndCentDir = struct.calcsize(structEndArchive)
  41. _ECD_SIGNATURE = 0
  42. _ECD_DISK_NUMBER = 1
  43. _ECD_DISK_START = 2
  44. _ECD_ENTRIES_THIS_DISK = 3
  45. _ECD_ENTRIES_TOTAL = 4
  46. _ECD_SIZE = 5
  47. _ECD_OFFSET = 6
  48. _ECD_COMMENT_SIZE = 7
  49. # These last two indices are not part of the structure as defined in the
  50. # spec, but they are used internally by this module as a convenience
  51. _ECD_COMMENT = 8
  52. _ECD_LOCATION = 9
  53. # The "central directory" structure, magic number, size, and indices
  54. # of entries in the structure (section V.F in the format document)
  55. structCentralDir = "<4s4B4HL2L5H2L"
  56. stringCentralDir = "PK\001\002"
  57. sizeCentralDir = struct.calcsize(structCentralDir)
  58. # indexes of entries in the central directory structure
  59. _CD_SIGNATURE = 0
  60. _CD_CREATE_VERSION = 1
  61. _CD_CREATE_SYSTEM = 2
  62. _CD_EXTRACT_VERSION = 3
  63. _CD_EXTRACT_SYSTEM = 4
  64. _CD_FLAG_BITS = 5
  65. _CD_COMPRESS_TYPE = 6
  66. _CD_TIME = 7
  67. _CD_DATE = 8
  68. _CD_CRC = 9
  69. _CD_COMPRESSED_SIZE = 10
  70. _CD_UNCOMPRESSED_SIZE = 11
  71. _CD_FILENAME_LENGTH = 12
  72. _CD_EXTRA_FIELD_LENGTH = 13
  73. _CD_COMMENT_LENGTH = 14
  74. _CD_DISK_NUMBER_START = 15
  75. _CD_INTERNAL_FILE_ATTRIBUTES = 16
  76. _CD_EXTERNAL_FILE_ATTRIBUTES = 17
  77. _CD_LOCAL_HEADER_OFFSET = 18
  78. # The "local file header" structure, magic number, size, and indices
  79. # (section V.A in the format document)
  80. structFileHeader = "<4s2B4HL2L2H"
  81. stringFileHeader = "PK\003\004"
  82. sizeFileHeader = struct.calcsize(structFileHeader)
  83. _FH_SIGNATURE = 0
  84. _FH_EXTRACT_VERSION = 1
  85. _FH_EXTRACT_SYSTEM = 2
  86. _FH_GENERAL_PURPOSE_FLAG_BITS = 3
  87. _FH_COMPRESSION_METHOD = 4
  88. _FH_LAST_MOD_TIME = 5
  89. _FH_LAST_MOD_DATE = 6
  90. _FH_CRC = 7
  91. _FH_COMPRESSED_SIZE = 8
  92. _FH_UNCOMPRESSED_SIZE = 9
  93. _FH_FILENAME_LENGTH = 10
  94. _FH_EXTRA_FIELD_LENGTH = 11
  95. # The "Zip64 end of central directory locator" structure, magic number, and size
  96. structEndArchive64Locator = "<4sLQL"
  97. stringEndArchive64Locator = "PK\x06\x07"
  98. sizeEndCentDir64Locator = struct.calcsize(structEndArchive64Locator)
  99. # The "Zip64 end of central directory" record, magic number, size, and indices
  100. # (section V.G in the format document)
  101. structEndArchive64 = "<4sQ2H2L4Q"
  102. stringEndArchive64 = "PK\x06\x06"
  103. sizeEndCentDir64 = struct.calcsize(structEndArchive64)
  104. _CD64_SIGNATURE = 0
  105. _CD64_DIRECTORY_RECSIZE = 1
  106. _CD64_CREATE_VERSION = 2
  107. _CD64_EXTRACT_VERSION = 3
  108. _CD64_DISK_NUMBER = 4
  109. _CD64_DISK_NUMBER_START = 5
  110. _CD64_NUMBER_ENTRIES_THIS_DISK = 6
  111. _CD64_NUMBER_ENTRIES_TOTAL = 7
  112. _CD64_DIRECTORY_SIZE = 8
  113. _CD64_OFFSET_START_CENTDIR = 9
  114. def _check_zipfile(fp):
  115. try:
  116. if _EndRecData(fp):
  117. return True # file has correct magic number
  118. except IOError:
  119. pass
  120. return False
  121. def is_zipfile(filename):
  122. """Quickly see if a file is a ZIP file by checking the magic number.
  123. The filename argument may be a file or file-like object too.
  124. """
  125. result = False
  126. try:
  127. if hasattr(filename, "read"):
  128. result = _check_zipfile(fp=filename)
  129. else:
  130. with open(filename, "rb") as fp:
  131. result = _check_zipfile(fp)
  132. except IOError:
  133. pass
  134. return result
  135. def _EndRecData64(fpin, offset, endrec):
  136. """
  137. Read the ZIP64 end-of-archive records and use that to update endrec
  138. """
  139. try:
  140. fpin.seek(offset - sizeEndCentDir64Locator, 2)
  141. except IOError:
  142. # If the seek fails, the file is not large enough to contain a ZIP64
  143. # end-of-archive record, so just return the end record we were given.
  144. return endrec
  145. data = fpin.read(sizeEndCentDir64Locator)
  146. sig, diskno, reloff, disks = struct.unpack(structEndArchive64Locator, data)
  147. if sig != stringEndArchive64Locator:
  148. return endrec
  149. if diskno != 0 or disks != 1:
  150. raise BadZipfile("zipfiles that span multiple disks are not supported")
  151. # Assume no 'zip64 extensible data'
  152. fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2)
  153. data = fpin.read(sizeEndCentDir64)
  154. sig, sz, create_version, read_version, disk_num, disk_dir, \
  155. dircount, dircount2, dirsize, diroffset = \
  156. struct.unpack(structEndArchive64, data)
  157. if sig != stringEndArchive64:
  158. return endrec
  159. # Update the original endrec using data from the ZIP64 record
  160. endrec[_ECD_SIGNATURE] = sig
  161. endrec[_ECD_DISK_NUMBER] = disk_num
  162. endrec[_ECD_DISK_START] = disk_dir
  163. endrec[_ECD_ENTRIES_THIS_DISK] = dircount
  164. endrec[_ECD_ENTRIES_TOTAL] = dircount2
  165. endrec[_ECD_SIZE] = dirsize
  166. endrec[_ECD_OFFSET] = diroffset
  167. return endrec
  168. def _EndRecData(fpin):
  169. """Return data from the "End of Central Directory" record, or None.
  170. The data is a list of the nine items in the ZIP "End of central dir"
  171. record followed by a tenth item, the file seek offset of this record."""
  172. # Determine file size
  173. fpin.seek(0, 2)
  174. filesize = fpin.tell()
  175. # Check to see if this is ZIP file with no archive comment (the
  176. # "end of central directory" structure should be the last item in the
  177. # file if this is the case).
  178. try:
  179. fpin.seek(-sizeEndCentDir, 2)
  180. except IOError:
  181. return None
  182. data = fpin.read()
  183. if data[0:4] == stringEndArchive and data[-2:] == "\000\000":
  184. # the signature is correct and there's no comment, unpack structure
  185. endrec = struct.unpack(structEndArchive, data)
  186. endrec=list(endrec)
  187. # Append a blank comment and record start offset
  188. endrec.append("")
  189. endrec.append(filesize - sizeEndCentDir)
  190. # Try to read the "Zip64 end of central directory" structure
  191. return _EndRecData64(fpin, -sizeEndCentDir, endrec)
  192. # Either this is not a ZIP file, or it is a ZIP file with an archive
  193. # comment. Search the end of the file for the "end of central directory"
  194. # record signature. The comment is the last item in the ZIP file and may be
  195. # up to 64K long. It is assumed that the "end of central directory" magic
  196. # number does not appear in the comment.
  197. maxCommentStart = max(filesize - (1 << 16) - sizeEndCentDir, 0)
  198. fpin.seek(maxCommentStart, 0)
  199. data = fpin.read()
  200. start = data.rfind(stringEndArchive)
  201. if start >= 0:
  202. # found the magic number; attempt to unpack and interpret
  203. recData = data[start:start+sizeEndCentDir]
  204. endrec = list(struct.unpack(structEndArchive, recData))
  205. commentSize = endrec[_ECD_COMMENT_SIZE] #as claimed by the zip file
  206. comment = data[start+sizeEndCentDir:start+sizeEndCentDir+commentSize]
  207. endrec.append(comment)
  208. endrec.append(maxCommentStart + start)
  209. # Try to read the "Zip64 end of central directory" structure
  210. return _EndRecData64(fpin, maxCommentStart + start - filesize,
  211. endrec)
  212. # Unable to find a valid end of central directory structure
  213. return
  214. class ZipInfo (object):
  215. """Class with attributes describing each file in the ZIP archive."""
  216. __slots__ = (
  217. 'orig_filename',
  218. 'filename',
  219. 'date_time',
  220. 'compress_type',
  221. 'comment',
  222. 'extra',
  223. 'create_system',
  224. 'create_version',
  225. 'extract_version',
  226. 'reserved',
  227. 'flag_bits',
  228. 'volume',
  229. 'internal_attr',
  230. 'external_attr',
  231. 'header_offset',
  232. 'CRC',
  233. 'compress_size',
  234. 'file_size',
  235. '_raw_time',
  236. )
  237. def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
  238. self.orig_filename = filename # Original file name in archive
  239. # Terminate the file name at the first null byte. Null bytes in file
  240. # names are used as tricks by viruses in archives.
  241. null_byte = filename.find(chr(0))
  242. if null_byte >= 0:
  243. filename = filename[0:null_byte]
  244. # This is used to ensure paths in generated ZIP files always use
  245. # forward slashes as the directory separator, as required by the
  246. # ZIP format specification.
  247. if os.sep != "/" and os.sep in filename:
  248. filename = filename.replace(os.sep, "/")
  249. self.filename = filename # Normalized file name
  250. self.date_time = date_time # year, month, day, hour, min, sec
  251. if date_time[0] < 1980:
  252. raise ValueError('ZIP does not support timestamps before 1980')
  253. # Standard values:
  254. self.compress_type = ZIP_STORED # Type of compression for the file
  255. self.comment = "" # Comment for each file
  256. self.extra = "" # ZIP extra data
  257. if sys.platform == 'win32':
  258. self.create_system = 0 # System which created ZIP archive
  259. else:
  260. # Assume everything else is unix-y
  261. self.create_system = 3 # System which created ZIP archive
  262. self.create_version = 20 # Version which created ZIP archive
  263. self.extract_version = 20 # Version needed to extract archive
  264. self.reserved = 0 # Must be zero
  265. self.flag_bits = 0 # ZIP flag bits
  266. self.volume = 0 # Volume number of file header
  267. self.internal_attr = 0 # Internal attributes
  268. self.external_attr = 0 # External file attributes
  269. # Other attributes are set by class ZipFile:
  270. # header_offset Byte offset to the file header
  271. # CRC CRC-32 of the uncompressed file
  272. # compress_size Size of the compressed file
  273. # file_size Size of the uncompressed file
  274. def FileHeader(self):
  275. """Return the per-file header as a string."""
  276. dt = self.date_time
  277. dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
  278. dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
  279. if self.flag_bits & 0x08:
  280. # Set these to zero because we write them after the file data
  281. CRC = compress_size = file_size = 0
  282. else:
  283. CRC = self.CRC
  284. compress_size = self.compress_size
  285. file_size = self.file_size
  286. extra = self.extra
  287. if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
  288. # File is larger than what fits into a 4 byte integer,
  289. # fall back to the ZIP64 extension
  290. fmt = '<HHQQ'
  291. extra = extra + struct.pack(fmt,
  292. 1, struct.calcsize(fmt)-4, file_size, compress_size)
  293. file_size = 0xffffffff
  294. compress_size = 0xffffffff
  295. self.extract_version = max(45, self.extract_version)
  296. self.create_version = max(45, self.extract_version)
  297. filename, flag_bits = self._encodeFilenameFlags()
  298. header = struct.pack(structFileHeader, stringFileHeader,
  299. self.extract_version, self.reserved, flag_bits,
  300. self.compress_type, dostime, dosdate, CRC,
  301. compress_size, file_size,
  302. len(filename), len(extra))
  303. return header + filename + extra
  304. def _encodeFilenameFlags(self):
  305. if isinstance(self.filename, unicode):
  306. try:
  307. return self.filename.encode('ascii'), self.flag_bits
  308. except UnicodeEncodeError:
  309. return self.filename.encode('utf-8'), self.flag_bits | 0x800
  310. else:
  311. return self.filename, self.flag_bits
  312. def _decodeFilename(self):
  313. if self.flag_bits & 0x800:
  314. return self.filename.decode('utf-8')
  315. else:
  316. return self.filename
  317. def _decodeExtra(self):
  318. # Try to decode the extra field.
  319. extra = self.extra
  320. unpack = struct.unpack
  321. while extra:
  322. tp, ln = unpack('<HH', extra[:4])
  323. if tp == 1:
  324. if ln >= 24:
  325. counts = unpack('<QQQ', extra[4:28])
  326. elif ln == 16:
  327. counts = unpack('<QQ', extra[4:20])
  328. elif ln == 8:
  329. counts = unpack('<Q', extra[4:12])
  330. elif ln == 0:
  331. counts = ()
  332. else:
  333. raise RuntimeError, "Corrupt extra field %s"%(ln,)
  334. idx = 0
  335. # ZIP64 extension (large files and/or large archives)
  336. if self.file_size in (0xffffffffffffffffL, 0xffffffffL):
  337. self.file_size = counts[idx]
  338. idx += 1
  339. if self.compress_size == 0xFFFFFFFFL:
  340. self.compress_size = counts[idx]
  341. idx += 1
  342. if self.header_offset == 0xffffffffL:
  343. old = self.header_offset
  344. self.header_offset = counts[idx]
  345. idx+=1
  346. extra = extra[ln+4:]
  347. class _ZipDecrypter:
  348. """Class to handle decryption of files stored within a ZIP archive.
  349. ZIP supports a password-based form of encryption. Even though known
  350. plaintext attacks have been found against it, it is still useful
  351. to be able to get data out of such a file.
  352. Usage:
  353. zd = _ZipDecrypter(mypwd)
  354. plain_char = zd(cypher_char)
  355. plain_text = map(zd, cypher_text)
  356. """
  357. def _GenerateCRCTable():
  358. """Generate a CRC-32 table.
  359. ZIP encryption uses the CRC32 one-byte primitive for scrambling some
  360. internal keys. We noticed that a direct implementation is faster than
  361. relying on binascii.crc32().
  362. """
  363. poly = 0xedb88320
  364. table = [0] * 256
  365. for i in range(256):
  366. crc = i
  367. for j in range(8):
  368. if crc & 1:
  369. crc = ((crc >> 1) & 0x7FFFFFFF) ^ poly
  370. else:
  371. crc = ((crc >> 1) & 0x7FFFFFFF)
  372. table[i] = crc
  373. return table
  374. crctable = _GenerateCRCTable()
  375. def _crc32(self, ch, crc):
  376. """Compute the CRC32 primitive on one byte."""
  377. return ((crc >> 8) & 0xffffff) ^ self.crctable[(crc ^ ord(ch)) & 0xff]
  378. def __init__(self, pwd):
  379. self.key0 = 305419896
  380. self.key1 = 591751049
  381. self.key2 = 878082192
  382. for p in pwd:
  383. self._UpdateKeys(p)
  384. def _UpdateKeys(self, c):
  385. self.key0 = self._crc32(c, self.key0)
  386. self.key1 = (self.key1 + (self.key0 & 255)) & 4294967295
  387. self.key1 = (self.key1 * 134775813 + 1) & 4294967295
  388. self.key2 = self._crc32(chr((self.key1 >> 24) & 255), self.key2)
  389. def __call__(self, c):
  390. """Decrypt a single character."""
  391. c = ord(c)
  392. k = self.key2 | 2
  393. c = c ^ (((k * (k^1)) >> 8) & 255)
  394. c = chr(c)
  395. self._UpdateKeys(c)
  396. return c
  397. class ZipExtFile(io.BufferedIOBase):
  398. """File-like object for reading an archive member.
  399. Is returned by ZipFile.open().
  400. """
  401. # Max size supported by decompressor.
  402. MAX_N = 1 << 31 - 1
  403. # Read from compressed files in 4k blocks.
  404. MIN_READ_SIZE = 4096
  405. # Search for universal newlines or line chunks.
  406. PATTERN = re.compile(r'^(?P<chunk>[^\r\n]+)|(?P<newline>\n|\r\n?)')
  407. def __init__(self, fileobj, mode, zipinfo, decrypter=None,
  408. close_fileobj=False):
  409. self._fileobj = fileobj
  410. self._decrypter = decrypter
  411. self._close_fileobj = close_fileobj
  412. self._compress_type = zipinfo.compress_type
  413. self._compress_size = zipinfo.compress_size
  414. self._compress_left = zipinfo.compress_size
  415. if self._compress_type == ZIP_DEFLATED:
  416. self._decompressor = zlib.decompressobj(-15)
  417. self._unconsumed = ''
  418. self._readbuffer = ''
  419. self._offset = 0
  420. self._universal = 'U' in mode
  421. self.newlines = None
  422. # Adjust read size for encrypted files since the first 12 bytes
  423. # are for the encryption/password information.
  424. if self._decrypter is not None:
  425. self._compress_left -= 12
  426. self.mode = mode
  427. self.name = zipinfo.filename
  428. if hasattr(zipinfo, 'CRC'):
  429. self._expected_crc = zipinfo.CRC
  430. self._running_crc = crc32(b'') & 0xffffffff
  431. else:
  432. self._expected_crc = None
  433. def readline(self, limit=-1):
  434. """Read and return a line from the stream.
  435. If limit is specified, at most limit bytes will be read.
  436. """
  437. if not self._universal and limit < 0:
  438. # Shortcut common case - newline found in buffer.
  439. i = self._readbuffer.find('\n', self._offset) + 1
  440. if i > 0:
  441. line = self._readbuffer[self._offset: i]
  442. self._offset = i
  443. return line
  444. if not self._universal:
  445. return io.BufferedIOBase.readline(self, limit)
  446. line = ''
  447. while limit < 0 or len(line) < limit:
  448. readahead = self.peek(2)
  449. if readahead == '':
  450. return line
  451. #
  452. # Search for universal newlines or line chunks.
  453. #
  454. # The pattern returns either a line chunk or a newline, but not
  455. # both. Combined with peek(2), we are assured that the sequence
  456. # '\r\n' is always retrieved completely and never split into
  457. # separate newlines - '\r', '\n' due to coincidental readaheads.
  458. #
  459. match = self.PATTERN.search(readahead)
  460. newline = match.group('newline')
  461. if newline is not None:
  462. if self.newlines is None:
  463. self.newlines = []
  464. if newline not in self.newlines:
  465. self.newlines.append(newline)
  466. self._offset += len(newline)
  467. return line + '\n'
  468. chunk = match.group('chunk')
  469. if limit >= 0:
  470. chunk = chunk[: limit - len(line)]
  471. self._offset += len(chunk)
  472. line += chunk
  473. return line
  474. def peek(self, n=1):
  475. """Returns buffered bytes without advancing the position."""
  476. if n > len(self._readbuffer) - self._offset:
  477. chunk = self.read(n)
  478. self._offset -= len(chunk)
  479. # Return up to 512 bytes to reduce allocation overhead for tight loops.
  480. return self._readbuffer[self._offset: self._offset + 512]
  481. def readable(self):
  482. return True
  483. def read(self, n=-1):
  484. """Read and return up to n bytes.
  485. If the argument is omitted, None, or negative, data is read and returned until EOF is reached..
  486. """
  487. buf = ''
  488. if n is None:
  489. n = -1
  490. while True:
  491. if n < 0:
  492. data = self.read1(n)
  493. elif n > len(buf):
  494. data = self.read1(n - len(buf))
  495. else:
  496. return buf
  497. if len(data) == 0:
  498. return buf
  499. buf += data
  500. def _update_crc(self, newdata, eof):
  501. # Update the CRC using the given data.
  502. if self._expected_crc is None:
  503. # No need to compute the CRC if we don't have a reference value
  504. return
  505. self._running_crc = crc32(newdata, self._running_crc) & 0xffffffff
  506. # Check the CRC if we're at the end of the file
  507. if eof and self._running_crc != self._expected_crc:
  508. raise BadZipfile("Bad CRC-32 for file %r" % self.name)
  509. def read1(self, n):
  510. """Read up to n bytes with at most one read() system call."""
  511. # Simplify algorithm (branching) by transforming negative n to large n.
  512. if n < 0 or n is None:
  513. n = self.MAX_N
  514. # Bytes available in read buffer.
  515. len_readbuffer = len(self._readbuffer) - self._offset
  516. # Read from file.
  517. if self._compress_left > 0 and n > len_readbuffer + len(self._unconsumed):
  518. nbytes = n - len_readbuffer - len(self._unconsumed)
  519. nbytes = max(nbytes, self.MIN_READ_SIZE)
  520. nbytes = min(nbytes, self._compress_left)
  521. data = self._fileobj.read(nbytes)
  522. self._compress_left -= len(data)
  523. if data and self._decrypter is not None:
  524. data = ''.join(map(self._decrypter, data))
  525. if self._compress_type == ZIP_STORED:
  526. self._update_crc(data, eof=(self._compress_left==0))
  527. self._readbuffer = self._readbuffer[self._offset:] + data
  528. self._offset = 0
  529. else:
  530. # Prepare deflated bytes for decompression.
  531. self._unconsumed += data
  532. # Handle unconsumed data.
  533. if (len(self._unconsumed) > 0 and n > len_readbuffer and
  534. self._compress_type == ZIP_DEFLATED):
  535. data = self._decompressor.decompress(
  536. self._unconsumed,
  537. max(n - len_readbuffer, self.MIN_READ_SIZE)
  538. )
  539. self._unconsumed = self._decompressor.unconsumed_tail
  540. eof = len(self._unconsumed) == 0 and self._compress_left == 0
  541. if eof:
  542. data += self._decompressor.flush()
  543. self._update_crc(data, eof=eof)
  544. self._readbuffer = self._readbuffer[self._offset:] + data
  545. self._offset = 0
  546. # Read from buffer.
  547. data = self._readbuffer[self._offset: self._offset + n]
  548. self._offset += len(data)
  549. return data
  550. def close(self):
  551. try:
  552. if self._close_fileobj:
  553. self._fileobj.close()
  554. finally:
  555. super(ZipExtFile, self).close()
  556. class ZipFile:
  557. """ Class with methods to open, read, write, close, list zip files.
  558. z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False)
  559. file: Either the path to the file, or a file-like object.
  560. If it is a path, the file will be opened and closed by ZipFile.
  561. mode: The mode can be either read "r", write "w" or append "a".
  562. compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib).
  563. allowZip64: if True ZipFile will create files with ZIP64 extensions when
  564. needed, otherwise it will raise an exception when this would
  565. be necessary.
  566. """
  567. fp = None # Set here since __del__ checks it
  568. def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False):
  569. """Open the ZIP file with mode read "r", write "w" or append "a"."""
  570. if mode not in ("r", "w", "a"):
  571. raise RuntimeError('ZipFile() requires mode "r", "w", or "a"')
  572. if compression == ZIP_STORED:
  573. pass
  574. elif compression == ZIP_DEFLATED:
  575. if not zlib:
  576. raise RuntimeError,\
  577. "Compression requires the (missing) zlib module"
  578. else:
  579. raise RuntimeError, "That compression method is not supported"
  580. self._allowZip64 = allowZip64
  581. self._didModify = False
  582. self.debug = 0 # Level of printing: 0 through 3
  583. self.NameToInfo = {} # Find file info given name
  584. self.filelist = [] # List of ZipInfo instances for archive
  585. self.compression = compression # Method of compression
  586. self.mode = key = mode.replace('b', '')[0]
  587. self.pwd = None
  588. self.comment = ''
  589. # Check if we were passed a file-like object
  590. if isinstance(file, basestring):
  591. self._filePassed = 0
  592. self.filename = file
  593. modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
  594. try:
  595. self.fp = open(file, modeDict[mode])
  596. except IOError:
  597. if mode == 'a':
  598. mode = key = 'w'
  599. self.fp = open(file, modeDict[mode])
  600. else:
  601. raise
  602. else:
  603. self._filePassed = 1
  604. self.fp = file
  605. self.filename = getattr(file, 'name', None)
  606. if key == 'r':
  607. self._GetContents()
  608. elif key == 'w':
  609. # set the modified flag so central directory gets written
  610. # even if no files are added to the archive
  611. self._didModify = True
  612. elif key == 'a':
  613. try:
  614. # See if file is a zip file
  615. self._RealGetContents()
  616. # seek to start of directory and overwrite
  617. self.fp.seek(self.start_dir, 0)
  618. except BadZipfile:
  619. # file is not a zip file, just append
  620. self.fp.seek(0, 2)
  621. # set the modified flag so central directory gets written
  622. # even if no files are added to the archive
  623. self._didModify = True
  624. else:
  625. if not self._filePassed:
  626. self.fp.close()
  627. self.fp = None
  628. raise RuntimeError, 'Mode must be "r", "w" or "a"'
  629. def __enter__(self):
  630. return self
  631. def __exit__(self, type, value, traceback):
  632. self.close()
  633. def _GetContents(self):
  634. """Read the directory, making sure we close the file if the format
  635. is bad."""
  636. try:
  637. self._RealGetContents()
  638. except BadZipfile:
  639. if not self._filePassed:
  640. self.fp.close()
  641. self.fp = None
  642. raise
  643. def _RealGetContents(self):
  644. """Read in the table of contents for the ZIP file."""
  645. fp = self.fp
  646. try:
  647. endrec = _EndRecData(fp)
  648. except IOError:
  649. raise BadZipfile("File is not a zip file")
  650. if not endrec:
  651. raise BadZipfile, "File is not a zip file"
  652. if self.debug > 1:
  653. print endrec
  654. size_cd = endrec[_ECD_SIZE] # bytes in central directory
  655. offset_cd = endrec[_ECD_OFFSET] # offset of central directory
  656. self.comment = endrec[_ECD_COMMENT] # archive comment
  657. # "concat" is zero, unless zip was concatenated to another file
  658. concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
  659. if endrec[_ECD_SIGNATURE] == stringEndArchive64:
  660. # If Zip64 extension structures are present, account for them
  661. concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)
  662. if self.debug > 2:
  663. inferred = concat + offset_cd
  664. print "given, inferred, offset", offset_cd, inferred, concat
  665. # self.start_dir: Position of start of central directory
  666. self.start_dir = offset_cd + concat
  667. fp.seek(self.start_dir, 0)
  668. data = fp.read(size_cd)
  669. fp = cStringIO.StringIO(data)
  670. total = 0
  671. while total < size_cd:
  672. centdir = fp.read(sizeCentralDir)
  673. if centdir[0:4] != stringCentralDir:
  674. raise BadZipfile, "Bad magic number for central directory"
  675. centdir = struct.unpack(structCentralDir, centdir)
  676. if self.debug > 2:
  677. print centdir
  678. filename = fp.read(centdir[_CD_FILENAME_LENGTH])
  679. # Create ZipInfo instance to store file information
  680. x = ZipInfo(filename)
  681. x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
  682. x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
  683. x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
  684. (x.create_version, x.create_system, x.extract_version, x.reserved,
  685. x.flag_bits, x.compress_type, t, d,
  686. x.CRC, x.compress_size, x.file_size) = centdir[1:12]
  687. x.volume, x.internal_attr, x.external_attr = centdir[15:18]
  688. # Convert date/time code to (year, month, day, hour, min, sec)
  689. x._raw_time = t
  690. x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F,
  691. t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
  692. x._decodeExtra()
  693. x.header_offset = x.header_offset + concat
  694. x.filename = x._decodeFilename()
  695. self.filelist.append(x)
  696. self.NameToInfo[x.filename] = x
  697. # update total bytes read from central directory
  698. total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH]
  699. + centdir[_CD_EXTRA_FIELD_LENGTH]
  700. + centdir[_CD_COMMENT_LENGTH])
  701. if self.debug > 2:
  702. print "total", total
  703. def namelist(self):
  704. """Return a list of file names in the archive."""
  705. l = []
  706. for data in self.filelist:
  707. l.append(data.filename)
  708. return l
  709. def infolist(self):
  710. """Return a list of class ZipInfo instances for files in the
  711. archive."""
  712. return self.filelist
  713. def printdir(self):
  714. """Print a table of contents for the zip file."""
  715. print "%-46s %19s %12s" % ("File Name", "Modified ", "Size")
  716. for zinfo in self.filelist:
  717. date = "%d-%02d-%02d %02d:%02d:%02d" % zinfo.date_time[:6]
  718. print "%-46s %s %12d" % (zinfo.filename, date, zinfo.file_size)
  719. def testzip(self):
  720. """Read all the files and check the CRC."""
  721. chunk_size = 2 ** 20
  722. for zinfo in self.filelist:
  723. try:
  724. # Read by chunks, to avoid an OverflowError or a
  725. # MemoryError with very large embedded files.
  726. f = self.open(zinfo.filename, "r")
  727. while f.read(chunk_size): # Check CRC-32
  728. pass
  729. except BadZipfile:
  730. return zinfo.filename
  731. def getinfo(self, name):
  732. """Return the instance of ZipInfo given 'name'."""
  733. info = self.NameToInfo.get(name)
  734. if info is None:
  735. raise KeyError(
  736. 'There is no item named %r in the archive' % name)
  737. return info
  738. def setpassword(self, pwd):
  739. """Set default password for encrypted files."""
  740. self.pwd = pwd
  741. def read(self, name, pwd=None):
  742. """Return file bytes (as a string) for name."""
  743. with self.open(name, "r", pwd) as fp:
  744. return fp.read()
  745. def open(self, name, mode="r", pwd=None):
  746. """Return file-like object for 'name'."""
  747. if mode not in ("r", "U", "rU"):
  748. raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
  749. if not self.fp:
  750. raise RuntimeError, \
  751. "Attempt to read ZIP archive that was already closed"
  752. # Only open a new file for instances where we were not
  753. # given a file object in the constructor
  754. if self._filePassed:
  755. zef_file = self.fp
  756. else:
  757. zef_file = open(self.filename, 'rb')
  758. # Make sure we have an info object
  759. if isinstance(name, ZipInfo):
  760. # 'name' is already an info object
  761. zinfo = name
  762. else:
  763. # Get info object for name
  764. try:
  765. zinfo = self.getinfo(name)
  766. except KeyError:
  767. if not self._filePassed:
  768. zef_file.close()
  769. raise
  770. zef_file.seek(zinfo.header_offset, 0)
  771. # Skip the file header:
  772. fheader = zef_file.read(sizeFileHeader)
  773. if fheader[0:4] != stringFileHeader:
  774. raise BadZipfile, "Bad magic number for file header"
  775. fheader = struct.unpack(structFileHeader, fheader)
  776. fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
  777. if fheader[_FH_EXTRA_FIELD_LENGTH]:
  778. zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
  779. if fname != zinfo.orig_filename:
  780. if not self._filePassed:
  781. zef_file.close()
  782. raise BadZipfile, \
  783. 'File name in directory "%s" and header "%s" differ.' % (
  784. zinfo.orig_filename, fname)
  785. # check for encrypted flag & handle password
  786. is_encrypted = zinfo.flag_bits & 0x1
  787. zd = None
  788. if is_encrypted:
  789. if not pwd:
  790. pwd = self.pwd
  791. if not pwd:
  792. if not self._filePassed:
  793. zef_file.close()
  794. raise RuntimeError, "File %s is encrypted, " \
  795. "password required for extraction" % name
  796. zd = _ZipDecrypter(pwd)
  797. # The first 12 bytes in the cypher stream is an encryption header
  798. # used to strengthen the algorithm. The first 11 bytes are
  799. # completely random, while the 12th contains the MSB of the CRC,
  800. # or the MSB of the file time depending on the header type
  801. # and is used to check the correctness of the password.
  802. bytes = zef_file.read(12)
  803. h = map(zd, bytes[0:12])
  804. if zinfo.flag_bits & 0x8:
  805. # compare against the file type from extended local headers
  806. check_byte = (zinfo._raw_time >> 8) & 0xff
  807. else:
  808. # compare against the CRC otherwise
  809. check_byte = (zinfo.CRC >> 24) & 0xff
  810. if ord(h[11]) != check_byte:
  811. if not self._filePassed:
  812. zef_file.close()
  813. raise RuntimeError("Bad password for file", name)
  814. return ZipExtFile(zef_file, mode, zinfo, zd,
  815. close_fileobj=not self._filePassed)
  816. def extract(self, member, path=None, pwd=None):
  817. """Extract a member from the archive to the current working directory,
  818. using its full name. Its file information is extracted as accurately
  819. as possible. `member' may be a filename or a ZipInfo object. You can
  820. specify a different directory using `path'.
  821. """
  822. if not isinstance(member, ZipInfo):
  823. member = self.getinfo(member)
  824. if path is None:
  825. path = os.getcwd()
  826. return self._extract_member(member, path, pwd)
  827. def extractall(self, path=None, members=None, pwd=None):
  828. """Extract all members from the archive to the current working
  829. directory. `path' specifies a different directory to extract to.
  830. `members' is optional and must be a subset of the list returned
  831. by namelist().
  832. """
  833. if members is None:
  834. members = self.namelist()
  835. for zipinfo in members:
  836. self.extract(zipinfo, path, pwd)
  837. def _extract_member(self, member, targetpath, pwd):
  838. """Extract the ZipInfo object 'member' to a physical
  839. file on the path targetpath.
  840. """
  841. # build the destination pathname, replacing
  842. # forward slashes to platform specific separators.
  843. # Strip trailing path separator, unless it represents the root.
  844. if (targetpath[-1:] in (os.path.sep, os.path.altsep)
  845. and len(os.path.splitdrive(targetpath)[1]) > 1):
  846. targetpath = targetpath[:-1]
  847. # don't include leading "/" from file name if present
  848. if member.filename[0] == '/':
  849. targetpath = os.path.join(targetpath, member.filename[1:])
  850. else:
  851. targetpath = os.path.join(targetpath, member.filename)
  852. targetpath = os.path.normpath(targetpath)
  853. # Create all upper directories if necessary.
  854. upperdirs = os.path.dirname(targetpath)
  855. if upperdirs and not os.path.exists(upperdirs):
  856. os.makedirs(upperdirs)
  857. if member.filename[-1] == '/':
  858. if not os.path.isdir(targetpath):
  859. os.mkdir(targetpath)
  860. return targetpath
  861. source = self.open(member, pwd=pwd)
  862. target = open(targetpath, "wb")
  863. shutil.copyfileobj(source, target)
  864. source.close()
  865. target.close()
  866. return targetpath
  867. def _writecheck(self, zinfo):
  868. """Check for errors before writing a file to the archive."""
  869. if zinfo.filename in self.NameToInfo:
  870. if self.debug: # Warning for duplicate names
  871. print "Duplicate name:", zinfo.filename
  872. if self.mode not in ("w", "a"):
  873. raise RuntimeError, 'write() requires mode "w" or "a"'
  874. if not self.fp:
  875. raise RuntimeError, \
  876. "Attempt to write ZIP archive that was already closed"
  877. if zinfo.compress_type == ZIP_DEFLATED and not zlib:
  878. raise RuntimeError, \
  879. "Compression requires the (missing) zlib module"
  880. if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED):
  881. raise RuntimeError, \
  882. "That compression method is not supported"
  883. if zinfo.file_size > ZIP64_LIMIT:
  884. if not self._allowZip64:
  885. raise LargeZipFile("Filesize would require ZIP64 extensions")
  886. if zinfo.header_offset > ZIP64_LIMIT:
  887. if not self._allowZip64:
  888. raise LargeZipFile("Zipfile size would require ZIP64 extensions")
  889. def write(self, filename, arcname=None, compress_type=None):
  890. """Put the bytes from filename into the archive under the name
  891. arcname."""
  892. if not self.fp:
  893. raise RuntimeError(
  894. "Attempt to write to ZIP archive that was already closed")
  895. st = os.stat(filename)
  896. isdir = stat.S_ISDIR(st.st_mode)
  897. mtime = time.localtime(st.st_mtime)
  898. date_time = mtime[0:6]
  899. # Create ZipInfo instance to store file information
  900. if arcname is None:
  901. arcname = filename
  902. arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
  903. while arcname[0] in (os.sep, os.altsep):
  904. arcname = arcname[1:]
  905. if isdir:
  906. arcname += '/'
  907. zinfo = ZipInfo(arcname, date_time)
  908. zinfo.external_attr = (st[0] & 0xFFFF) << 16L # Unix attributes
  909. if compress_type is None:
  910. zinfo.compress_type = self.compression
  911. else:
  912. zinfo.compress_type = compress_type
  913. zinfo.file_size = st.st_size
  914. zinfo.flag_bits = 0x00
  915. zinfo.header_offset = self.fp.tell() # Start of header bytes
  916. self._writecheck(zinfo)
  917. self._didModify = True
  918. if isdir:
  919. zinfo.file_size = 0
  920. zinfo.compress_size = 0
  921. zinfo.CRC = 0
  922. self.filelist.append(zinfo)
  923. self.NameToInfo[zinfo.filename] = zinfo
  924. self.fp.write(zinfo.FileHeader())
  925. return
  926. with open(filename, "rb") as fp:
  927. # Must overwrite CRC and sizes with correct data later
  928. zinfo.CRC = CRC = 0
  929. zinfo.compress_size = compress_size = 0
  930. zinfo.file_size = file_size = 0
  931. self.fp.write(zinfo.FileHeader())
  932. if zinfo.compress_type == ZIP_DEFLATED:
  933. cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
  934. zlib.DEFLATED, -15)
  935. else:
  936. cmpr = None
  937. while 1:
  938. buf = fp.read(1024 * 8)
  939. if not buf:
  940. break
  941. file_size = file_size + len(buf)
  942. CRC = crc32(buf, CRC) & 0xffffffff
  943. if cmpr:
  944. buf = cmpr.compress(buf)
  945. compress_size = compress_size + len(buf)
  946. self.fp.write(buf)
  947. if cmpr:
  948. buf = cmpr.flush()
  949. compress_size = compress_size + len(buf)
  950. self.fp.write(buf)
  951. zinfo.compress_size = compress_size
  952. else:
  953. zinfo.compress_size = file_size
  954. zinfo.CRC = CRC
  955. zinfo.file_size = file_size
  956. # Seek backwards and write CRC and file sizes
  957. position = self.fp.tell() # Preserve current position in file
  958. self.fp.seek(zinfo.header_offset + 14, 0)
  959. self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
  960. zinfo.file_size))
  961. self.fp.seek(position, 0)
  962. self.filelist.append(zinfo)
  963. self.NameToInfo[zinfo.filename] = zinfo
  964. def writestr(self, zinfo_or_arcname, bytes, compress_type=None):
  965. """Write a file into the archive. The contents is the string
  966. 'bytes'. 'zinfo_or_arcname' is either a ZipInfo instance or
  967. the name of the file in the archive."""
  968. if not isinstance(zinfo_or_arcname, ZipInfo):
  969. zinfo = ZipInfo(filename=zinfo_or_arcname,
  970. date_time=time.localtime(time.time())[:6])
  971. zinfo.compress_type = self.compression
  972. zinfo.external_attr = 0600 << 16
  973. else:
  974. zinfo = zinfo_or_arcname
  975. if not self.fp:
  976. raise RuntimeError(
  977. "Attempt to write to ZIP archive that was already closed")
  978. if compress_type is not None:
  979. zinfo.compress_type = compress_type
  980. zinfo.file_size = len(bytes) # Uncompressed size
  981. zinfo.header_offset = self.fp.tell() # Start of header bytes
  982. self._writecheck(zinfo)
  983. self._didModify = True
  984. zinfo.CRC = crc32(bytes) & 0xffffffff # CRC-32 checksum
  985. if zinfo.compress_type == ZIP_DEFLATED:
  986. co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
  987. zlib.DEFLATED, -15)
  988. bytes = co.compress(bytes) + co.flush()
  989. zinfo.compress_size = len(bytes) # Compressed size
  990. else:
  991. zinfo.compress_size = zinfo.file_size
  992. zinfo.header_offset = self.fp.tell() # Start of header bytes
  993. self.fp.write(zinfo.FileHeader())
  994. self.fp.write(bytes)
  995. self.fp.flush()
  996. if zinfo.flag_bits & 0x08:
  997. # Write CRC and file sizes after the file data
  998. self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
  999. zinfo.file_size))
  1000. self.filelist.append(zinfo)
  1001. self.NameToInfo[zinfo.filename] = zinfo
  1002. def __del__(self):
  1003. """Call the "close()" method in case the user forgot."""
  1004. self.close()
  1005. def close(self):
  1006. """Close the file, and for mode "w" and "a" write the ending
  1007. records."""
  1008. if self.fp is None:
  1009. return
  1010. if self.mode in ("w", "a") and self._didModify: # write ending records
  1011. count = 0
  1012. pos1 = self.fp.tell()
  1013. for zinfo in self.filelist: # write central directory
  1014. count = count + 1
  1015. dt = zinfo.date_time
  1016. dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
  1017. dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
  1018. extra = []
  1019. if zinfo.file_size > ZIP64_LIMIT \
  1020. or zinfo.compress_size > ZIP64_LIMIT:
  1021. extra.append(zinfo.file_size)
  1022. extra.append(zinfo.compress_size)
  1023. file_size = 0xffffffff
  1024. compress_size = 0xffffffff
  1025. else:
  1026. file_size = zinfo.file_size
  1027. compress_size = zinfo.compress_size
  1028. if zinfo.header_offset > ZIP64_LIMIT:
  1029. extra.append(zinfo.header_offset)
  1030. header_offset = 0xffffffffL
  1031. else:
  1032. header_offset = zinfo.header_offset
  1033. extra_data = zinfo.extra
  1034. if extra:
  1035. # Append a ZIP64 field to the extra's
  1036. extra_data = struct.pack(
  1037. '<HH' + 'Q'*len(extra),
  1038. 1, 8*len(extra), *extra) + extra_data
  1039. extract_version = max(45, zinfo.extract_version)
  1040. create_version = max(45, zinfo.create_version)
  1041. else:
  1042. extract_version = zinfo.extract_version
  1043. create_version = zinfo.create_version
  1044. try:
  1045. filename, flag_bits = zinfo._encodeFilenameFlags()
  1046. centdir = struct.pack(structCentralDir,
  1047. stringCentralDir, create_version,
  1048. zinfo.create_system, extract_version, zinfo.reserved,
  1049. flag_bits, zinfo.compress_type, dostime, dosdate,
  1050. zinfo.CRC, compress_size, file_size,
  1051. len(filename), len(extra_data), len(zinfo.comment),
  1052. 0, zinfo.internal_attr, zinfo.external_attr,
  1053. header_offset)
  1054. except DeprecationWarning:
  1055. print >>sys.stderr, (structCentralDir,
  1056. stringCentralDir, create_version,
  1057. zinfo.create_system, extract_version, zinfo.reserved,
  1058. zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
  1059. zinfo.CRC, compress_size, file_size,
  1060. len(zinfo.filename), len(extra_data), len(zinfo.comment),
  1061. 0, zinfo.internal_attr, zinfo.external_attr,
  1062. header_offset)
  1063. raise
  1064. self.fp.write(centdir)
  1065. self.fp.write(filename)
  1066. self.fp.write(extra_data)
  1067. self.fp.write(zinfo.comment)
  1068. pos2 = self.fp.tell()
  1069. # Write end-of-zip-archive record
  1070. centDirCount = count
  1071. centDirSize = pos2 - pos1
  1072. centDirOffset = pos1
  1073. if (centDirCount >= ZIP_FILECOUNT_LIMIT or
  1074. centDirOffset > ZIP64_LIMIT or
  1075. centDirSize > ZIP64_LIMIT):
  1076. # Need to write the ZIP64 end-of-archive records
  1077. zip64endrec = struct.pack(
  1078. structEndArchive64, stringEndArchive64,
  1079. 44, 45, 45, 0, 0, centDirCount, centDirCount,
  1080. centDirSize, centDirOffset)
  1081. self.fp.write(zip64endrec)
  1082. zip64locrec = struct.pack(
  1083. structEndArchive64Locator,
  1084. stringEndArchive64Locator, 0, pos2, 1)
  1085. self.fp.write(zip64locrec)
  1086. centDirCount = min(centDirCount, 0xFFFF)
  1087. centDirSize = min(centDirSize, 0xFFFFFFFF)
  1088. centDirOffset = min(centDirOffset, 0xFFFFFFFF)
  1089. # check for valid comment length
  1090. if len(self.comment) >= ZIP_MAX_COMMENT:
  1091. if self.debug > 0:
  1092. msg = 'Archive comment is too long; truncating to %d bytes' \
  1093. % ZIP_MAX_COMMENT
  1094. self.comment = self.comment[:ZIP_MAX_COMMENT]
  1095. endrec = struct.pack(structEndArchive, stringEndArchive,
  1096. 0, 0, centDirCount, centDirCount,
  1097. centDirSize, centDirOffset, len(self.comment))
  1098. self.fp.write(endrec)
  1099. self.fp.write(self.comment)
  1100. self.fp.flush()
  1101. if not self._filePassed:
  1102. self.fp.close()
  1103. self.fp = None
  1104. class PyZipFile(ZipFile):
  1105. """Class to create ZIP archives with Python library files and packages."""
  1106. def writepy(self, pathname, basename = ""):
  1107. """Add all files from "pathname" to the ZIP archive.
  1108. If pathname is a package directory, search the directory and
  1109. all package subdirectories recursively for all *.py and enter
  1110. the modules into the archive. If pathname is a plain
  1111. directory, listdir *.py and enter all modules. Else, pathname
  1112. must be a Python *.py file and the module will be put into the
  1113. archive. Added modules are always module.pyo or module.pyc.
  1114. This method will compile the module.py into module.pyc if
  1115. necessary.
  1116. """
  1117. dir, name = os.path.split(pathname)
  1118. if os.path.isdir(pathname):
  1119. initname = os.path.join(pathname, "__init__.py")
  1120. if os.path.isfile(initname):
  1121. # This is a package directory, add it
  1122. if basename:
  1123. basename = "%s/%s" % (basename, name)
  1124. else:
  1125. basename = name
  1126. if self.debug:
  1127. print "Adding package in", pathname, "as", basename
  1128. fname, arcname = self._get_codename(initname[0:-3], basename)
  1129. if self.debug:
  1130. print "Adding", arcname
  1131. self.write(fname, arcname)
  1132. dirlist = os.listdir(pathname)
  1133. dirlist.remove("__init__.py")
  1134. # Add all *.py files and package subdirectories
  1135. for filename in dirlist:
  1136. path = os.path.join(pathname, filename)
  1137. root, ext = os.path.splitext(filename)
  1138. if os.path.isdir(path):
  1139. if os.path.isfile(os.path.join(path, "__init__.py")):
  1140. # This is a package directory, add it
  1141. self.writepy(path, basename) # Recursive call

Large files files are truncated, but you can click here to view the full file