f564abbd03629b67f69d294f5af1352069032168
[profile/ivi/python.git] / Lib / compileall.py
1 """Module/script to "compile" all .py files to .pyc (or .pyo) file.
2
3 When called as a script with arguments, this compiles the directories
4 given as arguments recursively; the -l option prevents it from
5 recursing into directories.
6
7 Without arguments, if compiles all modules on sys.path, without
8 recursing into subdirectories.  (Even though it should do so for
9 packages -- for now, you'll have to deal with packages separately.)
10
11 See module py_compile for details of the actual byte-compilation.
12
13 """
14 import os
15 import sys
16 import py_compile
17 import struct
18 import imp
19
20 __all__ = ["compile_dir","compile_file","compile_path"]
21
22 def compile_dir(dir, maxlevels=10, ddir=None,
23                 force=0, rx=None, quiet=0):
24     """Byte-compile all modules in the given directory tree.
25
26     Arguments (only dir is required):
27
28     dir:       the directory to byte-compile
29     maxlevels: maximum recursion level (default 10)
30     ddir:      if given, purported directory name (this is the
31                directory name that will show up in error messages)
32     force:     if 1, force compilation, even if timestamps are up-to-date
33     quiet:     if 1, be quiet during compilation
34
35     """
36     if not quiet:
37         print 'Listing', dir, '...'
38     try:
39         names = os.listdir(dir)
40     except os.error:
41         print "Can't list", dir
42         names = []
43     names.sort()
44     success = 1
45     for name in names:
46         fullname = os.path.join(dir, name)
47         if ddir is not None:
48             dfile = os.path.join(ddir, name)
49         else:
50             dfile = None
51         if not os.path.isdir(fullname):
52             if not compile_file(fullname, ddir, force, rx, quiet):
53                 success = 0
54         elif maxlevels > 0 and \
55              name != os.curdir and name != os.pardir and \
56              os.path.isdir(fullname) and \
57              not os.path.islink(fullname):
58             if not compile_dir(fullname, maxlevels - 1, dfile, force, rx,
59                                quiet):
60                 success = 0
61     return success
62
63 def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):
64     """Byte-compile file.
65     file:      the file to byte-compile
66     ddir:      if given, purported directory name (this is the
67                directory name that will show up in error messages)
68     force:     if 1, force compilation, even if timestamps are up-to-date
69     quiet:     if 1, be quiet during compilation
70
71     """
72
73     success = 1
74     name = os.path.basename(fullname)
75     if ddir is not None:
76         dfile = os.path.join(ddir, name)
77     else:
78         dfile = None
79     if rx is not None:
80         mo = rx.search(fullname)
81         if mo:
82             return success
83     if os.path.isfile(fullname):
84         head, tail = name[:-3], name[-3:]
85         if tail == '.py':
86             if not force:
87                 try:
88                     mtime = int(os.stat(fullname).st_mtime)
89                     expect = struct.pack('<4sl', imp.get_magic(), mtime)
90                     cfile = fullname + (__debug__ and 'c' or 'o')
91                     with open(cfile, 'rb') as chandle:
92                         actual = chandle.read(8)
93                     if expect == actual:
94                         return success
95                 except IOError:
96                     pass
97             if not quiet:
98                 print 'Compiling', fullname, '...'
99             try:
100                 ok = py_compile.compile(fullname, None, dfile, True)
101             except py_compile.PyCompileError,err:
102                 if quiet:
103                     print 'Compiling', fullname, '...'
104                 print err.msg
105                 success = 0
106             except IOError, e:
107                 print "Sorry", e
108                 success = 0
109             else:
110                 if ok == 0:
111                     success = 0
112     return success
113
114 def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0):
115     """Byte-compile all module on sys.path.
116
117     Arguments (all optional):
118
119     skip_curdir: if true, skip current directory (default true)
120     maxlevels:   max recursion level (default 0)
121     force: as for compile_dir() (default 0)
122     quiet: as for compile_dir() (default 0)
123
124     """
125     success = 1
126     for dir in sys.path:
127         if (not dir or dir == os.curdir) and skip_curdir:
128             print 'Skipping current directory'
129         else:
130             success = success and compile_dir(dir, maxlevels, None,
131                                               force, quiet=quiet)
132     return success
133
134 def expand_args(args, flist):
135     """read names in flist and append to args"""
136     expanded = args[:]
137     if flist:
138         try:
139             if flist == '-':
140                 fd = sys.stdin
141             else:
142                 fd = open(flist)
143             while 1:
144                 line = fd.readline()
145                 if not line:
146                     break
147                 expanded.append(line[:-1])
148         except IOError:
149             print "Error reading file list %s" % flist
150             raise
151     return expanded
152
153 def main():
154     """Script main program."""
155     import getopt
156     try:
157         opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:')
158     except getopt.error, msg:
159         print msg
160         print "usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \
161               "[-x regexp] [-i list] [directory|file ...]"
162         print "-l: don't recurse down"
163         print "-f: force rebuild even if timestamps are up-to-date"
164         print "-q: quiet operation"
165         print "-d destdir: purported directory name for error messages"
166         print "   if no directory arguments, -l sys.path is assumed"
167         print "-x regexp: skip files matching the regular expression regexp"
168         print "   the regexp is searched for in the full path of the file"
169         print "-i list: expand list with its content (file and directory names)"
170         sys.exit(2)
171     maxlevels = 10
172     ddir = None
173     force = 0
174     quiet = 0
175     rx = None
176     flist = None
177     for o, a in opts:
178         if o == '-l': maxlevels = 0
179         if o == '-d': ddir = a
180         if o == '-f': force = 1
181         if o == '-q': quiet = 1
182         if o == '-x':
183             import re
184             rx = re.compile(a)
185         if o == '-i': flist = a
186     if ddir:
187         if len(args) != 1 and not os.path.isdir(args[0]):
188             print "-d destdir require exactly one directory argument"
189             sys.exit(2)
190     success = 1
191     try:
192         if args or flist:
193             try:
194                 if flist:
195                     args = expand_args(args, flist)
196             except IOError:
197                 success = 0
198             if success:
199                 for arg in args:
200                     if os.path.isdir(arg):
201                         if not compile_dir(arg, maxlevels, ddir,
202                                            force, rx, quiet):
203                             success = 0
204                     else:
205                         if not compile_file(arg, ddir, force, rx, quiet):
206                             success = 0
207         else:
208             success = compile_path()
209     except KeyboardInterrupt:
210         print "\n[interrupt]"
211         success = 0
212     return success
213
214 if __name__ == '__main__':
215     exit_status = int(not main())
216     sys.exit(exit_status)