+++ /dev/null
-"""Module/script to byte-compile all .py files to .pyc (or .pyo) files.\r
-\r
-When called as a script with arguments, this compiles the directories\r
-given as arguments recursively; the -l option prevents it from\r
-recursing into directories.\r
-\r
-Without arguments, if compiles all modules on sys.path, without\r
-recursing into subdirectories. (Even though it should do so for\r
-packages -- for now, you'll have to deal with packages separately.)\r
-\r
-See module py_compile for details of the actual byte-compilation.\r
-"""\r
-import os\r
-import sys\r
-import py_compile\r
-import struct\r
-import imp\r
-\r
-__all__ = ["compile_dir","compile_file","compile_path"]\r
-\r
-def compile_dir(dir, maxlevels=10, ddir=None,\r
- force=0, rx=None, quiet=0):\r
- """Byte-compile all modules in the given directory tree.\r
-\r
- Arguments (only dir is required):\r
-\r
- dir: the directory to byte-compile\r
- maxlevels: maximum recursion level (default 10)\r
- ddir: the directory that will be prepended to the path to the\r
- file as it is compiled into each byte-code file.\r
- force: if 1, force compilation, even if timestamps are up-to-date\r
- quiet: if 1, be quiet during compilation\r
- """\r
- if not quiet:\r
- print 'Listing', dir, '...'\r
- try:\r
- names = os.listdir(dir)\r
- except os.error:\r
- print "Can't list", dir\r
- names = []\r
- names.sort()\r
- success = 1\r
- for name in names:\r
- fullname = os.path.join(dir, name)\r
- if ddir is not None:\r
- dfile = os.path.join(ddir, name)\r
- else:\r
- dfile = None\r
- if not os.path.isdir(fullname):\r
- if not compile_file(fullname, ddir, force, rx, quiet):\r
- success = 0\r
- elif maxlevels > 0 and \\r
- name != os.curdir and name != os.pardir and \\r
- os.path.isdir(fullname) and \\r
- not os.path.islink(fullname):\r
- if not compile_dir(fullname, maxlevels - 1, dfile, force, rx,\r
- quiet):\r
- success = 0\r
- return success\r
-\r
-def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):\r
- """Byte-compile one file.\r
-\r
- Arguments (only fullname is required):\r
-\r
- fullname: the file to byte-compile\r
- ddir: if given, the directory name compiled in to the\r
- byte-code file.\r
- force: if 1, force compilation, even if timestamps are up-to-date\r
- quiet: if 1, be quiet during compilation\r
- """\r
- success = 1\r
- name = os.path.basename(fullname)\r
- if ddir is not None:\r
- dfile = os.path.join(ddir, name)\r
- else:\r
- dfile = None\r
- if rx is not None:\r
- mo = rx.search(fullname)\r
- if mo:\r
- return success\r
- if os.path.isfile(fullname):\r
- head, tail = name[:-3], name[-3:]\r
- if tail == '.py':\r
- if not force:\r
- try:\r
- mtime = int(os.stat(fullname).st_mtime)\r
- expect = struct.pack('<4sl', imp.get_magic(), mtime)\r
- cfile = fullname + (__debug__ and 'c' or 'o')\r
- with open(cfile, 'rb') as chandle:\r
- actual = chandle.read(8)\r
- if expect == actual:\r
- return success\r
- except IOError:\r
- pass\r
- if not quiet:\r
- print 'Compiling', fullname, '...'\r
- try:\r
- ok = py_compile.compile(fullname, None, dfile, True)\r
- except py_compile.PyCompileError,err:\r
- if quiet:\r
- print 'Compiling', fullname, '...'\r
- print err.msg\r
- success = 0\r
- except IOError, e:\r
- print "Sorry", e\r
- success = 0\r
- else:\r
- if ok == 0:\r
- success = 0\r
- return success\r
-\r
-def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0):\r
- """Byte-compile all module on sys.path.\r
-\r
- Arguments (all optional):\r
-\r
- skip_curdir: if true, skip current directory (default true)\r
- maxlevels: max recursion level (default 0)\r
- force: as for compile_dir() (default 0)\r
- quiet: as for compile_dir() (default 0)\r
- """\r
- success = 1\r
- for dir in sys.path:\r
- if (not dir or dir == os.curdir) and skip_curdir:\r
- print 'Skipping current directory'\r
- else:\r
- success = success and compile_dir(dir, maxlevels, None,\r
- force, quiet=quiet)\r
- return success\r
-\r
-def expand_args(args, flist):\r
- """read names in flist and append to args"""\r
- expanded = args[:]\r
- if flist:\r
- try:\r
- if flist == '-':\r
- fd = sys.stdin\r
- else:\r
- fd = open(flist)\r
- while 1:\r
- line = fd.readline()\r
- if not line:\r
- break\r
- expanded.append(line[:-1])\r
- except IOError:\r
- print "Error reading file list %s" % flist\r
- raise\r
- return expanded\r
-\r
-def main():\r
- """Script main program."""\r
- import getopt\r
- try:\r
- opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:')\r
- except getopt.error, msg:\r
- print msg\r
- print "usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \\r
- "[-x regexp] [-i list] [directory|file ...]"\r
- print\r
- print "arguments: zero or more file and directory names to compile; " \\r
- "if no arguments given, "\r
- print " defaults to the equivalent of -l sys.path"\r
- print\r
- print "options:"\r
- print "-l: don't recurse into subdirectories"\r
- print "-f: force rebuild even if timestamps are up-to-date"\r
- print "-q: output only error messages"\r
- print "-d destdir: directory to prepend to file paths for use in " \\r
- "compile-time tracebacks and in"\r
- print " runtime tracebacks in cases where the source " \\r
- "file is unavailable"\r
- print "-x regexp: skip files matching the regular expression regexp; " \\r
- "the regexp is searched for"\r
- print " in the full path of each file considered for " \\r
- "compilation"\r
- print "-i file: add all the files and directories listed in file to " \\r
- "the list considered for"\r
- print ' compilation; if "-", names are read from stdin'\r
-\r
- sys.exit(2)\r
- maxlevels = 10\r
- ddir = None\r
- force = 0\r
- quiet = 0\r
- rx = None\r
- flist = None\r
- for o, a in opts:\r
- if o == '-l': maxlevels = 0\r
- if o == '-d': ddir = a\r
- if o == '-f': force = 1\r
- if o == '-q': quiet = 1\r
- if o == '-x':\r
- import re\r
- rx = re.compile(a)\r
- if o == '-i': flist = a\r
- if ddir:\r
- if len(args) != 1 and not os.path.isdir(args[0]):\r
- print "-d destdir require exactly one directory argument"\r
- sys.exit(2)\r
- success = 1\r
- try:\r
- if args or flist:\r
- try:\r
- if flist:\r
- args = expand_args(args, flist)\r
- except IOError:\r
- success = 0\r
- if success:\r
- for arg in args:\r
- if os.path.isdir(arg):\r
- if not compile_dir(arg, maxlevels, ddir,\r
- force, rx, quiet):\r
- success = 0\r
- else:\r
- if not compile_file(arg, ddir, force, rx, quiet):\r
- success = 0\r
- else:\r
- success = compile_path()\r
- except KeyboardInterrupt:\r
- print "\n[interrupted]"\r
- success = 0\r
- return success\r
-\r
-if __name__ == '__main__':\r
- exit_status = int(not main())\r
- sys.exit(exit_status)\r