blob: 36c4a68494d81b7354aa69cb2465924413b6214f [file] [log] [blame]
Greg Ward2689e3d1999-03-22 14:52:19 +00001"""distutils.util
2
Greg Wardaebf7062000-04-04 02:05:59 +00003Miscellaneous utility functions -- anything that doesn't fit into
Greg Ward47527692000-09-30 18:49:14 +00004one of the other *util.py modules.
5"""
Greg Ward2689e3d1999-03-22 14:52:19 +00006
Éric Araujo47a45212011-10-08 00:34:13 +02007import os
8import re
9import imp
10import sys
11import string
Jesus Cea8874fd62012-01-18 03:58:42 +010012import platform
Greg Ward1297b5c2000-09-30 20:37:56 +000013from distutils.errors import DistutilsPlatformError
14from distutils.dep_util import newer
Tarek Ziadé36797272010-07-22 12:50:05 +000015from distutils.spawn import spawn
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000016from distutils import log
Tarek Ziadé04fe7c02009-10-25 23:08:47 +000017from distutils.errors import DistutilsByteCompileError
Greg Wardaa458bc2000-04-22 15:14:58 +000018
Tarek Ziadé36797272010-07-22 12:50:05 +000019def get_platform ():
20 """Return a string that identifies the current platform. This is used
21 mainly to distinguish platform-specific build directories and
22 platform-specific built distributions. Typically includes the OS name
23 and version and the architecture (as supplied by 'os.uname()'),
24 although the exact information included depends on the OS; eg. for IRIX
25 the architecture isn't particularly important (IRIX only runs on SGI
26 hardware), but for Linux the kernel version isn't particularly
27 important.
Tarek Ziadé8b441d02010-01-29 11:46:31 +000028
Tarek Ziadé36797272010-07-22 12:50:05 +000029 Examples of returned values:
30 linux-i586
31 linux-alpha (?)
32 solaris-2.6-sun4u
33 irix-5.3
34 irix64-6.2
Tarek Ziadé8b441d02010-01-29 11:46:31 +000035
Tarek Ziadé36797272010-07-22 12:50:05 +000036 Windows will return one of:
37 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
38 win-ia64 (64bit Windows on Itanium)
39 win32 (all others - specifically, sys.platform is returned)
40
41 For other non-POSIX platforms, currently just returns 'sys.platform'.
Tarek Ziadé8b441d02010-01-29 11:46:31 +000042 """
Tarek Ziadé36797272010-07-22 12:50:05 +000043 if os.name == 'nt':
44 # sniff sys.version for architecture.
45 prefix = " bit ("
46 i = sys.version.find(prefix)
47 if i == -1:
48 return sys.platform
49 j = sys.version.find(")", i)
50 look = sys.version[i+len(prefix):j].lower()
51 if look == 'amd64':
52 return 'win-amd64'
53 if look == 'itanium':
54 return 'win-ia64'
55 return sys.platform
Tarek Ziadé8b441d02010-01-29 11:46:31 +000056
Tarek Ziadé36797272010-07-22 12:50:05 +000057 if os.name != "posix" or not hasattr(os, 'uname'):
58 # XXX what about the architecture? NT is Intel or Alpha,
59 # Mac OS is M68k or PPC, etc.
60 return sys.platform
Tarek Ziadé8b441d02010-01-29 11:46:31 +000061
Tarek Ziadé36797272010-07-22 12:50:05 +000062 # Try to distinguish various flavours of Unix
Greg Ward50919292000-03-07 03:27:08 +000063
Tarek Ziadé36797272010-07-22 12:50:05 +000064 (osname, host, release, version, machine) = os.uname()
Greg Ward50919292000-03-07 03:27:08 +000065
Tarek Ziadé36797272010-07-22 12:50:05 +000066 # Convert the OS name to lowercase, remove '/' characters
67 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
68 osname = osname.lower().replace('/', '')
69 machine = machine.replace(' ', '_')
70 machine = machine.replace('/', '-')
71
72 if osname[:5] == "linux":
73 # At least on Linux/Intel, 'machine' is the processor --
74 # i386, etc.
75 # XXX what about Alpha, SPARC, etc?
76 return "%s-%s" % (osname, machine)
77 elif osname[:5] == "sunos":
78 if release[0] >= "5": # SunOS 5 == Solaris 2
79 osname = "solaris"
80 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea8874fd62012-01-18 03:58:42 +010081 machine += ".%s" % platform.architecture()[0]
Tarek Ziadé36797272010-07-22 12:50:05 +000082 # fall through to standard osname-release-machine representation
83 elif osname[:4] == "irix": # could be "irix64"!
84 return "%s-%s" % (osname, release)
85 elif osname[:3] == "aix":
86 return "%s-%s.%s" % (osname, version, release)
87 elif osname[:6] == "cygwin":
88 osname = "cygwin"
89 rel_re = re.compile (r'[\d.]+', re.ASCII)
90 m = rel_re.match(release)
91 if m:
92 release = m.group()
93 elif osname[:6] == "darwin":
94 #
95 # For our purposes, we'll assume that the system version from
96 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
97 # to. This makes the compatibility story a bit more sane because the
98 # machine is going to compile and link as if it were
99 # MACOSX_DEPLOYMENT_TARGET.
100 from distutils.sysconfig import get_config_vars
101 cfgvars = get_config_vars()
102
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200103 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
Tarek Ziadé36797272010-07-22 12:50:05 +0000104
105 if 1:
106 # Always calculate the release of the running machine,
107 # needed to determine if we can build fat binaries or not.
108
109 macrelease = macver
110 # Get the system version. Reading this plist is a documented
111 # way to get the system version (see the documentation for
112 # the Gestalt Manager)
113 try:
114 f = open('/System/Library/CoreServices/SystemVersion.plist')
115 except IOError:
116 # We're on a plain darwin box, fall back to the default
117 # behaviour.
118 pass
119 else:
Éric Araujobee5cef2010-11-05 23:51:56 +0000120 try:
121 m = re.search(
122 r'<key>ProductUserVisibleVersion</key>\s*' +
123 r'<string>(.*?)</string>', f.read())
124 if m is not None:
125 macrelease = '.'.join(m.group(1).split('.')[:2])
126 # else: fall back to the default behaviour
127 finally:
128 f.close()
Tarek Ziadé36797272010-07-22 12:50:05 +0000129
130 if not macver:
131 macver = macrelease
132
133 if macver:
134 from distutils.sysconfig import get_config_vars
135 release = macver
136 osname = "macosx"
137
138 if (macrelease + '.') >= '10.4.' and \
139 '-arch' in get_config_vars().get('CFLAGS', '').strip():
140 # The universal build will build fat binaries, but not on
141 # systems before 10.4
142 #
143 # Try to detect 4-way universal builds, those have machine-type
144 # 'universal' instead of 'fat'.
145
146 machine = 'fat'
147 cflags = get_config_vars().get('CFLAGS')
148
149 archs = re.findall('-arch\s+(\S+)', cflags)
150 archs = tuple(sorted(set(archs)))
151
152 if len(archs) == 1:
153 machine = archs[0]
154 elif archs == ('i386', 'ppc'):
155 machine = 'fat'
156 elif archs == ('i386', 'x86_64'):
157 machine = 'intel'
158 elif archs == ('i386', 'ppc', 'x86_64'):
159 machine = 'fat3'
160 elif archs == ('ppc64', 'x86_64'):
161 machine = 'fat64'
162 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
163 machine = 'universal'
164 else:
165 raise ValueError(
166 "Don't know machine value for archs=%r"%(archs,))
167
168 elif machine == 'i386':
169 # On OSX the machine type returned by uname is always the
170 # 32-bit variant, even if the executable architecture is
171 # the 64-bit variant
172 if sys.maxsize >= 2**32:
173 machine = 'x86_64'
174
175 elif machine in ('PowerPC', 'Power_Macintosh'):
176 # Pick a sane name for the PPC architecture.
177 machine = 'ppc'
178
179 # See 'i386' case
180 if sys.maxsize >= 2**32:
181 machine = 'ppc64'
182
183 return "%s-%s-%s" % (osname, release, machine)
184
185# get_platform ()
186
187
188def convert_path (pathname):
189 """Return 'pathname' as a name that will work on the native filesystem,
Greg Wardb8b263b2000-09-30 18:40:42 +0000190 i.e. split it on '/' and put it back together again using the current
191 directory separator. Needed because filenames in the setup script are
192 always supplied in Unix style, and have to be converted to the local
193 convention before we can actually use them in the filesystem. Raises
Greg Ward47527692000-09-30 18:49:14 +0000194 ValueError on non-Unix-ish systems if 'pathname' either starts or
195 ends with a slash.
Greg Wardb8b263b2000-09-30 18:40:42 +0000196 """
Greg Ward7ec05352000-09-22 01:05:43 +0000197 if os.sep == '/':
198 return pathname
Neal Norwitzb0df6a12002-08-13 17:42:57 +0000199 if not pathname:
200 return pathname
201 if pathname[0] == '/':
Collin Winter5b7e9d72007-08-30 03:52:21 +0000202 raise ValueError("path '%s' cannot be absolute" % pathname)
Neal Norwitzb0df6a12002-08-13 17:42:57 +0000203 if pathname[-1] == '/':
Collin Winter5b7e9d72007-08-30 03:52:21 +0000204 raise ValueError("path '%s' cannot end with '/'" % pathname)
Greg Ward7ec05352000-09-22 01:05:43 +0000205
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000206 paths = pathname.split('/')
Jack Jansenb4cd5c12001-01-28 12:23:32 +0000207 while '.' in paths:
208 paths.remove('.')
209 if not paths:
210 return os.curdir
Neal Norwitzd9108552006-03-17 08:00:19 +0000211 return os.path.join(*paths)
Greg Ward50919292000-03-07 03:27:08 +0000212
Tarek Ziadé36797272010-07-22 12:50:05 +0000213# convert_path ()
Greg Ward1b4ede52000-03-22 00:22:44 +0000214
215
Tarek Ziadé36797272010-07-22 12:50:05 +0000216def change_root (new_root, pathname):
217 """Return 'pathname' with 'new_root' prepended. If 'pathname' is
218 relative, this is equivalent to "os.path.join(new_root,pathname)".
Greg Ward67f75d42000-04-27 01:53:46 +0000219 Otherwise, it requires making 'pathname' relative and then joining the
Greg Ward4b46ef92000-05-31 02:14:32 +0000220 two, which is tricky on DOS/Windows and Mac OS.
221 """
222 if os.name == 'posix':
Greg Wardbe86bde2000-09-26 01:56:15 +0000223 if not os.path.isabs(pathname):
224 return os.path.join(new_root, pathname)
Greg Ward4b46ef92000-05-31 02:14:32 +0000225 else:
Greg Wardbe86bde2000-09-26 01:56:15 +0000226 return os.path.join(new_root, pathname[1:])
Greg Ward67f75d42000-04-27 01:53:46 +0000227
228 elif os.name == 'nt':
Greg Wardbe86bde2000-09-26 01:56:15 +0000229 (drive, path) = os.path.splitdrive(pathname)
Greg Ward4b46ef92000-05-31 02:14:32 +0000230 if path[0] == '\\':
231 path = path[1:]
Greg Wardbe86bde2000-09-26 01:56:15 +0000232 return os.path.join(new_root, path)
Greg Ward67f75d42000-04-27 01:53:46 +0000233
Marc-André Lemburg2544f512002-01-31 18:56:00 +0000234 elif os.name == 'os2':
235 (drive, path) = os.path.splitdrive(pathname)
236 if path[0] == os.sep:
237 path = path[1:]
238 return os.path.join(new_root, path)
239
Greg Ward67f75d42000-04-27 01:53:46 +0000240 else:
Tarek Ziadé36797272010-07-22 12:50:05 +0000241 raise DistutilsPlatformError("nothing known about platform '%s'" % os.name)
242
Greg Ward67f75d42000-04-27 01:53:46 +0000243
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000244_environ_checked = 0
Tarek Ziadé36797272010-07-22 12:50:05 +0000245def check_environ ():
246 """Ensure that 'os.environ' has all the environment variables we
247 guarantee that users can use in config files, command-line options,
Greg Wardb8b263b2000-09-30 18:40:42 +0000248 etc. Currently this includes:
249 HOME - user's home directory (Unix only)
250 PLAT - description of the current platform, including hardware
251 and OS (see 'get_platform()')
Greg Ward1b4ede52000-03-22 00:22:44 +0000252 """
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000253 global _environ_checked
254 if _environ_checked:
255 return
256
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000257 if os.name == 'posix' and 'HOME' not in os.environ:
Greg Ward1b4ede52000-03-22 00:22:44 +0000258 import pwd
Greg Wardbe86bde2000-09-26 01:56:15 +0000259 os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
Greg Ward1b4ede52000-03-22 00:22:44 +0000260
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000261 if 'PLAT' not in os.environ:
Tarek Ziadé36797272010-07-22 12:50:05 +0000262 os.environ['PLAT'] = get_platform()
Greg Ward1b4ede52000-03-22 00:22:44 +0000263
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000264 _environ_checked = 1
265
Greg Ward1b4ede52000-03-22 00:22:44 +0000266
Tarek Ziadé36797272010-07-22 12:50:05 +0000267def subst_vars (s, local_vars):
268 """Perform shell/Perl-style variable substitution on 'string'. Every
269 occurrence of '$' followed by a name is considered a variable, and
Greg Ward47527692000-09-30 18:49:14 +0000270 variable is substituted by the value found in the 'local_vars'
271 dictionary, or in 'os.environ' if it's not in 'local_vars'.
272 'os.environ' is first checked/augmented to guarantee that it contains
273 certain values: see 'check_environ()'. Raise ValueError for any
274 variables not found in either 'local_vars' or 'os.environ'.
Greg Wardb8b263b2000-09-30 18:40:42 +0000275 """
Greg Wardbe86bde2000-09-26 01:56:15 +0000276 check_environ()
Greg Ward1b4ede52000-03-22 00:22:44 +0000277 def _subst (match, local_vars=local_vars):
278 var_name = match.group(1)
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000279 if var_name in local_vars:
Greg Wardbe86bde2000-09-26 01:56:15 +0000280 return str(local_vars[var_name])
Greg Ward1b4ede52000-03-22 00:22:44 +0000281 else:
282 return os.environ[var_name]
283
Greg Ward47527692000-09-30 18:49:14 +0000284 try:
Jeremy Hylton5e2d0762001-01-25 20:10:32 +0000285 return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
Guido van Rossumb940e112007-01-10 16:19:56 +0000286 except KeyError as var:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000287 raise ValueError("invalid variable '$%s'" % var)
Greg Ward1b4ede52000-03-22 00:22:44 +0000288
Tarek Ziadé36797272010-07-22 12:50:05 +0000289# subst_vars ()
Greg Ward7c1a6d42000-03-29 02:48:40 +0000290
Tarek Ziadé36797272010-07-22 12:50:05 +0000291
292def grok_environment_error (exc, prefix="error: "):
293 """Generate a useful error message from an EnvironmentError (IOError or
294 OSError) exception object. Handles Python 1.5.1 and 1.5.2 styles, and
Greg Warde9055132000-06-17 02:16:46 +0000295 does what it can to deal with exception objects that don't have a
296 filename (which happens when the error is due to a two-file operation,
297 such as 'rename()' or 'link()'. Returns the error message as a string
298 prefixed with 'prefix'.
299 """
300 # check for Python 1.5.2-style {IO,OS}Error exception objects
Greg Wardbe86bde2000-09-26 01:56:15 +0000301 if hasattr(exc, 'filename') and hasattr(exc, 'strerror'):
Greg Warde9055132000-06-17 02:16:46 +0000302 if exc.filename:
303 error = prefix + "%s: %s" % (exc.filename, exc.strerror)
304 else:
305 # two-argument functions in posix module don't
306 # include the filename in the exception object!
307 error = prefix + "%s" % exc.strerror
308 else:
Georg Brandl5dfe0de2008-01-06 21:41:49 +0000309 error = prefix + str(exc.args[-1])
Greg Warde9055132000-06-17 02:16:46 +0000310
311 return error
Greg Ward6a2a3db2000-06-24 20:40:02 +0000312
Tarek Ziadé36797272010-07-22 12:50:05 +0000313
Greg Ward6a2a3db2000-06-24 20:40:02 +0000314# Needed by 'split_quoted()'
Martin v. Löwis1c0f1f92004-03-25 14:58:19 +0000315_wordchars_re = _squote_re = _dquote_re = None
316def _init_regex():
317 global _wordchars_re, _squote_re, _dquote_re
318 _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
319 _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
320 _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
Greg Ward6a2a3db2000-06-24 20:40:02 +0000321
Tarek Ziadé36797272010-07-22 12:50:05 +0000322def split_quoted (s):
Greg Ward6a2a3db2000-06-24 20:40:02 +0000323 """Split a string up according to Unix shell-like rules for quotes and
Tarek Ziadé36797272010-07-22 12:50:05 +0000324 backslashes. In short: words are delimited by spaces, as long as those
Greg Ward6a2a3db2000-06-24 20:40:02 +0000325 spaces are not escaped by a backslash, or inside a quoted string.
326 Single and double quotes are equivalent, and the quote characters can
327 be backslash-escaped. The backslash is stripped from any two-character
328 escape sequence, leaving only the escaped character. The quote
329 characters are stripped from any quoted string. Returns a list of
330 words.
331 """
Tarek Ziadé36797272010-07-22 12:50:05 +0000332
Greg Ward6a2a3db2000-06-24 20:40:02 +0000333 # This is a nice algorithm for splitting up a single string, since it
334 # doesn't require character-by-character examination. It was a little
335 # bit of a brain-bender to get it working right, though...
Martin v. Löwis1c0f1f92004-03-25 14:58:19 +0000336 if _wordchars_re is None: _init_regex()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000337
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000338 s = s.strip()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000339 words = []
340 pos = 0
341
342 while s:
343 m = _wordchars_re.match(s, pos)
344 end = m.end()
345 if end == len(s):
346 words.append(s[:end])
347 break
348
Greg Ward2b042de2000-08-08 14:38:13 +0000349 if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
Greg Ward6a2a3db2000-06-24 20:40:02 +0000350 words.append(s[:end]) # we definitely have a word delimiter
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000351 s = s[end:].lstrip()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000352 pos = 0
353
354 elif s[end] == '\\': # preserve whatever is being escaped;
355 # will become part of the current word
356 s = s[:end] + s[end+1:]
357 pos = end+1
358
359 else:
360 if s[end] == "'": # slurp singly-quoted string
361 m = _squote_re.match(s, end)
362 elif s[end] == '"': # slurp doubly-quoted string
363 m = _dquote_re.match(s, end)
364 else:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000365 raise RuntimeError("this can't happen (bad char '%c')" % s[end])
Greg Ward6a2a3db2000-06-24 20:40:02 +0000366
367 if m is None:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000368 raise ValueError("bad string (mismatched %s quotes?)" % s[end])
Greg Ward6a2a3db2000-06-24 20:40:02 +0000369
370 (beg, end) = m.span()
371 s = s[:beg] + s[beg+1:end-1] + s[end:]
372 pos = m.end() - 2
373
374 if pos >= len(s):
375 words.append(s)
376 break
377
378 return words
379
Tarek Ziadé36797272010-07-22 12:50:05 +0000380# split_quoted ()
Greg Ward1c16ac32000-08-02 01:37:30 +0000381
382
Tarek Ziadé36797272010-07-22 12:50:05 +0000383def execute (func, args, msg=None, verbose=0, dry_run=0):
384 """Perform some action that affects the outside world (eg. by
385 writing to the filesystem). Such actions are special because they
386 are disabled by the 'dry_run' flag. This method takes care of all
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000387 that bureaucracy for you; all you have to do is supply the
388 function to call and an argument tuple for it (to embody the
389 "external action" being performed), and an optional message to
390 print.
Greg Ward1c16ac32000-08-02 01:37:30 +0000391 """
Greg Ward1c16ac32000-08-02 01:37:30 +0000392 if msg is None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000393 msg = "%s%r" % (func.__name__, args)
Fred Drakeb94b8492001-12-06 20:51:35 +0000394 if msg[-2:] == ',)': # correct for singleton tuple
Greg Ward1c16ac32000-08-02 01:37:30 +0000395 msg = msg[0:-2] + ')'
396
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000397 log.info(msg)
Greg Ward1c16ac32000-08-02 01:37:30 +0000398 if not dry_run:
Neal Norwitzd9108552006-03-17 08:00:19 +0000399 func(*args)
Greg Ward1c16ac32000-08-02 01:37:30 +0000400
Greg Ward817dc092000-09-25 01:25:06 +0000401
Tarek Ziadé36797272010-07-22 12:50:05 +0000402def strtobool (val):
Greg Ward817dc092000-09-25 01:25:06 +0000403 """Convert a string representation of truth to true (1) or false (0).
Tim Peters182b5ac2004-07-18 06:16:08 +0000404
Greg Ward817dc092000-09-25 01:25:06 +0000405 True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
406 are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
407 'val' is anything else.
408 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000409 val = val.lower()
Greg Ward817dc092000-09-25 01:25:06 +0000410 if val in ('y', 'yes', 't', 'true', 'on', '1'):
411 return 1
412 elif val in ('n', 'no', 'f', 'false', 'off', '0'):
413 return 0
414 else:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000415 raise ValueError("invalid truth value %r" % (val,))
Greg Ward1297b5c2000-09-30 20:37:56 +0000416
417
Tarek Ziadé36797272010-07-22 12:50:05 +0000418def byte_compile (py_files,
419 optimize=0, force=0,
420 prefix=None, base_dir=None,
421 verbose=1, dry_run=0,
422 direct=None):
Greg Wardf217e212000-10-01 23:49:30 +0000423 """Byte-compile a collection of Python source files to either .pyc
Éric Araujo04ea9532011-10-08 03:02:37 +0200424 or .pyo files in a __pycache__ subdirectory. 'py_files' is a list
425 of files to compile; any files that don't end in ".py" are silently
426 skipped. 'optimize' must be one of the following:
Greg Ward1297b5c2000-09-30 20:37:56 +0000427 0 - don't optimize (generate .pyc)
428 1 - normal optimization (like "python -O")
429 2 - extra optimization (like "python -OO")
430 If 'force' is true, all files are recompiled regardless of
431 timestamps.
432
433 The source filename encoded in each bytecode file defaults to the
434 filenames listed in 'py_files'; you can modify these with 'prefix' and
435 'basedir'. 'prefix' is a string that will be stripped off of each
436 source filename, and 'base_dir' is a directory name that will be
437 prepended (after 'prefix' is stripped). You can supply either or both
438 (or neither) of 'prefix' and 'base_dir', as you wish.
439
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000440 If 'dry_run' is true, doesn't actually do anything that would
441 affect the filesystem.
Greg Ward1297b5c2000-09-30 20:37:56 +0000442
443 Byte-compilation is either done directly in this interpreter process
444 with the standard py_compile module, or indirectly by writing a
445 temporary script and executing it. Normally, you should let
446 'byte_compile()' figure out to use direct compilation or not (see
447 the source for details). The 'direct' flag is used by the script
448 generated in indirect mode; unless you know what you're doing, leave
449 it set to None.
450 """
Tarek Ziadé04fe7c02009-10-25 23:08:47 +0000451 # nothing is done if sys.dont_write_bytecode is True
452 if sys.dont_write_bytecode:
453 raise DistutilsByteCompileError('byte-compiling is disabled.')
454
Greg Ward1297b5c2000-09-30 20:37:56 +0000455 # First, if the caller didn't force us into direct or indirect mode,
456 # figure out which mode we should be in. We take a conservative
457 # approach: choose direct mode *only* if the current interpreter is
458 # in debug mode and optimize is 0. If we're not in debug mode (-O
459 # or -OO), we don't know which level of optimization this
460 # interpreter is running with, so we can't do direct
461 # byte-compilation and be certain that it's the right thing. Thus,
462 # always compile indirectly if the current interpreter is in either
463 # optimize mode, or if either optimization level was requested by
464 # the caller.
465 if direct is None:
466 direct = (__debug__ and optimize == 0)
467
468 # "Indirect" byte-compilation: write a temporary script and then
469 # run it with the appropriate flags.
470 if not direct:
Marc-André Lemburg03750792002-12-03 08:45:11 +0000471 try:
472 from tempfile import mkstemp
473 (script_fd, script_name) = mkstemp(".py")
474 except ImportError:
475 from tempfile import mktemp
476 (script_fd, script_name) = None, mktemp(".py")
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000477 log.info("writing byte-compilation script '%s'", script_name)
Greg Ward1297b5c2000-09-30 20:37:56 +0000478 if not dry_run:
Marc-André Lemburg03750792002-12-03 08:45:11 +0000479 if script_fd is not None:
480 script = os.fdopen(script_fd, "w")
481 else:
482 script = open(script_name, "w")
Greg Ward1297b5c2000-09-30 20:37:56 +0000483
484 script.write("""\
485from distutils.util import byte_compile
486files = [
487""")
Greg Ward9216cfe2000-10-03 03:31:05 +0000488
489 # XXX would be nice to write absolute filenames, just for
490 # safety's sake (script should be more robust in the face of
491 # chdir'ing before running it). But this requires abspath'ing
492 # 'prefix' as well, and that breaks the hack in build_lib's
493 # 'byte_compile()' method that carefully tacks on a trailing
494 # slash (os.sep really) to make sure the prefix here is "just
495 # right". This whole prefix business is rather delicate -- the
496 # problem is that it's really a directory, but I'm treating it
497 # as a dumb string, so trailing slashes and so forth matter.
498
499 #py_files = map(os.path.abspath, py_files)
500 #if prefix:
501 # prefix = os.path.abspath(prefix)
502
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000503 script.write(",\n".join(map(repr, py_files)) + "]\n")
Greg Ward1297b5c2000-09-30 20:37:56 +0000504 script.write("""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000505byte_compile(files, optimize=%r, force=%r,
506 prefix=%r, base_dir=%r,
507 verbose=%r, dry_run=0,
Greg Ward1297b5c2000-09-30 20:37:56 +0000508 direct=1)
Walter Dörwald70a6b492004-02-12 17:35:32 +0000509""" % (optimize, force, prefix, base_dir, verbose))
Greg Ward1297b5c2000-09-30 20:37:56 +0000510
511 script.close()
512
513 cmd = [sys.executable, script_name]
514 if optimize == 1:
515 cmd.insert(1, "-O")
516 elif optimize == 2:
517 cmd.insert(1, "-OO")
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000518 spawn(cmd, dry_run=dry_run)
Greg Ward9216cfe2000-10-03 03:31:05 +0000519 execute(os.remove, (script_name,), "removing %s" % script_name,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000520 dry_run=dry_run)
Fred Drakeb94b8492001-12-06 20:51:35 +0000521
Greg Ward1297b5c2000-09-30 20:37:56 +0000522 # "Direct" byte-compilation: use the py_compile module to compile
523 # right here, right now. Note that the script generated in indirect
524 # mode simply calls 'byte_compile()' in direct mode, a weird sort of
525 # cross-process recursion. Hey, it works!
526 else:
527 from py_compile import compile
528
529 for file in py_files:
530 if file[-3:] != ".py":
Greg Wardf217e212000-10-01 23:49:30 +0000531 # This lets us be lazy and not filter filenames in
532 # the "install_lib" command.
533 continue
Greg Ward1297b5c2000-09-30 20:37:56 +0000534
535 # Terminology from the py_compile module:
536 # cfile - byte-compiled file
537 # dfile - purported source filename (same as 'file' by default)
Éric Araujo47a45212011-10-08 00:34:13 +0200538 if optimize >= 0:
539 cfile = imp.cache_from_source(file, debug_override=not optimize)
540 else:
541 cfile = imp.cache_from_source(file)
Greg Ward1297b5c2000-09-30 20:37:56 +0000542 dfile = file
543 if prefix:
544 if file[:len(prefix)] != prefix:
Tarek Ziadé36797272010-07-22 12:50:05 +0000545 raise ValueError("invalid prefix: filename %r doesn't start with %r"
546 % (file, prefix))
Greg Ward1297b5c2000-09-30 20:37:56 +0000547 dfile = dfile[len(prefix):]
548 if base_dir:
549 dfile = os.path.join(base_dir, dfile)
550
551 cfile_base = os.path.basename(cfile)
552 if direct:
553 if force or newer(file, cfile):
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000554 log.info("byte-compiling %s to %s", file, cfile_base)
Greg Ward1297b5c2000-09-30 20:37:56 +0000555 if not dry_run:
556 compile(file, cfile, dfile)
557 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000558 log.debug("skipping byte-compilation of %s to %s",
559 file, cfile_base)
Greg Ward1297b5c2000-09-30 20:37:56 +0000560
Tarek Ziadé36797272010-07-22 12:50:05 +0000561# byte_compile ()
Andrew M. Kuchlingdf66df02001-03-22 03:03:41 +0000562
Tarek Ziadé36797272010-07-22 12:50:05 +0000563def rfc822_escape (header):
Andrew M. Kuchlingdf66df02001-03-22 03:03:41 +0000564 """Return a version of the string escaped for inclusion in an
Andrew M. Kuchling88b08842001-03-23 17:30:26 +0000565 RFC-822 header, by ensuring there are 8 spaces space after each newline.
Andrew M. Kuchlingdf66df02001-03-22 03:03:41 +0000566 """
Tarek Ziadédf872d42009-12-06 09:28:17 +0000567 lines = header.split('\n')
568 sep = '\n' + 8 * ' '
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000569 return sep.join(lines)
Martin v. Löwis6178db62008-12-01 04:38:52 +0000570
571# 2to3 support
572
573def run_2to3(files, fixer_names=None, options=None, explicit=None):
574 """Invoke 2to3 on a list of Python files.
575 The files should all come from the build area, as the
576 modification is done in-place. To reduce the build time,
577 only files modified since the last invocation of this
578 function should be passed in the files argument."""
579
580 if not files:
581 return
582
583 # Make this class local, to delay import of 2to3
584 from lib2to3.refactor import RefactoringTool, get_fixers_from_package
585 class DistutilsRefactoringTool(RefactoringTool):
586 def log_error(self, msg, *args, **kw):
587 log.error(msg, *args)
588
589 def log_message(self, msg, *args):
590 log.info(msg, *args)
591
592 def log_debug(self, msg, *args):
593 log.debug(msg, *args)
594
595 if fixer_names is None:
596 fixer_names = get_fixers_from_package('lib2to3.fixes')
597 r = DistutilsRefactoringTool(fixer_names, options=options)
598 r.refactor(files, write=True)
599
Georg Brandl6d4a9cf2009-03-31 00:34:54 +0000600def copydir_run_2to3(src, dest, template=None, fixer_names=None,
601 options=None, explicit=None):
602 """Recursively copy a directory, only copying new and changed files,
603 running run_2to3 over all newly copied Python modules afterward.
604
605 If you give a template string, it's parsed like a MANIFEST.in.
606 """
607 from distutils.dir_util import mkpath
608 from distutils.file_util import copy_file
609 from distutils.filelist import FileList
610 filelist = FileList()
611 curdir = os.getcwd()
612 os.chdir(src)
613 try:
614 filelist.findall()
615 finally:
616 os.chdir(curdir)
617 filelist.files[:] = filelist.allfiles
618 if template:
619 for line in template.splitlines():
620 line = line.strip()
621 if not line: continue
622 filelist.process_template_line(line)
623 copied = []
624 for filename in filelist.files:
625 outname = os.path.join(dest, filename)
626 mkpath(os.path.dirname(outname))
627 res = copy_file(os.path.join(src, filename), outname, update=1)
628 if res[1]: copied.append(outname)
629 run_2to3([fn for fn in copied if fn.lower().endswith('.py')],
630 fixer_names=fixer_names, options=options, explicit=explicit)
631 return copied
632
Martin v. Löwis6178db62008-12-01 04:38:52 +0000633class Mixin2to3:
634 '''Mixin class for commands that run 2to3.
635 To configure 2to3, setup scripts may either change
636 the class variables, or inherit from individual commands
637 to override how 2to3 is invoked.'''
638
639 # provide list of fixers to run;
640 # defaults to all from lib2to3.fixers
641 fixer_names = None
642
643 # options dictionary
644 options = None
645
646 # list of fixers to invoke even though they are marked as explicit
647 explicit = None
648
649 def run_2to3(self, files):
650 return run_2to3(files, self.fixer_names, self.options, self.explicit)