"""distutils.command.build_scripts Implements the Distutils 'build_scripts' command.""" # created 2000/05/23, Bastian Kleineidam __revision__ = "$Id$" import sys, os, re from distutils.core import Command from distutils.dep_util import newer # check if Python is called on the first line with this expression first_line_re = re.compile(r'^#!.*python(\s+.*)?') class build_scripts (Command): description = "\"build\" scripts (copy and fixup #! line)" user_options = [ ('build-dir=', 'd', "directory to \"build\" (copy) to"), ('force', 'f', "forcibly build everything (ignore file timestamps"), ] def initialize_options (self): self.build_dir = None self.scripts = None self.force = None self.outfiles = None def finalize_options (self): self.set_undefined_options ('build', ('build_scripts', 'build_dir'), ('force', 'force')) self.scripts = self.distribution.scripts def run (self): if not self.scripts: return self.copy_scripts() def copy_scripts (self): """Copy each script listed in 'self.scripts'; if it's marked as a Python script in the Unix way (first line matches 'first_line_re', ie. starts with "\#!" and contains "python"), then adjust the first line to refer to the current Python intepreter as we copy. """ outfiles = [] self.mkpath(self.build_dir) for script in self.scripts: adjust = 0 outfile = os.path.join(self.build_dir, script) if not self.force and not newer(script, outfile): self.announce("not copying %s (output up-to-date)" % script) continue # Always open the file, but ignore failures in dry-run mode -- # that way, we'll get accurate feedback if we can read the # script. try: f = open(script, "r") except IOError: if not self.dry_run: raise f = None else: first_line = f.readline() if not first_line: self.warn("%s is an empty file (skipping)" % script) continue match = first_line_re.match(first_line) if match: adjust = 1 post_interp = match.group(1) if adjust: self.announce("copying and adjusting %s -> %s" % (script, self.build_dir)) if not self.dry_run: outf = open(outfile, "w") outf.write("#!%s%s\n" % (os.path.normpath(sys.executable), post_interp)) outf.writelines(f.readlines()) outf.close() if f: f.close() else: f.close() self.copy_file(script, outfile) # copy_scripts () # class build_scripts