Merged revisions 78983,78985 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r78983 | matthias.klose | 2010-03-15 18:44:12 +0100 (Mo, 15 Mär 2010) | 2 lines

  - Issue #8140: extend compileall to compile single files. Add -i option.
........
  r78985 | matthias.klose | 2010-03-15 19:00:01 +0100 (Mo, 15 Mär 2010) | 2 lines

  - Fix typo in Lib/compileall.py(__all__).
........
This commit is contained in:
Matthias Klose 2010-03-16 00:36:26 +00:00
parent 82f60910b7
commit c33b902ebb
3 changed files with 123 additions and 50 deletions

View File

@ -17,7 +17,7 @@ import py_compile
import struct import struct
import imp import imp
__all__ = ["compile_dir","compile_path"] __all__ = ["compile_dir","compile_file","compile_path"]
def compile_dir(dir, maxlevels=10, ddir=None, def compile_dir(dir, maxlevels=10, ddir=None,
force=0, rx=None, quiet=0): force=0, rx=None, quiet=0):
@ -48,47 +48,9 @@ def compile_dir(dir, maxlevels=10, ddir=None,
dfile = os.path.join(ddir, name) dfile = os.path.join(ddir, name)
else: else:
dfile = None dfile = None
if rx is not None: if not os.path.isdir(fullname):
mo = rx.search(fullname) if not compile_file(fullname, ddir, force, rx, quiet):
if mo: success = 0
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='')
print(err.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 \ elif maxlevels > 0 and \
name != os.curdir and name != os.pardir and \ name != os.curdir and name != os.pardir and \
os.path.isdir(fullname) and \ os.path.isdir(fullname) and \
@ -98,6 +60,64 @@ def compile_dir(dir, maxlevels=10, ddir=None,
success = 0 success = 0
return success return success
def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):
"""Byte-compile file.
file: the file to byte-compile
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
"""
success = 1
name = os.path.basename(fullname)
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:
return success
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:
return success
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='')
print(err.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
return success
def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0): def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0):
"""Byte-compile all module on sys.path. """Byte-compile all module on sys.path.
@ -118,15 +138,34 @@ def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0):
force, quiet=quiet) force, quiet=quiet)
return success return success
def expand_args(args, flist):
"""read names in flist and append to args"""
expanded = args[:]
if flist:
try:
if flist == '-':
fd = sys.stdin
else:
fd = open(flist)
while 1:
line = fd.readline()
if not line:
break
expanded.append(line[:-1])
except IOError:
print("Error reading file list %s" % flist)
raise
return expanded
def main(): def main():
"""Script main program.""" """Script main program."""
import getopt import getopt
try: try:
opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:') opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:')
except getopt.error as msg: except getopt.error as msg:
print(msg) print(msg)
print("usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \ print("usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \
"[-x regexp] [directory ...]") "[-x regexp] [-i list] [directory|file ...]")
print("-l: don't recurse down") print("-l: don't recurse down")
print("-f: force rebuild even if timestamps are up-to-date") print("-f: force rebuild even if timestamps are up-to-date")
print("-q: quiet operation") print("-q: quiet operation")
@ -134,12 +173,14 @@ def main():
print(" if no directory arguments, -l sys.path is assumed") print(" if no directory arguments, -l sys.path is assumed")
print("-x regexp: skip files matching the regular expression regexp") print("-x regexp: skip files matching the regular expression regexp")
print(" the regexp is searched for in the full path of the file") print(" the regexp is searched for in the full path of the file")
print("-i list: expand list with its content (file and directory names)")
sys.exit(2) sys.exit(2)
maxlevels = 10 maxlevels = 10
ddir = None ddir = None
force = 0 force = 0
quiet = 0 quiet = 0
rx = None rx = None
flist = None
for o, a in opts: for o, a in opts:
if o == '-l': maxlevels = 0 if o == '-l': maxlevels = 0
if o == '-d': ddir = a if o == '-d': ddir = a
@ -148,17 +189,28 @@ def main():
if o == '-x': if o == '-x':
import re import re
rx = re.compile(a) rx = re.compile(a)
if o == '-i': flist = a
if ddir: if ddir:
if len(args) != 1: if len(args) != 1 and not os.path.isdir(args[0]):
print("-d destdir require exactly one directory argument") print("-d destdir require exactly one directory argument")
sys.exit(2) sys.exit(2)
success = 1 success = 1
try: try:
if args: if args or flist:
for dir in args: try:
if not compile_dir(dir, maxlevels, ddir, if flist:
force, rx, quiet): args = expand_args(args, flist)
success = 0 except IOError:
success = 0
if success:
for arg in args:
if os.path.isdir(arg):
if not compile_dir(arg, maxlevels, ddir,
force, rx, quiet):
success = 0
else:
if not compile_file(arg, ddir, force, rx, quiet):
success = 0
else: else:
success = compile_path() success = compile_path()
except KeyboardInterrupt: except KeyboardInterrupt:

View File

@ -17,6 +17,9 @@ class CompileallTests(unittest.TestCase):
self.bc_path = self.source_path + ('c' if __debug__ else 'o') self.bc_path = self.source_path + ('c' if __debug__ else 'o')
with open(self.source_path, 'w') as file: with open(self.source_path, 'w') as file:
file.write('x = 123\n') file.write('x = 123\n')
self.source_path2 = os.path.join(self.directory, '_test2.py')
self.bc_path2 = self.source_path2 + ('c' if __debug__ else 'o')
shutil.copyfile(self.source_path, self.source_path2)
def tearDown(self): def tearDown(self):
shutil.rmtree(self.directory) shutil.rmtree(self.directory)
@ -52,6 +55,22 @@ class CompileallTests(unittest.TestCase):
# Test a change in mtime leads to a new .pyc. # Test a change in mtime leads to a new .pyc.
self.recreation_check(b'\0\0\0\0') self.recreation_check(b'\0\0\0\0')
def test_compile_files(self):
# Test compiling a single file, and complete directory
for fn in (self.bc_path, self.bc_path2):
try:
os.unlink(fn)
except:
pass
compileall.compile_file(self.source_path, force=False, quiet=True)
self.assertTrue(os.path.isfile(self.bc_path) \
and not os.path.isfile(self.bc_path2))
os.unlink(self.bc_path)
compileall.compile_dir(self.directory, force=False, quiet=True)
self.assertTrue(os.path.isfile(self.bc_path) \
and os.path.isfile(self.bc_path2))
os.unlink(self.bc_path)
os.unlink(self.bc_path2)
def test_main(): def test_main():
support.run_unittest(CompileallTests) support.run_unittest(CompileallTests)

View File

@ -283,6 +283,8 @@ C-API
Library Library
------- -------
- Issue #8140: extend compileall to compile single files. Add -i option.
- Issue #7356: ctypes.util: Make parsing of ldconfig output independent of - Issue #7356: ctypes.util: Make parsing of ldconfig output independent of
the locale. the locale.