0001 """distutils.command.build_scripts 0002 0003 Implements the Distutils 'build_scripts' command.""" 0004 0005 # This module should be kept compatible with Python 1.5.2. 0006 0007 __revision__ = "$Id: build_scripts.py,v 1.24 2004/08/25 11:37:43 loewis Exp $" 0008 0009 import sys, os, re 0010 from stat import ST_MODE 0011 from distutils import sysconfig 0012 from distutils.core import Command 0013 from distutils.dep_util import newer 0014 from distutils.util import convert_path 0015 from distutils import log 0016 0017 # check if Python is called on the first line with this expression 0018 first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$') 0019 0020 class build_scripts (Command): 0021 0022 description = "\"build\" scripts (copy and fixup #! line)" 0023 0024 user_options = [ 0025 ('build-dir=', 'd', "directory to \"build\" (copy) to"), 0026 ('force', 'f', "forcibly build everything (ignore file timestamps"), 0027 ('executable=', 'e', "specify final destination interpreter path"), 0028 ] 0029 0030 boolean_options = ['force'] 0031 0032 0033 def initialize_options (self): 0034 self.build_dir = None 0035 self.scripts = None 0036 self.force = None 0037 self.executable = None 0038 self.outfiles = None 0039 0040 def finalize_options (self): 0041 self.set_undefined_options('build', 0042 ('build_scripts', 'build_dir'), 0043 ('force', 'force'), 0044 ('executable', 'executable')) 0045 self.scripts = self.distribution.scripts 0046 0047 def get_source_files(self): 0048 return self.scripts 0049 0050 def run (self): 0051 if not self.scripts: 0052 return 0053 self.copy_scripts() 0054 0055 0056 def copy_scripts (self): 0057 """Copy each script listed in 'self.scripts'; if it's marked as a 0058 Python script in the Unix way (first line matches 'first_line_re', 0059 ie. starts with "\#!" and contains "python"), then adjust the first 0060 line to refer to the current Python interpreter as we copy. 0061 """ 0062 self.mkpath(self.build_dir) 0063 outfiles = [] 0064 for script in self.scripts: 0065 adjust = 0 0066 script = convert_path(script) 0067 outfile = os.path.join(self.build_dir, os.path.basename(script)) 0068 outfiles.append(outfile) 0069 0070 if not self.force and not newer(script, outfile): 0071 log.debug("not copying %s (up-to-date)", script) 0072 continue 0073 0074 # Always open the file, but ignore failures in dry-run mode -- 0075 # that way, we'll get accurate feedback if we can read the 0076 # script. 0077 try: 0078 f = open(script, "r") 0079 except IOError: 0080 if not self.dry_run: 0081 raise 0082 f = None 0083 else: 0084 first_line = f.readline() 0085 if not first_line: 0086 self.warn("%s is an empty file (skipping)" % script) 0087 continue 0088 0089 match = first_line_re.match(first_line) 0090 if match: 0091 adjust = 1 0092 post_interp = match.group(1) or '' 0093 0094 if adjust: 0095 log.info("copying and adjusting %s -> %s", script, 0096 self.build_dir) 0097 if not self.dry_run: 0098 outf = open(outfile, "w") 0099 if not sysconfig.python_build: 0100 outf.write("#!%s%s\n" % 0101 (self.executable, 0102 post_interp)) 0103 else: 0104 outf.write("#!%s%s\n" % 0105 (os.path.join( 0106 sysconfig.get_config_var("BINDIR"), 0107 "python" + sysconfig.get_config_var("EXE")), 0108 post_interp)) 0109 outf.writelines(f.readlines()) 0110 outf.close() 0111 if f: 0112 f.close() 0113 else: 0114 f.close() 0115 self.copy_file(script, outfile) 0116 0117 if os.name == 'posix': 0118 for file in outfiles: 0119 if self.dry_run: 0120 log.info("changing mode of %s", file) 0121 else: 0122 oldmode = os.stat(file)[ST_MODE] & 07777 0123 newmode = (oldmode | 0555) & 07777 0124 if newmode != oldmode: 0125 log.info("changing mode of %s from %o to %o", 0126 file, oldmode, newmode) 0127 os.chmod(file, newmode) 0128 0129 # copy_scripts () 0130 0131 # class build_scripts 0132
Generated by PyXR 0.9.4