mirror of
https://github.com/AdaCore/cpython.git
synced 2026-02-12 12:57:15 -08:00
Backport of R. David Murray’s 3.2 patch. The code is ugly, with print statements split across lines, but the output is readable.
175 lines
6.0 KiB
Python
175 lines
6.0 KiB
Python
"""Module/script to "compile" all .py files to .pyc (or .pyo) file.
|
|
|
|
When called as a script with arguments, this compiles the directories
|
|
given as arguments recursively; the -l option prevents it from
|
|
recursing into directories.
|
|
|
|
Without arguments, if compiles all modules on sys.path, without
|
|
recursing into subdirectories. (Even though it should do so for
|
|
packages -- for now, you'll have to deal with packages separately.)
|
|
|
|
See module py_compile for details of the actual byte-compilation.
|
|
|
|
"""
|
|
import os
|
|
import sys
|
|
import py_compile
|
|
import struct
|
|
import imp
|
|
|
|
__all__ = ["compile_dir","compile_path"]
|
|
|
|
def compile_dir(dir, maxlevels=10, ddir=None,
|
|
force=0, rx=None, quiet=0):
|
|
"""Byte-compile all modules in the given directory tree.
|
|
|
|
Arguments (only dir is required):
|
|
|
|
dir: the directory to byte-compile
|
|
maxlevels: maximum recursion level (default 10)
|
|
ddir: if given, purported directory name (this is the
|
|
directory name that will show up in error messages)
|
|
force: if 1, force compilation, even if timestamps are up-to-date
|
|
quiet: if 1, be quiet during compilation
|
|
|
|
"""
|
|
if not quiet:
|
|
print('Listing', dir, '...')
|
|
try:
|
|
names = os.listdir(dir)
|
|
except os.error:
|
|
print("Can't list", dir)
|
|
names = []
|
|
names.sort()
|
|
success = 1
|
|
for name in names:
|
|
fullname = os.path.join(dir, name)
|
|
if ddir is not None:
|
|
dfile = os.path.join(ddir, name)
|
|
else:
|
|
dfile = None
|
|
if rx is not None:
|
|
mo = rx.search(fullname)
|
|
if mo:
|
|
continue
|
|
if os.path.isfile(fullname):
|
|
head, tail = name[:-3], name[-3:]
|
|
if tail == '.py':
|
|
if not force:
|
|
try:
|
|
mtime = int(os.stat(fullname).st_mtime)
|
|
expect = struct.pack('<4sl', imp.get_magic(), mtime)
|
|
cfile = fullname + (__debug__ and 'c' or 'o')
|
|
with open(cfile, 'rb') as chandle:
|
|
actual = chandle.read(8)
|
|
if expect == actual:
|
|
continue
|
|
except IOError:
|
|
pass
|
|
if not quiet:
|
|
print('Compiling', fullname, '...')
|
|
try:
|
|
ok = py_compile.compile(fullname, None, dfile, True)
|
|
except KeyboardInterrupt:
|
|
raise KeyboardInterrupt
|
|
except py_compile.PyCompileError as err:
|
|
if quiet:
|
|
print('*** Error compiling', fullname, '...')
|
|
else:
|
|
print('*** ', end='')
|
|
# escape non-printable characters in msg
|
|
msg = err.msg.encode(sys.stdout.encoding, 'backslashreplace')
|
|
msg = msg.decode(sys.stdout.encoding)
|
|
print(msg)
|
|
success = 0
|
|
except (SyntaxError, UnicodeError, IOError) as e:
|
|
if quiet:
|
|
print('*** Error compiling', fullname, '...')
|
|
else:
|
|
print('*** ', end='')
|
|
print(e.__class__.__name__ + ':', e)
|
|
success = 0
|
|
else:
|
|
if ok == 0:
|
|
success = 0
|
|
elif maxlevels > 0 and \
|
|
name != os.curdir and name != os.pardir and \
|
|
os.path.isdir(fullname) and \
|
|
not os.path.islink(fullname):
|
|
if not compile_dir(fullname, maxlevels - 1, dfile, force, rx,
|
|
quiet):
|
|
success = 0
|
|
return success
|
|
|
|
def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0):
|
|
"""Byte-compile all module on sys.path.
|
|
|
|
Arguments (all optional):
|
|
|
|
skip_curdir: if true, skip current directory (default true)
|
|
maxlevels: max recursion level (default 0)
|
|
force: as for compile_dir() (default 0)
|
|
quiet: as for compile_dir() (default 0)
|
|
|
|
"""
|
|
success = 1
|
|
for dir in sys.path:
|
|
if (not dir or dir == os.curdir) and skip_curdir:
|
|
print('Skipping current directory')
|
|
else:
|
|
success = success and compile_dir(dir, maxlevels, None,
|
|
force, quiet=quiet)
|
|
return success
|
|
|
|
def main():
|
|
"""Script main program."""
|
|
import getopt
|
|
try:
|
|
opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:')
|
|
except getopt.error as msg:
|
|
print(msg)
|
|
print("usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \
|
|
"[-x regexp] [directory ...]")
|
|
print("-l: don't recurse down")
|
|
print("-f: force rebuild even if timestamps are up-to-date")
|
|
print("-q: quiet operation")
|
|
print("-d destdir: purported directory name for error messages")
|
|
print(" if no directory arguments, -l sys.path is assumed")
|
|
print("-x regexp: skip files matching the regular expression regexp")
|
|
print(" the regexp is searched for in the full path of the file")
|
|
sys.exit(2)
|
|
maxlevels = 10
|
|
ddir = None
|
|
force = 0
|
|
quiet = 0
|
|
rx = None
|
|
for o, a in opts:
|
|
if o == '-l': maxlevels = 0
|
|
if o == '-d': ddir = a
|
|
if o == '-f': force = 1
|
|
if o == '-q': quiet = 1
|
|
if o == '-x':
|
|
import re
|
|
rx = re.compile(a)
|
|
if ddir:
|
|
if len(args) != 1:
|
|
print("-d destdir require exactly one directory argument")
|
|
sys.exit(2)
|
|
success = 1
|
|
try:
|
|
if args:
|
|
for dir in args:
|
|
if not compile_dir(dir, maxlevels, ddir,
|
|
force, rx, quiet):
|
|
success = 0
|
|
else:
|
|
success = compile_path()
|
|
except KeyboardInterrupt:
|
|
print("\n[interrupt]")
|
|
success = 0
|
|
return success
|
|
|
|
if __name__ == '__main__':
|
|
exit_status = int(not main())
|
|
sys.exit(exit_status)
|