Update to 2.7.3
[profile/ivi/python.git] / Lib / distutils / command / build_scripts.py
1 """distutils.command.build_scripts
2
3 Implements the Distutils 'build_scripts' command."""
4
5 __revision__ = "$Id$"
6
7 import os, re
8 from stat import ST_MODE
9 from distutils.core import Command
10 from distutils.dep_util import newer
11 from distutils.util import convert_path
12 from distutils import log
13
14 # check if Python is called on the first line with this expression
15 first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
16
17 class build_scripts (Command):
18
19     description = "\"build\" scripts (copy and fixup #! line)"
20
21     user_options = [
22         ('build-dir=', 'd', "directory to \"build\" (copy) to"),
23         ('force', 'f', "forcibly build everything (ignore file timestamps"),
24         ('executable=', 'e', "specify final destination interpreter path"),
25         ]
26
27     boolean_options = ['force']
28
29
30     def initialize_options (self):
31         self.build_dir = None
32         self.scripts = None
33         self.force = None
34         self.executable = None
35         self.outfiles = None
36
37     def finalize_options (self):
38         self.set_undefined_options('build',
39                                    ('build_scripts', 'build_dir'),
40                                    ('force', 'force'),
41                                    ('executable', 'executable'))
42         self.scripts = self.distribution.scripts
43
44     def get_source_files(self):
45         return self.scripts
46
47     def run (self):
48         if not self.scripts:
49             return
50         self.copy_scripts()
51
52
53     def copy_scripts (self):
54         """Copy each script listed in 'self.scripts'; if it's marked as a
55         Python script in the Unix way (first line matches 'first_line_re',
56         ie. starts with "\#!" and contains "python"), then adjust the first
57         line to refer to the current Python interpreter as we copy.
58         """
59         _sysconfig = __import__('sysconfig')
60         self.mkpath(self.build_dir)
61         outfiles = []
62         for script in self.scripts:
63             adjust = 0
64             script = convert_path(script)
65             outfile = os.path.join(self.build_dir, os.path.basename(script))
66             outfiles.append(outfile)
67
68             if not self.force and not newer(script, outfile):
69                 log.debug("not copying %s (up-to-date)", script)
70                 continue
71
72             # Always open the file, but ignore failures in dry-run mode --
73             # that way, we'll get accurate feedback if we can read the
74             # script.
75             try:
76                 f = open(script, "r")
77             except IOError:
78                 if not self.dry_run:
79                     raise
80                 f = None
81             else:
82                 first_line = f.readline()
83                 if not first_line:
84                     self.warn("%s is an empty file (skipping)" % script)
85                     continue
86
87                 match = first_line_re.match(first_line)
88                 if match:
89                     adjust = 1
90                     post_interp = match.group(1) or ''
91
92             if adjust:
93                 log.info("copying and adjusting %s -> %s", script,
94                          self.build_dir)
95                 if not self.dry_run:
96                     outf = open(outfile, "w")
97                     if not _sysconfig.is_python_build():
98                         outf.write("#!%s%s\n" %
99                                    (self.executable,
100                                     post_interp))
101                     else:
102                         outf.write("#!%s%s\n" %
103                                    (os.path.join(
104                             _sysconfig.get_config_var("BINDIR"),
105                            "python%s%s" % (_sysconfig.get_config_var("VERSION"),
106                                            _sysconfig.get_config_var("EXE"))),
107                                     post_interp))
108                     outf.writelines(f.readlines())
109                     outf.close()
110                 if f:
111                     f.close()
112             else:
113                 if f:
114                     f.close()
115                 self.copy_file(script, outfile)
116
117         if os.name == 'posix':
118             for file in outfiles:
119                 if self.dry_run:
120                     log.info("changing mode of %s", file)
121                 else:
122                     oldmode = os.stat(file)[ST_MODE] & 07777
123                     newmode = (oldmode | 0555) & 07777
124                     if newmode != oldmode:
125                         log.info("changing mode of %s from %o to %o",
126                                  file, oldmode, newmode)
127                         os.chmod(file, newmode)
128
129     # copy_scripts ()
130
131 # class build_scripts