mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	- Issue #8140: extend compileall to compile single files. Add -i option.
This commit is contained in:
		
							parent
							
								
									dc36472472
								
							
						
					
					
						commit
						b13d04c991
					
				
					 3 changed files with 116 additions and 42 deletions
				
			
		| 
						 | 
					@ -17,7 +17,7 @@
 | 
				
			||||||
import struct
 | 
					import struct
 | 
				
			||||||
import imp
 | 
					import imp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__all__ = ["compile_dir","compile_path"]
 | 
					__all__ = ["compile_dir","compile_files","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,39 +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 py_compile.PyCompileError,err:
 | 
					 | 
				
			||||||
                    if quiet:
 | 
					 | 
				
			||||||
                        print 'Compiling', fullname, '...'
 | 
					 | 
				
			||||||
                    print err.msg
 | 
					 | 
				
			||||||
                    success = 0
 | 
					 | 
				
			||||||
                except IOError, e:
 | 
					 | 
				
			||||||
                    print "Sorry", 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 \
 | 
				
			||||||
| 
						 | 
					@ -90,6 +60,57 @@ 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 py_compile.PyCompileError,err:
 | 
				
			||||||
 | 
					                if quiet:
 | 
				
			||||||
 | 
					                    print 'Compiling', fullname, '...'
 | 
				
			||||||
 | 
					                print err.msg
 | 
				
			||||||
 | 
					                success = 0
 | 
				
			||||||
 | 
					            except IOError, e:
 | 
				
			||||||
 | 
					                print "Sorry", 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,15 +131,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, msg:
 | 
					    except getopt.error, 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"
 | 
				
			||||||
| 
						 | 
					@ -126,12 +166,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
 | 
				
			||||||
| 
						 | 
					@ -140,17 +182,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:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,9 @@ def setUp(self):
 | 
				
			||||||
        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 @@ def test_magic_number(self):
 | 
				
			||||||
        # 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():
 | 
				
			||||||
    test_support.run_unittest(CompileallTests)
 | 
					    test_support.run_unittest(CompileallTests)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,8 @@ Core and Builtins
 | 
				
			||||||
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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue