#10453: compileall now uses argparse instead of getopt, so -h works.
Patch by Michele Orrù.
This commit is contained in:
parent
a78f74ce02
commit
650f147298
|
@ -153,90 +153,68 @@ def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=False,
|
||||||
legacy=legacy)
|
legacy=legacy)
|
||||||
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 argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Utilities to support installing Python libraries.')
|
||||||
|
parser.add_argument('-l', action='store_const', default=10, const=0,
|
||||||
|
dest='maxlevels', help="don't recurse down")
|
||||||
|
parser.add_argument('-f', action='store_true', dest='force',
|
||||||
|
help='force rebuild even if timestamps are up to date')
|
||||||
|
parser.add_argument('-q', action='store_true', dest='quiet',
|
||||||
|
help='quiet operation')
|
||||||
|
parser.add_argument('-b', action='store_true', dest='legacy',
|
||||||
|
help='procude legacy byte-compiled file paths')
|
||||||
|
parser.add_argument('-d', metavar='DESTDIR', dest='ddir', default=None,
|
||||||
|
help=('purported directory name for error messages; '
|
||||||
|
'if no directory arguments, -l sys.path '
|
||||||
|
'is assumed.'))
|
||||||
|
parser.add_argument('-x', metavar='REGEXP', dest='rx', default=None,
|
||||||
|
help=('skip files matching the regular expression.\n\t'
|
||||||
|
'The regexp is searched for in the full path'
|
||||||
|
'of the file'))
|
||||||
|
parser.add_argument('-i', metavar='FILE', dest='flist',
|
||||||
|
help='expand the list with the contenent of FILE.')
|
||||||
|
parser.add_argument('compile_dest', metavar='FILE|DIR', nargs='?')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if (args.ddir and args.compile_dest != 1 and
|
||||||
|
not os.path.isdir(args.compile_dest)):
|
||||||
|
raise argparse.ArgumentError("-d destdir require exactly one "
|
||||||
|
"directory argument")
|
||||||
|
if args.rx:
|
||||||
|
import re
|
||||||
|
args.rx = re.compile(args.rx)
|
||||||
|
|
||||||
|
# if flist is provided then load it
|
||||||
|
compile_dests = [args.compile_dest]
|
||||||
|
if args.flist:
|
||||||
|
with open(args.flist) as f:
|
||||||
|
files = f.read().split()
|
||||||
|
compile_dests.extend(files)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:b')
|
if compile_dests:
|
||||||
except getopt.error as msg:
|
for dest in compile_dests:
|
||||||
print(msg)
|
if os.path.isdir(dest):
|
||||||
print("usage: python compileall.py [-l] [-f] [-q] [-d destdir] "
|
if not compile_dir(dest, args.maxlevels, args.ddir,
|
||||||
"[-x regexp] [-i list] [directory|file ...]")
|
args.force, args.rx, args.quiet,
|
||||||
print("-l: don't recurse down")
|
args.legacy):
|
||||||
print("-f: force rebuild even if timestamps are up-to-date")
|
return 0
|
||||||
print("-q: quiet operation")
|
else:
|
||||||
print("-d destdir: purported directory name for error messages")
|
if not compile_file(dest, args.ddir, args.force, args.rx,
|
||||||
print(" if no directory arguments, -l sys.path is assumed")
|
args.quiet, args.legacy):
|
||||||
print("-x regexp: skip files matching the regular expression regexp")
|
return 0
|
||||||
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)")
|
|
||||||
print("-b: Produce legacy byte-compile file paths")
|
|
||||||
sys.exit(2)
|
|
||||||
maxlevels = 10
|
|
||||||
ddir = None
|
|
||||||
force = False
|
|
||||||
quiet = False
|
|
||||||
rx = None
|
|
||||||
flist = None
|
|
||||||
legacy = False
|
|
||||||
for o, a in opts:
|
|
||||||
if o == '-l': maxlevels = 0
|
|
||||||
if o == '-d': ddir = a
|
|
||||||
if o == '-f': force = True
|
|
||||||
if o == '-q': quiet = True
|
|
||||||
if o == '-x':
|
|
||||||
import re
|
|
||||||
rx = re.compile(a)
|
|
||||||
if o == '-i': flist = a
|
|
||||||
if o == '-b': legacy = True
|
|
||||||
if ddir:
|
|
||||||
if len(args) != 1 and not os.path.isdir(args[0]):
|
|
||||||
print("-d destdir require exactly one directory argument")
|
|
||||||
sys.exit(2)
|
|
||||||
success = 1
|
|
||||||
try:
|
|
||||||
if args or flist:
|
|
||||||
try:
|
|
||||||
if flist:
|
|
||||||
args = expand_args(args, flist)
|
|
||||||
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, legacy):
|
|
||||||
success = 0
|
|
||||||
else:
|
|
||||||
if not compile_file(arg, ddir, force, rx,
|
|
||||||
quiet, legacy):
|
|
||||||
success = 0
|
|
||||||
else:
|
else:
|
||||||
success = compile_path(legacy=legacy)
|
return compile_path(legacy=args.legacy)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\n[interrupt]")
|
print("\n[interrupt]")
|
||||||
success = 0
|
return 0
|
||||||
return success
|
return 1
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
exit_status = int(not main())
|
exit_status = int(not main())
|
||||||
|
|
|
@ -7,6 +7,7 @@ import shutil
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
import io
|
import io
|
||||||
|
|
||||||
|
@ -112,7 +113,7 @@ class EncodingTest(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class CommandLineTests(unittest.TestCase):
|
class CommandLineTests(unittest.TestCase):
|
||||||
"""Test some aspects of compileall's CLI."""
|
"""Test compileall's CLI."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.addCleanup(self._cleanup)
|
self.addCleanup(self._cleanup)
|
||||||
|
@ -184,6 +185,57 @@ class CommandLineTests(unittest.TestCase):
|
||||||
self.assertTrue(os.path.exists(cachedir))
|
self.assertTrue(os.path.exists(cachedir))
|
||||||
self.assertFalse(os.path.exists(cachecachedir))
|
self.assertFalse(os.path.exists(cachecachedir))
|
||||||
|
|
||||||
|
def test_force(self):
|
||||||
|
retcode = subprocess.call(
|
||||||
|
(sys.executable, '-m', 'compileall', '-q', self.pkgdir))
|
||||||
|
self.assertEqual(retcode, 0)
|
||||||
|
pycpath = imp.cache_from_source(os.path.join(self.pkgdir, 'bar.py'))
|
||||||
|
# set atime/mtime backward to avoid file timestamp resolution issues
|
||||||
|
os.utime(pycpath, (time.time()-60,)*2)
|
||||||
|
access = os.stat(pycpath).st_mtime
|
||||||
|
retcode = subprocess.call(
|
||||||
|
(sys.executable, '-m', 'compileall', '-q', '-f', self.pkgdir))
|
||||||
|
self.assertEqual(retcode, 0)
|
||||||
|
access2 = os.stat(pycpath).st_mtime
|
||||||
|
self.assertNotEqual(access, access2)
|
||||||
|
|
||||||
|
def test_legacy(self):
|
||||||
|
# create a new module
|
||||||
|
newpackage = os.path.join(self.pkgdir, 'spam')
|
||||||
|
os.mkdir(newpackage)
|
||||||
|
with open(os.path.join(newpackage, '__init__.py'), 'w'):
|
||||||
|
pass
|
||||||
|
with open(os.path.join(newpackage, 'ham.py'), 'w'):
|
||||||
|
pass
|
||||||
|
sourcefile = os.path.join(newpackage, 'ham.py')
|
||||||
|
|
||||||
|
retcode = subprocess.call(
|
||||||
|
(sys.executable, '-m', 'compileall', '-q', '-l', self.pkgdir))
|
||||||
|
self.assertEqual(retcode, 0)
|
||||||
|
self.assertFalse(os.path.exists(imp.cache_from_source(sourcefile)))
|
||||||
|
|
||||||
|
retcode = subprocess.call(
|
||||||
|
(sys.executable, '-m', 'compileall', '-q', self.pkgdir))
|
||||||
|
self.assertEqual(retcode, 0)
|
||||||
|
self.assertTrue(os.path.exists(imp.cache_from_source(sourcefile)))
|
||||||
|
|
||||||
|
def test_quiet(self):
|
||||||
|
noise = subprocess.getoutput('{} -m compileall {}'.format(
|
||||||
|
sys.executable, self.pkgdir))
|
||||||
|
quiet = subprocess.getoutput(('{} -m compileall {}'.format(
|
||||||
|
sys.executable, self.pkgdir)))
|
||||||
|
self.assertTrue(len(noise) > len(quiet))
|
||||||
|
|
||||||
|
def test_regexp(self):
|
||||||
|
retcode = subprocess.call(
|
||||||
|
(sys.executable, '-m', 'compileall', '-q', '-x', 'bar.*', self.pkgdir))
|
||||||
|
self.assertEqual(retcode, 0)
|
||||||
|
|
||||||
|
sourcefile = os.path.join(self.pkgdir, 'bar.py')
|
||||||
|
self.assertFalse(os.path.exists(imp.cache_from_source(sourcefile)))
|
||||||
|
sourcefile = os.path.join(self.pkgdir, '__init__.py')
|
||||||
|
self.assertTrue(os.path.exists(imp.cache_from_source(sourcefile)))
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
support.run_unittest(
|
support.run_unittest(
|
||||||
|
|
|
@ -30,6 +30,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #10453: compileall now uses argparse instead of getopt, and thus
|
||||||
|
provides clean output when called with '-h'.
|
||||||
|
|
||||||
- Issue #8078: Add constants for higher baud rates in the termios module.
|
- Issue #8078: Add constants for higher baud rates in the termios module.
|
||||||
Patch by Rodolpho Eckhardt.
|
Patch by Rodolpho Eckhardt.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue