cpython/Lib/distutils/command/build_scripts.py
Fred Drake 53a79060bb When not copying a file because the output is up to date, make the message
slightly more brief, and more like the message that an extension will not
be built because the built copy is up to date.
2001-03-02 07:28:03 +00:00

103 lines
3.2 KiB
Python

"""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.
# This expression will leave lines using /usr/bin/env alone; presumably
# the script author knew what they were doing...)
first_line_re = re.compile(r'^#!(?!\s*/usr/bin/env\b).*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"),
]
boolean_options = ['force']
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 interpreter as we copy.
"""
outfiles = []
self.mkpath(self.build_dir)
for script in self.scripts:
adjust = 0
outfile = os.path.join(self.build_dir, os.path.basename(script))
if not self.force and not newer(script, outfile):
self.announce("not copying %s (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