14 from StringIO
import StringIO
32 if fn.endswith(
".pyc"):
34 infos[fn] = i.date_time
43 log = logging.getLogger(
"zipdir")
44 dirlen = len(directory) + 1
45 for root, dirs, files
in os.walk(directory):
46 if "lib-dynload" in dirs:
48 dirs.remove(
"lib-dynload")
49 arcdir = root[dirlen:]
51 ext = os.path.splitext(f)[1]
53 filename = os.path.join(arcdir, f)
54 all_files.add(filename)
55 if filename
not in infos:
57 added.append(filename)
59 filetime = time.localtime(os.stat(os.path.join(directory,filename))[stat.ST_MTIME])[:6]
60 if filetime > infos[filename]:
62 modified.append(filename)
65 untouched.append(filename) 67 log.debug(" %s -> %s", action, filename)
69 log.info(
" %s -> %s", action, filename)
71 elif (ext
not in [
".pyc",
".pyo",
".stamp",
".cmtref",
".confdb"]
72 and not f.startswith(
'.__afs')):
73 raise ZipdirError(
"Cannot add '%s' to the zip file, only '.py' are allowed." % os.path.join(arcdir, f))
75 for filename
in infos:
76 if filename
not in all_files:
77 removed.append(filename)
78 log.info(
" %s -> %s",
"R", filename) 79 return (added, modified, untouched, removed)
83 Check that a file honors the declared encoding (default ASCII for Python 2 84 and UTF-8 for Python 3). 86 Raises a UnicodeDecodeError in case of decoding problems and LookupError if 87 the specified codec does not exists. 89 See http://www.python.org/dev/peps/pep-0263/ 91 from itertools
import islice
94 if sys.version_info[0] <= 2:
100 enc_exp = re.compile(
r"coding[:=]\s*([-\w.]+)")
101 for l
in islice(fileObj, 2):
102 m = enc_exp.search(l)
107 if hasattr(fileObj,
'name'):
108 logging.getLogger(
'checkEncoding').debug(
'checking encoding %s on %s',
111 logging.getLogger(
'checkEncoding').debug(
'checking encoding %s on file object',
115 codecs.getreader(enc)(fileObj).read()
120 filename = os.path.realpath(directory +
".zip")
121 log = logging.getLogger(
"zipdir")
122 if not os.path.isdir(directory):
123 log.warning(
'directory %s missing, creating empty .zip file', directory)
124 open(filename,
"ab").close()
126 msg =
"Zipping directory '%s'" 128 msg +=
" (without pre-compilation)" 129 log.info(msg, directory)
132 if os.path.exists(filename):
133 zipFile = open(filename,
"r+b")
138 zipFile = open(filename,
"ab")
141 if zipfile.is_zipfile(filename):
142 infolist = zipfile.ZipFile(filename).infolist()
145 (added, modified, untouched, removed) =
_zipChanges(directory, infolist)
146 if added
or modified
or removed:
148 z = zipfile.PyZipFile(tempBuf,
"w", zipfile.ZIP_DEFLATED)
149 for f
in added + modified + untouched:
150 src = os.path.join(directory, f)
153 log.debug(
"adding '%s'", f)
157 if os.path.exists(src +
'c'):
158 log.debug(
"removing old .pyc for '%s'", f)
160 log.debug(
"adding '%s'", f)
161 z.writepy(src, os.path.dirname(f))
164 zipFile.write(tempBuf.getvalue())
166 log.info(
"File '%s' closed", filename)
168 log.info(
"Nothing to do on '%s'", filename)
169 except UnicodeDecodeError, x:
170 log.error(
"Wrong encoding in file '%s':", src)
172 log.error(
"Probably you forgot the line '# -*- coding: utf-8 -*-'")
180 from optparse
import OptionParser
181 parser = OptionParser(usage =
"%prog [options] directory1 [directory2 ...]")
182 parser.add_option(
"--no-pyc", action =
"store_true",
183 help =
"copy the .py files without pre-compiling them")
184 parser.add_option(
"--quiet", action =
"store_true",
185 help =
"do not print info messages")
186 parser.add_option(
"--debug", action =
"store_true",
187 help =
"print debug messages (has priority over --quiet)")
191 opts, args = parser.parse_args(argv[1:])
194 parser.error(
"Specify at least one directory to zip")
199 level = logging.WARNING
201 level = logging.DEBUG
202 logging.basicConfig(level=level)
208 if __name__ ==
'__main__':
def checkEncoding(fileObj)
Class for generic exception coming from the zipdir() function.
def main(argv=None)
Main function of the script.
def _zipChanges(directory, infolist)
Collect the changes to be applied to the zip file.
def zipdir(directory, no_pyc=False)
Make a zip file out of a directory containing python modules.