PageRenderTime 54ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/lib-python/2.7/zipfile.py

https://bitbucket.org/quangquach/pypy
Python | 1439 lines | 1375 code | 27 blank | 37 comment | 21 complexity | 6f061f8c6a1dc1a7f79c2ef4acab0767 MD5 | raw file

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. self._fileobj = fileobj
  409. self._decrypter = decrypter
  410. self._compress_type = zipinfo.compress_type
  411. self._compress_size = zipinfo.compress_size
  412. self._compress_left = zipinfo.compress_size
  413. if self._compress_type == ZIP_DEFLATED:
  414. self._decompressor = zlib.decompressobj(-15)
  415. self._unconsumed = ''
  416. self._readbuffer = ''
  417. self._offset = 0
  418. self._universal = 'U' in mode
  419. self.newlines = None
  420. # Adjust read size for encrypted files since the first 12 bytes
  421. # are for the encryption/password information.
  422. if self._decrypter is not None:
  423. self._compress_left -= 12
  424. self.mode = mode
  425. self.name = zipinfo.filename
  426. if hasattr(zipinfo, 'CRC'):
  427. self._expected_crc = zipinfo.CRC
  428. self._running_crc = crc32(b'') & 0xffffffff
  429. else:
  430. self._expected_crc = None
  431. def readline(self, limit=-1):
  432. """Read and return a line from the stream.
  433. If limit is specified, at most limit bytes will be read.
  434. """
  435. if not self._universal and limit < 0:
  436. # Shortcut common case - newline found in buffer.
  437. i = self._readbuffer.find('\n', self._offset) + 1
  438. if i > 0:
  439. line = self._readbuffer[self._offset: i]
  440. self._offset = i
  441. return line
  442. if not self._universal:
  443. return io.BufferedIOBase.readline(self, limit)
  444. line = ''
  445. while limit < 0 or len(line) < limit:
  446. readahead = self.peek(2)
  447. if readahead == '':
  448. return line
  449. #
  450. # Search for universal newlines or line chunks.
  451. #
  452. # The pattern returns either a line chunk or a newline, but not
  453. # both. Combined with peek(2), we are assured that the sequence
  454. # '\r\n' is always retrieved completely and never split into
  455. # separate newlines - '\r', '\n' due to coincidental readaheads.
  456. #
  457. match = self.PATTERN.search(readahead)
  458. newline = match.group('newline')
  459. if newline is not None:
  460. if self.newlines is None:
  461. self.newlines = []
  462. if newline not in self.newlines:
  463. self.newlines.append(newline)
  464. self._offset += len(newline)
  465. return line + '\n'
  466. chunk = match.group('chunk')
  467. if limit >= 0:
  468. chunk = chunk[: limit - len(line)]
  469. self._offset += len(chunk)
  470. line += chunk
  471. return line
  472. def peek(self, n=1):
  473. """Returns buffered bytes without advancing the position."""
  474. if n > len(self._readbuffer) - self._offset:
  475. chunk = self.read(n)
  476. self._offset -= len(chunk)
  477. # Return up to 512 bytes to reduce allocation overhead for tight loops.
  478. return self._readbuffer[self._offset: self._offset + 512]
  479. def readable(self):
  480. return True
  481. def read(self, n=-1):
  482. """Read and return up to n bytes.
  483. If the argument is omitted, None, or negative, data is read and returned until EOF is reached..
  484. """
  485. buf = ''
  486. if n is None:
  487. n = -1
  488. while True:
  489. if n < 0:
  490. data = self.read1(n)
  491. elif n > len(buf):
  492. data = self.read1(n - len(buf))
  493. else:
  494. return buf
  495. if len(data) == 0:
  496. return buf
  497. buf += data
  498. def _update_crc(self, newdata, eof):
  499. # Update the CRC using the given data.
  500. if self._expected_crc is None:
  501. # No need to compute the CRC if we don't have a reference value
  502. return
  503. self._running_crc = crc32(newdata, self._running_crc) & 0xffffffff
  504. # Check the CRC if we're at the end of the file
  505. if eof and self._running_crc != self._expected_crc:
  506. raise BadZipfile("Bad CRC-32 for file %r" % self.name)
  507. def read1(self, n):
  508. """Read up to n bytes with at most one read() system call."""
  509. # Simplify algorithm (branching) by transforming negative n to large n.
  510. if n < 0 or n is None:
  511. n = self.MAX_N
  512. # Bytes available in read buffer.
  513. len_readbuffer = len(self._readbuffer) - self._offset
  514. # Read from file.
  515. if self._compress_left > 0 and n > len_readbuffer + len(self._unconsumed):
  516. nbytes = n - len_readbuffer - len(self._unconsumed)
  517. nbytes = max(nbytes, self.MIN_READ_SIZE)
  518. nbytes = min(nbytes, self._compress_left)
  519. data = self._fileobj.read(nbytes)
  520. self._compress_left -= len(data)
  521. if data and self._decrypter is not None:
  522. data = ''.join(map(self._decrypter, data))
  523. if self._compress_type == ZIP_STORED:
  524. self._update_crc(data, eof=(self._compress_left==0))
  525. self._readbuffer = self._readbuffer[self._offset:] + data
  526. self._offset = 0
  527. else:
  528. # Prepare deflated bytes for decompression.
  529. self._unconsumed += data
  530. # Handle unconsumed data.
  531. if (len(self._unconsumed) > 0 and n > len_readbuffer and
  532. self._compress_type == ZIP_DEFLATED):
  533. data = self._decompressor.decompress(
  534. self._unconsumed,
  535. max(n - len_readbuffer, self.MIN_READ_SIZE)
  536. )
  537. self._unconsumed = self._decompressor.unconsumed_tail
  538. eof = len(self._unconsumed) == 0 and self._compress_left == 0
  539. if eof:
  540. data += self._decompressor.flush()
  541. self._update_crc(data, eof=eof)
  542. self._readbuffer = self._readbuffer[self._offset:] + data
  543. self._offset = 0
  544. # Read from buffer.
  545. data = self._readbuffer[self._offset: self._offset + n]
  546. self._offset += len(data)
  547. return data
  548. class ZipFile:
  549. """ Class with methods to open, read, write, close, list zip files.
  550. z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False)
  551. file: Either the path to the file, or a file-like object.
  552. If it is a path, the file will be opened and closed by ZipFile.
  553. mode: The mode can be either read "r", write "w" or append "a".
  554. compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib).
  555. allowZip64: if True ZipFile will create files with ZIP64 extensions when
  556. needed, otherwise it will raise an exception when this would
  557. be necessary.
  558. """
  559. fp = None # Set here since __del__ checks it
  560. def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False):
  561. """Open the ZIP file with mode read "r", write "w" or append "a"."""
  562. if mode not in ("r", "w", "a"):
  563. raise RuntimeError('ZipFile() requires mode "r", "w", or "a"')
  564. if compression == ZIP_STORED:
  565. pass
  566. elif compression == ZIP_DEFLATED:
  567. if not zlib:
  568. raise RuntimeError,\
  569. "Compression requires the (missing) zlib module"
  570. else:
  571. raise RuntimeError, "That compression method is not supported"
  572. self._allowZip64 = allowZip64
  573. self._didModify = False
  574. self.debug = 0 # Level of printing: 0 through 3
  575. self.NameToInfo = {} # Find file info given name
  576. self.filelist = [] # List of ZipInfo instances for archive
  577. self.compression = compression # Method of compression
  578. self.mode = key = mode.replace('b', '')[0]
  579. self.pwd = None
  580. self.comment = ''
  581. # Check if we were passed a file-like object
  582. if isinstance(file, basestring):
  583. self._filePassed = 0
  584. self.filename = file
  585. modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
  586. try:
  587. self.fp = open(file, modeDict[mode])
  588. except IOError:
  589. if mode == 'a':
  590. mode = key = 'w'
  591. self.fp = open(file, modeDict[mode])
  592. else:
  593. raise
  594. else:
  595. self._filePassed = 1
  596. self.fp = file
  597. self.filename = getattr(file, 'name', None)
  598. if key == 'r':
  599. self._GetContents()
  600. elif key == 'w':
  601. # set the modified flag so central directory gets written
  602. # even if no files are added to the archive
  603. self._didModify = True
  604. elif key == 'a':
  605. try:
  606. # See if file is a zip file
  607. self._RealGetContents()
  608. # seek to start of directory and overwrite
  609. self.fp.seek(self.start_dir, 0)
  610. except BadZipfile:
  611. # file is not a zip file, just append
  612. self.fp.seek(0, 2)
  613. # set the modified flag so central directory gets written
  614. # even if no files are added to the archive
  615. self._didModify = True
  616. else:
  617. if not self._filePassed:
  618. self.fp.close()
  619. self.fp = None
  620. raise RuntimeError, 'Mode must be "r", "w" or "a"'
  621. def __enter__(self):
  622. return self
  623. def __exit__(self, type, value, traceback):
  624. self.close()
  625. def _GetContents(self):
  626. """Read the directory, making sure we close the file if the format
  627. is bad."""
  628. try:
  629. self._RealGetContents()
  630. except BadZipfile:
  631. if not self._filePassed:
  632. self.fp.close()
  633. self.fp = None
  634. raise
  635. def _RealGetContents(self):
  636. """Read in the table of contents for the ZIP file."""
  637. fp = self.fp
  638. try:
  639. endrec = _EndRecData(fp)
  640. except IOError:
  641. raise BadZipfile("File is not a zip file")
  642. if not endrec:
  643. raise BadZipfile, "File is not a zip file"
  644. if self.debug > 1:
  645. print endrec
  646. size_cd = endrec[_ECD_SIZE] # bytes in central directory
  647. offset_cd = endrec[_ECD_OFFSET] # offset of central directory
  648. self.comment = endrec[_ECD_COMMENT] # archive comment
  649. # "concat" is zero, unless zip was concatenated to another file
  650. concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
  651. if endrec[_ECD_SIGNATURE] == stringEndArchive64:
  652. # If Zip64 extension structures are present, account for them
  653. concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)
  654. if self.debug > 2:
  655. inferred = concat + offset_cd
  656. print "given, inferred, offset", offset_cd, inferred, concat
  657. # self.start_dir: Position of start of central directory
  658. self.start_dir = offset_cd + concat
  659. fp.seek(self.start_dir, 0)
  660. data = fp.read(size_cd)
  661. fp = cStringIO.StringIO(data)
  662. total = 0
  663. while total < size_cd:
  664. centdir = fp.read(sizeCentralDir)
  665. if centdir[0:4] != stringCentralDir:
  666. raise BadZipfile, "Bad magic number for central directory"
  667. centdir = struct.unpack(structCentralDir, centdir)
  668. if self.debug > 2:
  669. print centdir
  670. filename = fp.read(centdir[_CD_FILENAME_LENGTH])
  671. # Create ZipInfo instance to store file information
  672. x = ZipInfo(filename)
  673. x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
  674. x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
  675. x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
  676. (x.create_version, x.create_system, x.extract_version, x.reserved,
  677. x.flag_bits, x.compress_type, t, d,
  678. x.CRC, x.compress_size, x.file_size) = centdir[1:12]
  679. x.volume, x.internal_attr, x.external_attr = centdir[15:18]
  680. # Convert date/time code to (year, month, day, hour, min, sec)
  681. x._raw_time = t
  682. x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F,
  683. t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
  684. x._decodeExtra()
  685. x.header_offset = x.header_offset + concat
  686. x.filename = x._decodeFilename()
  687. self.filelist.append(x)
  688. self.NameToInfo[x.filename] = x
  689. # update total bytes read from central directory
  690. total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH]
  691. + centdir[_CD_EXTRA_FIELD_LENGTH]
  692. + centdir[_CD_COMMENT_LENGTH])
  693. if self.debug > 2:
  694. print "total", total
  695. def namelist(self):
  696. """Return a list of file names in the archive."""
  697. l = []
  698. for data in self.filelist:
  699. l.append(data.filename)
  700. return l
  701. def infolist(self):
  702. """Return a list of class ZipInfo instances for files in the
  703. archive."""
  704. return self.filelist
  705. def printdir(self):
  706. """Print a table of contents for the zip file."""
  707. print "%-46s %19s %12s" % ("File Name", "Modified ", "Size")
  708. for zinfo in self.filelist:
  709. date = "%d-%02d-%02d %02d:%02d:%02d" % zinfo.date_time[:6]
  710. print "%-46s %s %12d" % (zinfo.filename, date, zinfo.file_size)
  711. def testzip(self):
  712. """Read all the files and check the CRC."""
  713. chunk_size = 2 ** 20
  714. for zinfo in self.filelist:
  715. try:
  716. # Read by chunks, to avoid an OverflowError or a
  717. # MemoryError with very large embedded files.
  718. f = self.open(zinfo.filename, "r")
  719. while f.read(chunk_size): # Check CRC-32
  720. pass
  721. except BadZipfile:
  722. return zinfo.filename
  723. def getinfo(self, name):
  724. """Return the instance of ZipInfo given 'name'."""
  725. info = self.NameToInfo.get(name)
  726. if info is None:
  727. raise KeyError(
  728. 'There is no item named %r in the archive' % name)
  729. return info
  730. def setpassword(self, pwd):
  731. """Set default password for encrypted files."""
  732. self.pwd = pwd
  733. def read(self, name, pwd=None):
  734. """Return file bytes (as a string) for name."""
  735. return self.open(name, "r", pwd).read()
  736. def open(self, name, mode="r", pwd=None):
  737. """Return file-like object for 'name'."""
  738. if mode not in ("r", "U", "rU"):
  739. raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
  740. if not self.fp:
  741. raise RuntimeError, \
  742. "Attempt to read ZIP archive that was already closed"
  743. # Only open a new file for instances where we were not
  744. # given a file object in the constructor
  745. if self._filePassed:
  746. zef_file = self.fp
  747. else:
  748. zef_file = open(self.filename, 'rb')
  749. # Make sure we have an info object
  750. if isinstance(name, ZipInfo):
  751. # 'name' is already an info object
  752. zinfo = name
  753. else:
  754. # Get info object for name
  755. zinfo = self.getinfo(name)
  756. zef_file.seek(zinfo.header_offset, 0)
  757. # Skip the file header:
  758. fheader = zef_file.read(sizeFileHeader)
  759. if fheader[0:4] != stringFileHeader:
  760. raise BadZipfile, "Bad magic number for file header"
  761. fheader = struct.unpack(structFileHeader, fheader)
  762. fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
  763. if fheader[_FH_EXTRA_FIELD_LENGTH]:
  764. zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
  765. if fname != zinfo.orig_filename:
  766. raise BadZipfile, \
  767. 'File name in directory "%s" and header "%s" differ.' % (
  768. zinfo.orig_filename, fname)
  769. # check for encrypted flag & handle password
  770. is_encrypted = zinfo.flag_bits & 0x1
  771. zd = None
  772. if is_encrypted:
  773. if not pwd:
  774. pwd = self.pwd
  775. if not pwd:
  776. raise RuntimeError, "File %s is encrypted, " \
  777. "password required for extraction" % name
  778. zd = _ZipDecrypter(pwd)
  779. # The first 12 bytes in the cypher stream is an encryption header
  780. # used to strengthen the algorithm. The first 11 bytes are
  781. # completely random, while the 12th contains the MSB of the CRC,
  782. # or the MSB of the file time depending on the header type
  783. # and is used to check the correctness of the password.
  784. bytes = zef_file.read(12)
  785. h = map(zd, bytes[0:12])
  786. if zinfo.flag_bits & 0x8:
  787. # compare against the file type from extended local headers
  788. check_byte = (zinfo._raw_time >> 8) & 0xff
  789. else:
  790. # compare against the CRC otherwise
  791. check_byte = (zinfo.CRC >> 24) & 0xff
  792. if ord(h[11]) != check_byte:
  793. raise RuntimeError("Bad password for file", name)
  794. return ZipExtFile(zef_file, mode, zinfo, zd)
  795. def extract(self, member, path=None, pwd=None):
  796. """Extract a member from the archive to the current working directory,
  797. using its full name. Its file information is extracted as accurately
  798. as possible. `member' may be a filename or a ZipInfo object. You can
  799. specify a different directory using `path'.
  800. """
  801. if not isinstance(member, ZipInfo):
  802. member = self.getinfo(member)
  803. if path is None:
  804. path = os.getcwd()
  805. return self._extract_member(member, path, pwd)
  806. def extractall(self, path=None, members=None, pwd=None):
  807. """Extract all members from the archive to the current working
  808. directory. `path' specifies a different directory to extract to.
  809. `members' is optional and must be a subset of the list returned
  810. by namelist().
  811. """
  812. if members is None:
  813. members = self.namelist()
  814. for zipinfo in members:
  815. self.extract(zipinfo, path, pwd)
  816. def _extract_member(self, member, targetpath, pwd):
  817. """Extract the ZipInfo object 'member' to a physical
  818. file on the path targetpath.
  819. """
  820. # build the destination pathname, replacing
  821. # forward slashes to platform specific separators.
  822. # Strip trailing path separator, unless it represents the root.
  823. if (targetpath[-1:] in (os.path.sep, os.path.altsep)
  824. and len(os.path.splitdrive(targetpath)[1]) > 1):
  825. targetpath = targetpath[:-1]
  826. # don't include leading "/" from file name if present
  827. if member.filename[0] == '/':
  828. targetpath = os.path.join(targetpath, member.filename[1:])
  829. else:
  830. targetpath = os.path.join(targetpath, member.filename)
  831. targetpath = os.path.normpath(targetpath)
  832. # Create all upper directories if necessary.
  833. upperdirs = os.path.dirname(targetpath)
  834. if upperdirs and not os.path.exists(upperdirs):
  835. os.makedirs(upperdirs)
  836. if member.filename[-1] == '/':
  837. if not os.path.isdir(targetpath):
  838. os.mkdir(targetpath)
  839. return targetpath
  840. source = self.open(member, pwd=pwd)
  841. target = file(targetpath, "wb")
  842. shutil.copyfileobj(source, target)
  843. source.close()
  844. target.close()
  845. return targetpath
  846. def _writecheck(self, zinfo):
  847. """Check for errors before writing a file to the archive."""
  848. if zinfo.filename in self.NameToInfo:
  849. if self.debug: # Warning for duplicate names
  850. print "Duplicate name:", zinfo.filename
  851. if self.mode not in ("w", "a"):
  852. raise RuntimeError, 'write() requires mode "w" or "a"'
  853. if not self.fp:
  854. raise RuntimeError, \
  855. "Attempt to write ZIP archive that was already closed"
  856. if zinfo.compress_type == ZIP_DEFLATED and not zlib:
  857. raise RuntimeError, \
  858. "Compression requires the (missing) zlib module"
  859. if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED):
  860. raise RuntimeError, \
  861. "That compression method is not supported"
  862. if zinfo.file_size > ZIP64_LIMIT:
  863. if not self._allowZip64:
  864. raise LargeZipFile("Filesize would require ZIP64 extensions")
  865. if zinfo.header_offset > ZIP64_LIMIT:
  866. if not self._allowZip64:
  867. raise LargeZipFile("Zipfile size would require ZIP64 extensions")
  868. def write(self, filename, arcname=None, compress_type=None):
  869. """Put the bytes from filename into the archive under the name
  870. arcname."""
  871. if not self.fp:
  872. raise RuntimeError(
  873. "Attempt to write to ZIP archive that was already closed")
  874. st = os.stat(filename)
  875. isdir = stat.S_ISDIR(st.st_mode)
  876. mtime = time.localtime(st.st_mtime)
  877. date_time = mtime[0:6]
  878. # Create ZipInfo instance to store file information
  879. if arcname is None:
  880. arcname = filename
  881. arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
  882. while arcname[0] in (os.sep, os.altsep):
  883. arcname = arcname[1:]
  884. if isdir:
  885. arcname += '/'
  886. zinfo = ZipInfo(arcname, date_time)
  887. zinfo.external_attr = (st[0] & 0xFFFF) << 16L # Unix attributes
  888. if compress_type is None:
  889. zinfo.compress_type = self.compression
  890. else:
  891. zinfo.compress_type = compress_type
  892. zinfo.file_size = st.st_size
  893. zinfo.flag_bits = 0x00
  894. zinfo.header_offset = self.fp.tell() # Start of header bytes
  895. self._writecheck(zinfo)
  896. self._didModify = True
  897. if isdir:
  898. zinfo.file_size = 0
  899. zinfo.compress_size = 0
  900. zinfo.CRC = 0
  901. self.filelist.append(zinfo)
  902. self.NameToInfo[zinfo.filename] = zinfo
  903. self.fp.write(zinfo.FileHeader())
  904. return
  905. with open(filename, "rb") as fp:
  906. # Must overwrite CRC and sizes with correct data later
  907. zinfo.CRC = CRC = 0
  908. zinfo.compress_size = compress_size = 0
  909. zinfo.file_size = file_size = 0
  910. self.fp.write(zinfo.FileHeader())
  911. if zinfo.compress_type == ZIP_DEFLATED:
  912. cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
  913. zlib.DEFLATED, -15)
  914. else:
  915. cmpr = None
  916. while 1:
  917. buf = fp.read(1024 * 8)
  918. if not buf:
  919. break
  920. file_size = file_size + len(buf)
  921. CRC = crc32(buf, CRC) & 0xffffffff
  922. if cmpr:
  923. buf = cmpr.compress(buf)
  924. compress_size = compress_size + len(buf)
  925. self.fp.write(buf)
  926. if cmpr:
  927. buf = cmpr.flush()
  928. compress_size = compress_size + len(buf)
  929. self.fp.write(buf)
  930. zinfo.compress_size = compress_size
  931. else:
  932. zinfo.compress_size = file_size
  933. zinfo.CRC = CRC
  934. zinfo.file_size = file_size
  935. # Seek backwards and write CRC and file sizes
  936. position = self.fp.tell() # Preserve current position in file
  937. self.fp.seek(zinfo.header_offset + 14, 0)
  938. self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
  939. zinfo.file_size))
  940. self.fp.seek(position, 0)
  941. self.filelist.append(zinfo)
  942. self.NameToInfo[zinfo.filename] = zinfo
  943. def writestr(self, zinfo_or_arcname, bytes, compress_type=None):
  944. """Write a file into the archive. The contents is the string
  945. 'bytes'. 'zinfo_or_arcname' is either a ZipInfo instance or
  946. the name of the file in the archive."""
  947. if not isinstance(zinfo_or_arcname, ZipInfo):
  948. zinfo = ZipInfo(filename=zinfo_or_arcname,
  949. date_time=time.localtime(time.time())[:6])
  950. zinfo.compress_type = self.compression
  951. zinfo.external_attr = 0600 << 16
  952. else:
  953. zinfo = zinfo_or_arcname
  954. if not self.fp:
  955. raise RuntimeError(
  956. "Attempt to write to ZIP archive that was already closed")
  957. if compress_type is not None:
  958. zinfo.compress_type = compress_type
  959. zinfo.file_size = len(bytes) # Uncompressed size
  960. zinfo.header_offset = self.fp.tell() # Start of header bytes
  961. self._writecheck(zinfo)
  962. self._didModify = True
  963. zinfo.CRC = crc32(bytes) & 0xffffffff # CRC-32 checksum
  964. if zinfo.compress_type == ZIP_DEFLATED:
  965. co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
  966. zlib.DEFLATED, -15)
  967. bytes = co.compress(bytes) + co.flush()
  968. zinfo.compress_size = len(bytes) # Compressed size
  969. else:
  970. zinfo.compress_size = zinfo.file_size
  971. zinfo.header_offset = self.fp.tell() # Start of header bytes
  972. self.fp.write(zinfo.FileHeader())
  973. self.fp.write(bytes)
  974. self.fp.flush()
  975. if zinfo.flag_bits & 0x08:
  976. # Write CRC and file sizes after the file data
  977. self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
  978. zinfo.file_size))
  979. self.filelist.append(zinfo)
  980. self.NameToInfo[zinfo.filename] = zinfo
  981. def __del__(self):
  982. """Call the "close()" method in case the user forgot."""
  983. self.close()
  984. def close(self):
  985. """Close the file, and for mode "w" and "a" write the ending
  986. records."""
  987. if self.fp is None:
  988. return
  989. if self.mode in ("w", "a") and self._didModify: # write ending records
  990. count = 0
  991. pos1 = self.fp.tell()
  992. for zinfo in self.filelist: # write central directory
  993. count = count + 1
  994. dt = zinfo.date_time
  995. dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
  996. dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
  997. extra = []
  998. if zinfo.file_size > ZIP64_LIMIT \
  999. or zinfo.compress_size > ZIP64_LIMIT:
  1000. extra.append(zinfo.file_size)
  1001. extra.append(zinfo.compress_size)
  1002. file_size = 0xffffffff
  1003. compress_size = 0xffffffff
  1004. else:
  1005. file_size = zinfo.file_size
  1006. compress_size = zinfo.compress_size
  1007. if zinfo.header_offset > ZIP64_LIMIT:
  1008. extra.append(zinfo.header_offset)
  1009. header_offset = 0xffffffffL
  1010. else:
  1011. header_offset = zinfo.header_offset
  1012. extra_data = zinfo.extra
  1013. if extra:
  1014. # Append a ZIP64 field to the extra's
  1015. extra_data = struct.pack(
  1016. '<HH' + 'Q'*len(extra),
  1017. 1, 8*len(extra), *extra) + extra_data
  1018. extract_version = max(45, zinfo.extract_version)
  1019. create_version = max(45, zinfo.create_version)
  1020. else:
  1021. extract_version = zinfo.extract_version
  1022. create_version = zinfo.create_version
  1023. try:
  1024. filename, flag_bits = zinfo._encodeFilenameFlags()
  1025. centdir = struct.pack(structCentralDir,
  1026. stringCentralDir, create_version,
  1027. zinfo.create_system, extract_version, zinfo.reserved,
  1028. flag_bits, zinfo.compress_type, dostime, dosdate,
  1029. zinfo.CRC, compress_size, file_size,
  1030. len(filename), len(extra_data), len(zinfo.comment),
  1031. 0, zinfo.internal_attr, zinfo.external_attr,
  1032. header_offset)
  1033. except DeprecationWarning:
  1034. print >>sys.stderr, (structCentralDir,
  1035. stringCentralDir, create_version,
  1036. zinfo.create_system, extract_version, zinfo.reserved,
  1037. zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
  1038. zinfo.CRC, compress_size, file_size,
  1039. len(zinfo.filename), len(extra_data), len(zinfo.comment),
  1040. 0, zinfo.internal_attr, zinfo.external_attr,
  1041. header_offset)
  1042. raise
  1043. self.fp.write(centdir)
  1044. self.fp.write(filename)
  1045. self.fp.write(extra_data)
  1046. self.fp.write(zinfo.comment)
  1047. pos2 = self.fp.tell()
  1048. # Write end-of-zip-archive record
  1049. centDirCount = count
  1050. centDirSize = pos2 - pos1
  1051. centDirOffset = pos1
  1052. if (centDirCount >= ZIP_FILECOUNT_LIMIT or
  1053. centDirOffset > ZIP64_LIMIT or
  1054. centDirSize > ZIP64_LIMIT):
  1055. # Need to write the ZIP64 end-of-archive records
  1056. zip64endrec = struct.pack(
  1057. structEndArchive64, stringEndArchive64,
  1058. 44, 45, 45, 0, 0, centDirCount, centDirCount,
  1059. centDirSize, centDirOffset)
  1060. self.fp.write(zip64endrec)
  1061. zip64locrec = struct.pack(
  1062. structEndArchive64Locator,
  1063. stringEndArchive64Locator, 0, pos2, 1)
  1064. self.fp.write(zip64locrec)
  1065. centDirCount = min(centDirCount, 0xFFFF)
  1066. centDirSize = min(centDirSize, 0xFFFFFFFF)
  1067. centDirOffset = min(centDirOffset, 0xFFFFFFFF)
  1068. # check for valid comment length
  1069. if len(self.comment) >= ZIP_MAX_COMMENT:
  1070. if self.debug > 0:
  1071. msg = 'Archive comment is too long; truncating to %d bytes' \
  1072. % ZIP_MAX_COMMENT
  1073. self.comment = self.comment[:ZIP_MAX_COMMENT]
  1074. endrec = struct.pack(structEndArchive, stringEndArchive,
  1075. 0, 0, centDirCount, centDirCount,
  1076. centDirSize, centDirOffset, len(self.comment))
  1077. self.fp.write(endrec)
  1078. self.fp.write(self.comment)
  1079. self.fp.flush()
  1080. if not self._filePassed:
  1081. self.fp.close()
  1082. self.fp = None
  1083. class PyZipFile(ZipFile):
  1084. """Class to create ZIP archives with Python library files and packages."""
  1085. def writepy(self, pathname, basename = ""):
  1086. """Add all files from "pathname" to the ZIP archive.
  1087. If pathname is a package directory, search the directory and
  1088. all package subdirectories recursively for all *.py and enter
  1089. the modules into the archive. If pathname is a plain
  1090. directory, listdir *.py and enter all modules. Else, pathname
  1091. must be a Python *.py file and the module will be put into the
  1092. archive. Added modules are always module.pyo or module.pyc.
  1093. This method will compile the module.py into module.pyc if
  1094. necessary.
  1095. """
  1096. dir, name = os.path.split(pathname)
  1097. if os.path.isdir(pathname):
  1098. initname = os.path.join(pathname, "__init__.py")
  1099. if os.path.isfile(initname):
  1100. # This is a package directory, add it
  1101. if basename:
  1102. basename = "%s/%s" % (basename, name)
  1103. else:
  1104. basename = name
  1105. if self.debug:
  1106. print "Adding package in", pathname, "as", basename
  1107. fname, arcname = self._get_codename(initname[0:-3], basename)
  1108. if self.debug:
  1109. print "Adding", arcname
  1110. self.write(fname, arcname)
  1111. dirlist = os.listdir(pathname)
  1112. dirlist.remove("__init__.py")
  1113. # Add all *.py files and package subdirectories
  1114. for filename in dirlist:
  1115. path = os.path.join(pathname, filename)
  1116. root, ext = os.path.splitext(filename)
  1117. if os.path.isdir(path):
  1118. if os.path.isfile(os.path.join(path, "__init__.py")):
  1119. # This is a package directory, add it
  1120. self.writepy(path, basename) # Recursive call
  1121. elif ext == ".py":
  1122. fname, arcname = self._get_codename(path[0:-3],
  1123. basename)
  1124. if self.debug:
  1125. print "Adding", arcname
  1126. self.write(fname, arcname)
  1127. else:
  1128. # This is NOT a package directory, add its files at top level
  1129. if self.debug:
  1130. print "Adding files from directory", pathname
  1131. for filename in os.listdir(pathname):
  1132. path = os.path.join(pathname, filename)
  1133. root, ext = os.path.splitext(filename)
  1134. if ext == ".py":

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