compileall.py revision 0c5958b1636c47ed7c284f859c8e805fd06a0e6
10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"""Module/script to byte-compile all .py files to .pyc (or .pyo) files. 20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiWhen called as a script with arguments, this compiles the directories 40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yigiven as arguments recursively; the -l option prevents it from 50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yirecursing into directories. 60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiWithout arguments, if compiles all modules on sys.path, without 80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yirecursing into subdirectories. (Even though it should do so for 90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yipackages -- for now, you'll have to deal with packages separately.) 100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSee module py_compile for details of the actual byte-compilation. 120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport os 140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport sys 150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport py_compile 160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport struct 170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport imp 180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi__all__ = ["compile_dir","compile_file","compile_path"] 200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef compile_dir(dir, maxlevels=10, ddir=None, 220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi force=0, rx=None, quiet=0): 230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Byte-compile all modules in the given directory tree. 240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Arguments (only dir is required): 260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dir: the directory to byte-compile 280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi maxlevels: maximum recursion level (default 10) 290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ddir: the directory that will be prepended to the path to the 300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi file as it is compiled into each byte-code file. 310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi force: if 1, force compilation, even if timestamps are up-to-date 320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi quiet: if 1, be quiet during compilation 330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """ 340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not quiet: 350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'Listing', dir, '...' 360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi names = os.listdir(dir) 380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except os.error: 390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "Can't list", dir 400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi names = [] 410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi names.sort() 420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 1 430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for name in names: 440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fullname = os.path.join(dir, name) 450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if sys.platform == "win32" and sys.version.find("GCC") >= 0: 460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fullname = fullname.replace('\\','/') 470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if ddir is not None: 480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dfile = os.path.join(ddir, name) 490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dfile = None 510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not os.path.isdir(fullname): 520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not compile_file(fullname, ddir, force, rx, quiet): 530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi elif maxlevels > 0 and \ 550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi name != os.curdir and name != os.pardir and \ 560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi os.path.isdir(fullname) and \ 570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi not os.path.islink(fullname): 580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not compile_dir(fullname, maxlevels - 1, dfile, force, rx, 590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi quiet): 600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return success 620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef compile_file(fullname, ddir=None, force=0, rx=None, quiet=0): 640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Byte-compile one file. 650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Arguments (only fullname is required): 670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fullname: the file to byte-compile 690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ddir: if given, the directory name compiled in to the 700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi byte-code file. 710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi force: if 1, force compilation, even if timestamps are up-to-date 720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi quiet: if 1, be quiet during compilation 730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """ 740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 1 750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi name = os.path.basename(fullname) 760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if ddir is not None: 770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dfile = os.path.join(ddir, name) 780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dfile = None 800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if rx is not None: 810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi mo = rx.search(fullname) 820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if mo: 830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return success 840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if os.path.isfile(fullname): 850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi head, tail = name[:-3], name[-3:] 860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if tail == '.py': 870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not force: 880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi mtime = int(os.stat(fullname).st_mtime) 900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi expect = struct.pack('<4sl', imp.get_magic(), mtime) 910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi cfile = fullname + (__debug__ and 'c' or 'o') 920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi with open(cfile, 'rb') as chandle: 930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi actual = chandle.read(8) 940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if expect == actual: 950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return success 960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except IOError: 970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not quiet: 990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'Compiling', fullname, '...' 1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ok = py_compile.compile(fullname, None, dfile, True) 1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except py_compile.PyCompileError,err: 1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if quiet: 1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'Compiling', fullname, '...' 1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print err.msg 1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except IOError, e: 1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "Sorry", e 1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if ok == 0: 1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return success 1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0): 1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Byte-compile all module on sys.path. 1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Arguments (all optional): 1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi skip_curdir: if true, skip current directory (default true) 1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi maxlevels: max recursion level (default 0) 1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi force: as for compile_dir() (default 0) 1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi quiet: as for compile_dir() (default 0) 1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """ 1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 1 1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for dir in sys.path: 1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if (not dir or dir == os.curdir) and skip_curdir: 1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'Skipping current directory' 1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = success and compile_dir(dir, maxlevels, None, 1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi force, quiet=quiet) 1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return success 1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef expand_args(args, flist): 1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """read names in flist and append to args""" 1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi expanded = args[:] 1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if flist: 1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if flist == '-': 1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fd = sys.stdin 1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fd = open(flist) 1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi while 1: 1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi line = fd.readline() 1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not line: 1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi break 1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi expanded.append(line[:-1]) 1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except IOError: 1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "Error reading file list %s" % flist 1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raise 1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return expanded 1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef main(): 1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Script main program.""" 1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi import getopt 1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:') 1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except getopt.error, msg: 1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print msg 1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \ 1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "[-x regexp] [-i list] [directory|file ...]" 1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "arguments: zero or more file and directory names to compile; " \ 1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "if no arguments given, " 1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print " defaults to the equivalent of -l sys.path" 1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "options:" 1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "-l: don't recurse into subdirectories" 1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "-f: force rebuild even if timestamps are up-to-date" 1700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "-q: output only error messages" 1710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "-d destdir: directory to prepend to file paths for use in " \ 1720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "compile-time tracebacks and in" 1730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print " runtime tracebacks in cases where the source " \ 1740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "file is unavailable" 1750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "-x regexp: skip files matching the regular expression regexp; " \ 1760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "the regexp is searched for" 1770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print " in the full path of each file considered for " \ 1780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "compilation" 1790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "-i file: add all the files and directories listed in file to " \ 1800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "the list considered for" 1810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print ' compilation; if "-", names are read from stdin' 1820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sys.exit(2) 1840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi maxlevels = 10 1850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ddir = None 1860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi force = 0 1870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi quiet = 0 1880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi rx = None 1890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi flist = None 1900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for o, a in opts: 1910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if o == '-l': maxlevels = 0 1920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if o == '-d': ddir = a 1930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if o == '-f': force = 1 1940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if o == '-q': quiet = 1 1950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if o == '-x': 1960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi import re 1970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi rx = re.compile(a) 1980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if o == '-i': flist = a 1990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if ddir: 2000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if len(args) != 1 and not os.path.isdir(args[0]): 2010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "-d destdir require exactly one directory argument" 2020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sys.exit(2) 2030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 1 2040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 2050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if args or flist: 2060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 2070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if flist: 2080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi args = expand_args(args, flist) 2090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except IOError: 2100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 2110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if success: 2120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for arg in args: 2130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if os.path.isdir(arg): 2140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not compile_dir(arg, maxlevels, ddir, 2150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi force, rx, quiet): 2160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 2170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 2180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not compile_file(arg, ddir, force, rx, quiet): 2190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 2200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 2210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = compile_path() 2220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except KeyboardInterrupt: 2230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "\n[interrupted]" 2240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi success = 0 2250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return success 2260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == '__main__': 2280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi exit_status = int(not main()) 2290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sys.exit(exit_status) 230