ZipPythonDir Namespace Reference

Classes

class  ZipdirError
 Class for generic exception coming from the zipdir() function. More...
 

Functions

def _zipChanges (directory, infolist)
 Collect the changes to be applied to the zip file. More...
 
def checkEncoding (fileObj)
 
def zipdir
 Make a zip file out of a directory containing python modules. More...
 
def main
 Main function of the script. More...
 

Function Documentation

def ZipPythonDir._zipChanges (   directory,
  infolist 
)
private

Collect the changes to be applied to the zip file.

Parameters
directorydirectory to be packed in the zip file
infolistlist of ZipInfo objects already contained in the zip archive
Returns
: tuple of (added, modified, untouched, removed) entries in the directory with respect to the zip file

Definition at line 30 of file ZipPythonDir.py.

30 def _zipChanges(directory, infolist):
31  # gets the dates of the files in the zip archive
32  infos = {}
33  for i in infolist:
34  fn = i.filename
35  if fn.endswith(".pyc"):
36  fn = fn[:-1]
37  infos[fn] = i.date_time
38 
39  # gets the changes
40  added = []
41  modified = []
42  untouched = []
43  removed = []
44  all_files = set()
45 
46  log = logging.getLogger("zipdir")
47  dirlen = len(directory) + 1
48  for root, dirs, files in os.walk(directory):
49  if "lib-dynload" in dirs:
50  # exclude the directory containing binary modules
51  dirs.remove("lib-dynload")
52  arcdir = root[dirlen:]
53  for f in files:
54  ext = os.path.splitext(f)[1]
55  if ext == ".py": # extensions that can enter the zip file
56  filename = os.path.join(arcdir, f)
57  all_files.add(filename)
58  if filename not in infos:
59  action = "A"
60  added.append(filename)
61  else:
62  filetime = time.localtime(os.stat(os.path.join(directory,filename))[stat.ST_MTIME])[:6]
63  if filetime > infos[filename]:
64  action = "M"
65  modified.append(filename)
66  else:
67  action = "U"
68  untouched.append(filename)
69  if action in ['U']:
70  log.debug(" %s -> %s", action, filename)
71  else:
72  log.info(" %s -> %s", action, filename)
73  # cases that can be ignored
74  elif (ext not in [".pyc", ".pyo", ".stamp", ".cmtref", ".confdb"]
75  and not f.startswith('.__afs')):
76  raise ZipdirError("Cannot add '%s' to the zip file, only '.py' are allowed." % os.path.join(arcdir, f))
77  # check for removed files
78  for filename in infos:
79  if filename not in all_files:
80  removed.append(filename)
81  log.info(" %s -> %s", "R", filename)
82  return (added, modified, untouched, removed)
83 
Class for generic exception coming from the zipdir() function.
Definition: ZipPythonDir.py:20
def _zipChanges(directory, infolist)
Collect the changes to be applied to the zip file.
Definition: ZipPythonDir.py:30
def ZipPythonDir.checkEncoding (   fileObj)
Check that a file honors the declared encoding (default ASCII for Python 2
and UTF-8 for Python 3).

Raises a UnicodeDecodeError in case of decoding problems and LookupError if
the specified codec does not exists.

See http://www.python.org/dev/peps/pep-0263/

Definition at line 84 of file ZipPythonDir.py.

84 def checkEncoding(fileObj):
85  '''
86  Check that a file honors the declared encoding (default ASCII for Python 2
87  and UTF-8 for Python 3).
88 
89  Raises a UnicodeDecodeError in case of decoding problems and LookupError if
90  the specified codec does not exists.
91 
92  See http://www.python.org/dev/peps/pep-0263/
93  '''
94  from itertools import islice
95 
96  # default encoding
97  if sys.version_info[0] <= 2:
98  enc = 'ascii'
99  else:
100  enc = 'utf-8'
101 
102  # find the encoding of the file, if specified (in the first two lines)
103  enc_exp = re.compile(r"coding[:=]\s*([-\w.]+)")
104  for l in islice(fileObj, 2):
105  m = enc_exp.search(l)
106  if m:
107  enc = m.group(1)
108  break
109 
110  if hasattr(fileObj, 'name'):
111  logging.getLogger('checkEncoding').debug('checking encoding %s on %s',
112  enc, fileObj.name)
113  else:
114  logging.getLogger('checkEncoding').debug('checking encoding %s on file object',
115  enc)
116  # try to read the file with the declared encoding
117  fileObj.seek(0)
118  codecs.getreader(enc)(fileObj).read()
119 
120 
def checkEncoding(fileObj)
Definition: ZipPythonDir.py:84
def ZipPythonDir.main (   argv = None)

Main function of the script.

Parse arguments and call zipdir() for each directory passed as argument

Definition at line 182 of file ZipPythonDir.py.

182 def main(argv = None):
183  from optparse import OptionParser
184  parser = OptionParser(usage = "%prog [options] directory1 [directory2 ...]")
185  parser.add_option("--no-pyc", action = "store_true",
186  help = "copy the .py files without pre-compiling them")
187  parser.add_option("--quiet", action = "store_true",
188  help = "do not print info messages")
189  parser.add_option("--debug", action = "store_true",
190  help = "print debug messages (has priority over --quiet)")
191 
192  if argv is None:
193  argv = sys.argv
194  opts, args = parser.parse_args(argv[1:])
195 
196  if not args:
197  parser.error("Specify at least one directory to zip")
198 
199  # Initialize the logging module
200  level = logging.INFO
201  if opts.quiet:
202  level = logging.WARNING
203  if opts.debug:
204  level = logging.DEBUG
205  logging.basicConfig(level = level)
206 
207  if "GAUDI_BUILD_LOCK" in os.environ:
208  _scopedLock = locker.LockFile(os.environ["GAUDI_BUILD_LOCK"], temporary = True)
209  # zip all the directories passed as arguments
210  for d in args:
211  zipdir(d, opts.no_pyc)
212 
Lock a file.
Definition: locker.py:63
def zipdir
Make a zip file out of a directory containing python modules.
def main
Main function of the script.
def ZipPythonDir.zipdir (   directory,
  no_pyc = False 
)

Make a zip file out of a directory containing python modules.

Definition at line 122 of file ZipPythonDir.py.

122 def zipdir(directory, no_pyc = False):
123  log = logging.getLogger("zipdir")
124  if not os.path.isdir(directory):
125  raise OSError(20, "Not a directory", directory)
126  msg = "Zipping directory '%s'"
127  if no_pyc:
128  msg += " (without pre-compilation)"
129  log.info(msg, directory)
130  filename = os.path.realpath(directory + ".zip")
131 
132  # Open the file in read an update mode
133  if os.path.exists(filename):
134  zipFile = open(filename, "r+b")
135  else:
136  # If the file does not exist, we need to create it.
137  # "append mode" ensures that, in case of two processes trying to
138  # create the file, they do not truncate each other file
139  zipFile = open(filename, "ab")
140 
141  locker.lock(zipFile)
142  try:
143  if zipfile.is_zipfile(filename):
144  infolist = zipfile.ZipFile(filename).infolist()
145  else:
146  infolist = []
147  (added, modified, untouched, removed) = _zipChanges(directory, infolist)
148  if added or modified or removed:
149  tempBuf = StringIO()
150  z = zipfile.PyZipFile(tempBuf, "w", zipfile.ZIP_DEFLATED)
151  for f in added + modified + untouched:
152  src = os.path.join(directory, f)
153  checkEncoding(open(src, 'rb'))
154  if no_pyc:
155  log.debug("adding '%s'", f)
156  z.write(src, f)
157  else:
158  # Remove the .pyc file to always force a re-compilation
159  if os.path.exists(src + 'c'):
160  log.debug("removing old .pyc for '%s'", f)
161  os.remove(src + 'c')
162  log.debug("adding '%s'", f)
163  z.writepy(src, os.path.dirname(f))
164  z.close()
165  zipFile.seek(0)
166  zipFile.write(tempBuf.getvalue())
167  zipFile.truncate()
168  log.info("File '%s' closed", filename)
169  else:
170  log.info("Nothing to do on '%s'", filename)
171  except UnicodeDecodeError, x:
172  log.error("Wrong encoding in file '%s':", src)
173  log.error(" %s", x)
174  log.error("Probably you forgot the line '# -*- coding: utf-8 -*-'")
175  sys.exit(1)
176  finally:
177  locker.unlock(zipFile)
178  zipFile.close()
179 
def lock(file)
Definition: locker.py:16
def zipdir
Make a zip file out of a directory containing python modules.
def checkEncoding(fileObj)
Definition: ZipPythonDir.py:84
def _zipChanges(directory, infolist)
Collect the changes to be applied to the zip file.
Definition: ZipPythonDir.py:30
def unlock(file)
Definition: locker.py:34