blob: 83682628ba680cfc261c0aeb81d9bf0043c8554d [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
Brett Cannon61c35562013-06-15 12:59:53 -04009import importlib.util
Éric Araujo47a45212011-10-08 00:34:13 +020010import string
Victor Stinner9def2842016-01-18 12:15:08 +010011import sys
Greg Ward1297b5c2000-09-30 20:37:56 +000012from distutils.errors import DistutilsPlatformError
13from distutils.dep_util import newer
Tarek Ziadé36797272010-07-22 12:50:05 +000014from distutils.spawn import spawn
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000015from distutils import log
Tarek Ziadé04fe7c02009-10-25 23:08:47 +000016from distutils.errors import DistutilsByteCompileError
Greg Wardaa458bc2000-04-22 15:14:58 +000017
Tarek Ziadé36797272010-07-22 12:50:05 +000018def get_platform ():
Benjamin Peterson06930632017-09-04 16:36:05 -070019 """Return a string that identifies the current platform. This is used mainly to
20 distinguish platform-specific build directories and platform-specific built
21 distributions. Typically includes the OS name and version and the
22 architecture (as supplied by 'os.uname()'), although the exact information
23 included depends on the OS; eg. on Linux, the kernel version isn't
24 particularly important.
Tarek Ziadé8b441d02010-01-29 11:46:31 +000025
Tarek Ziadé36797272010-07-22 12:50:05 +000026 Examples of returned values:
27 linux-i586
28 linux-alpha (?)
29 solaris-2.6-sun4u
Tarek Ziadé8b441d02010-01-29 11:46:31 +000030
Tarek Ziadé36797272010-07-22 12:50:05 +000031 Windows will return one of:
32 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
Tarek Ziadé36797272010-07-22 12:50:05 +000033 win32 (all others - specifically, sys.platform is returned)
34
35 For other non-POSIX platforms, currently just returns 'sys.platform'.
Benjamin Peterson06930632017-09-04 16:36:05 -070036
Tarek Ziadé8b441d02010-01-29 11:46:31 +000037 """
Tarek Ziadé36797272010-07-22 12:50:05 +000038 if os.name == 'nt':
Zachary Ware49ce74e2017-09-06 15:45:25 -070039 if 'amd64' in sys.version.lower():
Tarek Ziadé36797272010-07-22 12:50:05 +000040 return 'win-amd64'
Tarek Ziadé36797272010-07-22 12:50:05 +000041 return sys.platform
Tarek Ziadé8b441d02010-01-29 11:46:31 +000042
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +020043 # Set for cross builds explicitly
44 if "_PYTHON_HOST_PLATFORM" in os.environ:
45 return os.environ["_PYTHON_HOST_PLATFORM"]
46
Tarek Ziadé36797272010-07-22 12:50:05 +000047 if os.name != "posix" or not hasattr(os, 'uname'):
48 # XXX what about the architecture? NT is Intel or Alpha,
49 # Mac OS is M68k or PPC, etc.
50 return sys.platform
Tarek Ziadé8b441d02010-01-29 11:46:31 +000051
Tarek Ziadé36797272010-07-22 12:50:05 +000052 # Try to distinguish various flavours of Unix
Greg Ward50919292000-03-07 03:27:08 +000053
Tarek Ziadé36797272010-07-22 12:50:05 +000054 (osname, host, release, version, machine) = os.uname()
Greg Ward50919292000-03-07 03:27:08 +000055
Benjamin Peterson288d1da2017-09-28 22:44:27 -070056 # Convert the OS name to lowercase, remove '/' characters, and translate
57 # spaces (for "Power Macintosh")
Tarek Ziadé36797272010-07-22 12:50:05 +000058 osname = osname.lower().replace('/', '')
59 machine = machine.replace(' ', '_')
60 machine = machine.replace('/', '-')
61
62 if osname[:5] == "linux":
63 # At least on Linux/Intel, 'machine' is the processor --
64 # i386, etc.
65 # XXX what about Alpha, SPARC, etc?
66 return "%s-%s" % (osname, machine)
67 elif osname[:5] == "sunos":
68 if release[0] >= "5": # SunOS 5 == Solaris 2
69 osname = "solaris"
70 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea6e35d412012-01-18 04:27:37 +010071 # We can't use "platform.architecture()[0]" because a
72 # bootstrap problem. We use a dict to get an error
73 # if some suspicious happens.
74 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +010075 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadé36797272010-07-22 12:50:05 +000076 # fall through to standard osname-release-machine representation
Tarek Ziadé36797272010-07-22 12:50:05 +000077 elif osname[:3] == "aix":
78 return "%s-%s.%s" % (osname, version, release)
79 elif osname[:6] == "cygwin":
80 osname = "cygwin"
81 rel_re = re.compile (r'[\d.]+', re.ASCII)
82 m = rel_re.match(release)
83 if m:
84 release = m.group()
85 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -070086 import _osx_support, distutils.sysconfig
87 osname, release, machine = _osx_support.get_platform_osx(
88 distutils.sysconfig.get_config_vars(),
89 osname, release, machine)
Tarek Ziadé36797272010-07-22 12:50:05 +000090
91 return "%s-%s-%s" % (osname, release, machine)
92
93# get_platform ()
94
95
96def convert_path (pathname):
97 """Return 'pathname' as a name that will work on the native filesystem,
Greg Wardb8b263b2000-09-30 18:40:42 +000098 i.e. split it on '/' and put it back together again using the current
99 directory separator. Needed because filenames in the setup script are
100 always supplied in Unix style, and have to be converted to the local
101 convention before we can actually use them in the filesystem. Raises
Greg Ward47527692000-09-30 18:49:14 +0000102 ValueError on non-Unix-ish systems if 'pathname' either starts or
103 ends with a slash.
Greg Wardb8b263b2000-09-30 18:40:42 +0000104 """
Greg Ward7ec05352000-09-22 01:05:43 +0000105 if os.sep == '/':
106 return pathname
Neal Norwitzb0df6a12002-08-13 17:42:57 +0000107 if not pathname:
108 return pathname
109 if pathname[0] == '/':
Collin Winter5b7e9d72007-08-30 03:52:21 +0000110 raise ValueError("path '%s' cannot be absolute" % pathname)
Neal Norwitzb0df6a12002-08-13 17:42:57 +0000111 if pathname[-1] == '/':
Collin Winter5b7e9d72007-08-30 03:52:21 +0000112 raise ValueError("path '%s' cannot end with '/'" % pathname)
Greg Ward7ec05352000-09-22 01:05:43 +0000113
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000114 paths = pathname.split('/')
Jack Jansenb4cd5c12001-01-28 12:23:32 +0000115 while '.' in paths:
116 paths.remove('.')
117 if not paths:
118 return os.curdir
Neal Norwitzd9108552006-03-17 08:00:19 +0000119 return os.path.join(*paths)
Greg Ward50919292000-03-07 03:27:08 +0000120
Tarek Ziadé36797272010-07-22 12:50:05 +0000121# convert_path ()
Greg Ward1b4ede52000-03-22 00:22:44 +0000122
123
Tarek Ziadé36797272010-07-22 12:50:05 +0000124def change_root (new_root, pathname):
125 """Return 'pathname' with 'new_root' prepended. If 'pathname' is
126 relative, this is equivalent to "os.path.join(new_root,pathname)".
Greg Ward67f75d42000-04-27 01:53:46 +0000127 Otherwise, it requires making 'pathname' relative and then joining the
Greg Ward4b46ef92000-05-31 02:14:32 +0000128 two, which is tricky on DOS/Windows and Mac OS.
129 """
130 if os.name == 'posix':
Greg Wardbe86bde2000-09-26 01:56:15 +0000131 if not os.path.isabs(pathname):
132 return os.path.join(new_root, pathname)
Greg Ward4b46ef92000-05-31 02:14:32 +0000133 else:
Greg Wardbe86bde2000-09-26 01:56:15 +0000134 return os.path.join(new_root, pathname[1:])
Greg Ward67f75d42000-04-27 01:53:46 +0000135
136 elif os.name == 'nt':
Greg Wardbe86bde2000-09-26 01:56:15 +0000137 (drive, path) = os.path.splitdrive(pathname)
Greg Ward4b46ef92000-05-31 02:14:32 +0000138 if path[0] == '\\':
139 path = path[1:]
Greg Wardbe86bde2000-09-26 01:56:15 +0000140 return os.path.join(new_root, path)
Greg Ward67f75d42000-04-27 01:53:46 +0000141
Greg Ward67f75d42000-04-27 01:53:46 +0000142 else:
Tarek Ziadé36797272010-07-22 12:50:05 +0000143 raise DistutilsPlatformError("nothing known about platform '%s'" % os.name)
144
Greg Ward67f75d42000-04-27 01:53:46 +0000145
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000146_environ_checked = 0
Tarek Ziadé36797272010-07-22 12:50:05 +0000147def check_environ ():
148 """Ensure that 'os.environ' has all the environment variables we
149 guarantee that users can use in config files, command-line options,
Greg Wardb8b263b2000-09-30 18:40:42 +0000150 etc. Currently this includes:
151 HOME - user's home directory (Unix only)
152 PLAT - description of the current platform, including hardware
153 and OS (see 'get_platform()')
Greg Ward1b4ede52000-03-22 00:22:44 +0000154 """
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000155 global _environ_checked
156 if _environ_checked:
157 return
158
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000159 if os.name == 'posix' and 'HOME' not in os.environ:
Greg Ward1b4ede52000-03-22 00:22:44 +0000160 import pwd
Greg Wardbe86bde2000-09-26 01:56:15 +0000161 os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
Greg Ward1b4ede52000-03-22 00:22:44 +0000162
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000163 if 'PLAT' not in os.environ:
Tarek Ziadé36797272010-07-22 12:50:05 +0000164 os.environ['PLAT'] = get_platform()
Greg Ward1b4ede52000-03-22 00:22:44 +0000165
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000166 _environ_checked = 1
167
Greg Ward1b4ede52000-03-22 00:22:44 +0000168
Tarek Ziadé36797272010-07-22 12:50:05 +0000169def subst_vars (s, local_vars):
170 """Perform shell/Perl-style variable substitution on 'string'. Every
171 occurrence of '$' followed by a name is considered a variable, and
Greg Ward47527692000-09-30 18:49:14 +0000172 variable is substituted by the value found in the 'local_vars'
173 dictionary, or in 'os.environ' if it's not in 'local_vars'.
174 'os.environ' is first checked/augmented to guarantee that it contains
175 certain values: see 'check_environ()'. Raise ValueError for any
176 variables not found in either 'local_vars' or 'os.environ'.
Greg Wardb8b263b2000-09-30 18:40:42 +0000177 """
Greg Wardbe86bde2000-09-26 01:56:15 +0000178 check_environ()
Greg Ward1b4ede52000-03-22 00:22:44 +0000179 def _subst (match, local_vars=local_vars):
180 var_name = match.group(1)
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000181 if var_name in local_vars:
Greg Wardbe86bde2000-09-26 01:56:15 +0000182 return str(local_vars[var_name])
Greg Ward1b4ede52000-03-22 00:22:44 +0000183 else:
184 return os.environ[var_name]
185
Greg Ward47527692000-09-30 18:49:14 +0000186 try:
Jeremy Hylton5e2d0762001-01-25 20:10:32 +0000187 return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
Guido van Rossumb940e112007-01-10 16:19:56 +0000188 except KeyError as var:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000189 raise ValueError("invalid variable '$%s'" % var)
Greg Ward1b4ede52000-03-22 00:22:44 +0000190
Tarek Ziadé36797272010-07-22 12:50:05 +0000191# subst_vars ()
Greg Ward7c1a6d42000-03-29 02:48:40 +0000192
Tarek Ziadé36797272010-07-22 12:50:05 +0000193
194def grok_environment_error (exc, prefix="error: "):
Éric Araujofc773a22014-03-12 03:34:02 -0400195 # Function kept for backward compatibility.
196 # Used to try clever things with EnvironmentErrors,
197 # but nowadays str(exception) produces good messages.
198 return prefix + str(exc)
Greg Ward6a2a3db2000-06-24 20:40:02 +0000199
Tarek Ziadé36797272010-07-22 12:50:05 +0000200
Greg Ward6a2a3db2000-06-24 20:40:02 +0000201# Needed by 'split_quoted()'
Martin v. Löwis1c0f1f92004-03-25 14:58:19 +0000202_wordchars_re = _squote_re = _dquote_re = None
203def _init_regex():
204 global _wordchars_re, _squote_re, _dquote_re
205 _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
206 _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
207 _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
Greg Ward6a2a3db2000-06-24 20:40:02 +0000208
Tarek Ziadé36797272010-07-22 12:50:05 +0000209def split_quoted (s):
Greg Ward6a2a3db2000-06-24 20:40:02 +0000210 """Split a string up according to Unix shell-like rules for quotes and
Tarek Ziadé36797272010-07-22 12:50:05 +0000211 backslashes. In short: words are delimited by spaces, as long as those
Greg Ward6a2a3db2000-06-24 20:40:02 +0000212 spaces are not escaped by a backslash, or inside a quoted string.
213 Single and double quotes are equivalent, and the quote characters can
214 be backslash-escaped. The backslash is stripped from any two-character
215 escape sequence, leaving only the escaped character. The quote
216 characters are stripped from any quoted string. Returns a list of
217 words.
218 """
Tarek Ziadé36797272010-07-22 12:50:05 +0000219
Greg Ward6a2a3db2000-06-24 20:40:02 +0000220 # This is a nice algorithm for splitting up a single string, since it
221 # doesn't require character-by-character examination. It was a little
222 # bit of a brain-bender to get it working right, though...
Martin v. Löwis1c0f1f92004-03-25 14:58:19 +0000223 if _wordchars_re is None: _init_regex()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000224
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000225 s = s.strip()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000226 words = []
227 pos = 0
228
229 while s:
230 m = _wordchars_re.match(s, pos)
231 end = m.end()
232 if end == len(s):
233 words.append(s[:end])
234 break
235
Greg Ward2b042de2000-08-08 14:38:13 +0000236 if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
Greg Ward6a2a3db2000-06-24 20:40:02 +0000237 words.append(s[:end]) # we definitely have a word delimiter
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000238 s = s[end:].lstrip()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000239 pos = 0
240
241 elif s[end] == '\\': # preserve whatever is being escaped;
242 # will become part of the current word
243 s = s[:end] + s[end+1:]
244 pos = end+1
245
246 else:
247 if s[end] == "'": # slurp singly-quoted string
248 m = _squote_re.match(s, end)
249 elif s[end] == '"': # slurp doubly-quoted string
250 m = _dquote_re.match(s, end)
251 else:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000252 raise RuntimeError("this can't happen (bad char '%c')" % s[end])
Greg Ward6a2a3db2000-06-24 20:40:02 +0000253
254 if m is None:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000255 raise ValueError("bad string (mismatched %s quotes?)" % s[end])
Greg Ward6a2a3db2000-06-24 20:40:02 +0000256
257 (beg, end) = m.span()
258 s = s[:beg] + s[beg+1:end-1] + s[end:]
259 pos = m.end() - 2
260
261 if pos >= len(s):
262 words.append(s)
263 break
264
265 return words
266
Tarek Ziadé36797272010-07-22 12:50:05 +0000267# split_quoted ()
Greg Ward1c16ac32000-08-02 01:37:30 +0000268
269
Tarek Ziadé36797272010-07-22 12:50:05 +0000270def execute (func, args, msg=None, verbose=0, dry_run=0):
271 """Perform some action that affects the outside world (eg. by
272 writing to the filesystem). Such actions are special because they
273 are disabled by the 'dry_run' flag. This method takes care of all
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000274 that bureaucracy for you; all you have to do is supply the
275 function to call and an argument tuple for it (to embody the
276 "external action" being performed), and an optional message to
277 print.
Greg Ward1c16ac32000-08-02 01:37:30 +0000278 """
Greg Ward1c16ac32000-08-02 01:37:30 +0000279 if msg is None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000280 msg = "%s%r" % (func.__name__, args)
Fred Drakeb94b8492001-12-06 20:51:35 +0000281 if msg[-2:] == ',)': # correct for singleton tuple
Greg Ward1c16ac32000-08-02 01:37:30 +0000282 msg = msg[0:-2] + ')'
283
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000284 log.info(msg)
Greg Ward1c16ac32000-08-02 01:37:30 +0000285 if not dry_run:
Neal Norwitzd9108552006-03-17 08:00:19 +0000286 func(*args)
Greg Ward1c16ac32000-08-02 01:37:30 +0000287
Greg Ward817dc092000-09-25 01:25:06 +0000288
Tarek Ziadé36797272010-07-22 12:50:05 +0000289def strtobool (val):
Greg Ward817dc092000-09-25 01:25:06 +0000290 """Convert a string representation of truth to true (1) or false (0).
Tim Peters182b5ac2004-07-18 06:16:08 +0000291
Greg Ward817dc092000-09-25 01:25:06 +0000292 True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
293 are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
294 'val' is anything else.
295 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000296 val = val.lower()
Greg Ward817dc092000-09-25 01:25:06 +0000297 if val in ('y', 'yes', 't', 'true', 'on', '1'):
298 return 1
299 elif val in ('n', 'no', 'f', 'false', 'off', '0'):
300 return 0
301 else:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000302 raise ValueError("invalid truth value %r" % (val,))
Greg Ward1297b5c2000-09-30 20:37:56 +0000303
304
Tarek Ziadé36797272010-07-22 12:50:05 +0000305def byte_compile (py_files,
306 optimize=0, force=0,
307 prefix=None, base_dir=None,
308 verbose=1, dry_run=0,
309 direct=None):
Brett Cannonf299abd2015-04-13 14:21:02 -0400310 """Byte-compile a collection of Python source files to .pyc
311 files in a __pycache__ subdirectory. 'py_files' is a list
Éric Araujo04ea9532011-10-08 03:02:37 +0200312 of files to compile; any files that don't end in ".py" are silently
313 skipped. 'optimize' must be one of the following:
Brett Cannonf299abd2015-04-13 14:21:02 -0400314 0 - don't optimize
Greg Ward1297b5c2000-09-30 20:37:56 +0000315 1 - normal optimization (like "python -O")
316 2 - extra optimization (like "python -OO")
317 If 'force' is true, all files are recompiled regardless of
318 timestamps.
319
320 The source filename encoded in each bytecode file defaults to the
321 filenames listed in 'py_files'; you can modify these with 'prefix' and
322 'basedir'. 'prefix' is a string that will be stripped off of each
323 source filename, and 'base_dir' is a directory name that will be
324 prepended (after 'prefix' is stripped). You can supply either or both
325 (or neither) of 'prefix' and 'base_dir', as you wish.
326
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000327 If 'dry_run' is true, doesn't actually do anything that would
328 affect the filesystem.
Greg Ward1297b5c2000-09-30 20:37:56 +0000329
330 Byte-compilation is either done directly in this interpreter process
331 with the standard py_compile module, or indirectly by writing a
332 temporary script and executing it. Normally, you should let
333 'byte_compile()' figure out to use direct compilation or not (see
334 the source for details). The 'direct' flag is used by the script
335 generated in indirect mode; unless you know what you're doing, leave
336 it set to None.
337 """
Victor Stinner9def2842016-01-18 12:15:08 +0100338
339 # Late import to fix a bootstrap issue: _posixsubprocess is built by
340 # setup.py, but setup.py uses distutils.
341 import subprocess
342
Tarek Ziadé04fe7c02009-10-25 23:08:47 +0000343 # nothing is done if sys.dont_write_bytecode is True
344 if sys.dont_write_bytecode:
345 raise DistutilsByteCompileError('byte-compiling is disabled.')
346
Greg Ward1297b5c2000-09-30 20:37:56 +0000347 # First, if the caller didn't force us into direct or indirect mode,
348 # figure out which mode we should be in. We take a conservative
349 # approach: choose direct mode *only* if the current interpreter is
350 # in debug mode and optimize is 0. If we're not in debug mode (-O
351 # or -OO), we don't know which level of optimization this
352 # interpreter is running with, so we can't do direct
353 # byte-compilation and be certain that it's the right thing. Thus,
354 # always compile indirectly if the current interpreter is in either
355 # optimize mode, or if either optimization level was requested by
356 # the caller.
357 if direct is None:
358 direct = (__debug__ and optimize == 0)
359
360 # "Indirect" byte-compilation: write a temporary script and then
361 # run it with the appropriate flags.
362 if not direct:
Marc-André Lemburg03750792002-12-03 08:45:11 +0000363 try:
364 from tempfile import mkstemp
365 (script_fd, script_name) = mkstemp(".py")
Brett Cannoncd171c82013-07-04 17:43:24 -0400366 except ImportError:
Marc-André Lemburg03750792002-12-03 08:45:11 +0000367 from tempfile import mktemp
368 (script_fd, script_name) = None, mktemp(".py")
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000369 log.info("writing byte-compilation script '%s'", script_name)
Greg Ward1297b5c2000-09-30 20:37:56 +0000370 if not dry_run:
Marc-André Lemburg03750792002-12-03 08:45:11 +0000371 if script_fd is not None:
372 script = os.fdopen(script_fd, "w")
373 else:
374 script = open(script_name, "w")
Greg Ward1297b5c2000-09-30 20:37:56 +0000375
376 script.write("""\
377from distutils.util import byte_compile
378files = [
379""")
Greg Ward9216cfe2000-10-03 03:31:05 +0000380
381 # XXX would be nice to write absolute filenames, just for
382 # safety's sake (script should be more robust in the face of
383 # chdir'ing before running it). But this requires abspath'ing
384 # 'prefix' as well, and that breaks the hack in build_lib's
385 # 'byte_compile()' method that carefully tacks on a trailing
386 # slash (os.sep really) to make sure the prefix here is "just
387 # right". This whole prefix business is rather delicate -- the
388 # problem is that it's really a directory, but I'm treating it
389 # as a dumb string, so trailing slashes and so forth matter.
390
391 #py_files = map(os.path.abspath, py_files)
392 #if prefix:
393 # prefix = os.path.abspath(prefix)
394
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000395 script.write(",\n".join(map(repr, py_files)) + "]\n")
Greg Ward1297b5c2000-09-30 20:37:56 +0000396 script.write("""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000397byte_compile(files, optimize=%r, force=%r,
398 prefix=%r, base_dir=%r,
399 verbose=%r, dry_run=0,
Greg Ward1297b5c2000-09-30 20:37:56 +0000400 direct=1)
Walter Dörwald70a6b492004-02-12 17:35:32 +0000401""" % (optimize, force, prefix, base_dir, verbose))
Greg Ward1297b5c2000-09-30 20:37:56 +0000402
403 script.close()
404
Victor Stinner9def2842016-01-18 12:15:08 +0100405 cmd = [sys.executable]
406 cmd.extend(subprocess._optim_args_from_interpreter_flags())
407 cmd.append(script_name)
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000408 spawn(cmd, dry_run=dry_run)
Greg Ward9216cfe2000-10-03 03:31:05 +0000409 execute(os.remove, (script_name,), "removing %s" % script_name,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000410 dry_run=dry_run)
Fred Drakeb94b8492001-12-06 20:51:35 +0000411
Greg Ward1297b5c2000-09-30 20:37:56 +0000412 # "Direct" byte-compilation: use the py_compile module to compile
413 # right here, right now. Note that the script generated in indirect
414 # mode simply calls 'byte_compile()' in direct mode, a weird sort of
415 # cross-process recursion. Hey, it works!
416 else:
417 from py_compile import compile
418
419 for file in py_files:
420 if file[-3:] != ".py":
Greg Wardf217e212000-10-01 23:49:30 +0000421 # This lets us be lazy and not filter filenames in
422 # the "install_lib" command.
423 continue
Greg Ward1297b5c2000-09-30 20:37:56 +0000424
425 # Terminology from the py_compile module:
426 # cfile - byte-compiled file
427 # dfile - purported source filename (same as 'file' by default)
Éric Araujo47a45212011-10-08 00:34:13 +0200428 if optimize >= 0:
Brett Cannonf299abd2015-04-13 14:21:02 -0400429 opt = '' if optimize == 0 else optimize
Brett Cannon61c35562013-06-15 12:59:53 -0400430 cfile = importlib.util.cache_from_source(
Brett Cannonf299abd2015-04-13 14:21:02 -0400431 file, optimization=opt)
Éric Araujo47a45212011-10-08 00:34:13 +0200432 else:
Brett Cannon61c35562013-06-15 12:59:53 -0400433 cfile = importlib.util.cache_from_source(file)
Greg Ward1297b5c2000-09-30 20:37:56 +0000434 dfile = file
435 if prefix:
436 if file[:len(prefix)] != prefix:
Tarek Ziadé36797272010-07-22 12:50:05 +0000437 raise ValueError("invalid prefix: filename %r doesn't start with %r"
438 % (file, prefix))
Greg Ward1297b5c2000-09-30 20:37:56 +0000439 dfile = dfile[len(prefix):]
440 if base_dir:
441 dfile = os.path.join(base_dir, dfile)
442
443 cfile_base = os.path.basename(cfile)
444 if direct:
445 if force or newer(file, cfile):
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000446 log.info("byte-compiling %s to %s", file, cfile_base)
Greg Ward1297b5c2000-09-30 20:37:56 +0000447 if not dry_run:
448 compile(file, cfile, dfile)
449 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000450 log.debug("skipping byte-compilation of %s to %s",
451 file, cfile_base)
Greg Ward1297b5c2000-09-30 20:37:56 +0000452
Tarek Ziadé36797272010-07-22 12:50:05 +0000453# byte_compile ()
Andrew M. Kuchlingdf66df02001-03-22 03:03:41 +0000454
Tarek Ziadé36797272010-07-22 12:50:05 +0000455def rfc822_escape (header):
Andrew M. Kuchlingdf66df02001-03-22 03:03:41 +0000456 """Return a version of the string escaped for inclusion in an
Andrew M. Kuchling88b08842001-03-23 17:30:26 +0000457 RFC-822 header, by ensuring there are 8 spaces space after each newline.
Andrew M. Kuchlingdf66df02001-03-22 03:03:41 +0000458 """
Tarek Ziadédf872d42009-12-06 09:28:17 +0000459 lines = header.split('\n')
460 sep = '\n' + 8 * ' '
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000461 return sep.join(lines)
Martin v. Löwis6178db62008-12-01 04:38:52 +0000462
463# 2to3 support
464
465def run_2to3(files, fixer_names=None, options=None, explicit=None):
466 """Invoke 2to3 on a list of Python files.
467 The files should all come from the build area, as the
468 modification is done in-place. To reduce the build time,
469 only files modified since the last invocation of this
470 function should be passed in the files argument."""
471
472 if not files:
473 return
474
475 # Make this class local, to delay import of 2to3
476 from lib2to3.refactor import RefactoringTool, get_fixers_from_package
477 class DistutilsRefactoringTool(RefactoringTool):
478 def log_error(self, msg, *args, **kw):
479 log.error(msg, *args)
480
481 def log_message(self, msg, *args):
482 log.info(msg, *args)
483
484 def log_debug(self, msg, *args):
485 log.debug(msg, *args)
486
487 if fixer_names is None:
488 fixer_names = get_fixers_from_package('lib2to3.fixes')
489 r = DistutilsRefactoringTool(fixer_names, options=options)
490 r.refactor(files, write=True)
491
Georg Brandl6d4a9cf2009-03-31 00:34:54 +0000492def copydir_run_2to3(src, dest, template=None, fixer_names=None,
493 options=None, explicit=None):
494 """Recursively copy a directory, only copying new and changed files,
495 running run_2to3 over all newly copied Python modules afterward.
496
497 If you give a template string, it's parsed like a MANIFEST.in.
498 """
499 from distutils.dir_util import mkpath
500 from distutils.file_util import copy_file
501 from distutils.filelist import FileList
502 filelist = FileList()
503 curdir = os.getcwd()
504 os.chdir(src)
505 try:
506 filelist.findall()
507 finally:
508 os.chdir(curdir)
509 filelist.files[:] = filelist.allfiles
510 if template:
511 for line in template.splitlines():
512 line = line.strip()
513 if not line: continue
514 filelist.process_template_line(line)
515 copied = []
516 for filename in filelist.files:
517 outname = os.path.join(dest, filename)
518 mkpath(os.path.dirname(outname))
519 res = copy_file(os.path.join(src, filename), outname, update=1)
520 if res[1]: copied.append(outname)
521 run_2to3([fn for fn in copied if fn.lower().endswith('.py')],
522 fixer_names=fixer_names, options=options, explicit=explicit)
523 return copied
524
Martin v. Löwis6178db62008-12-01 04:38:52 +0000525class Mixin2to3:
526 '''Mixin class for commands that run 2to3.
527 To configure 2to3, setup scripts may either change
528 the class variables, or inherit from individual commands
529 to override how 2to3 is invoked.'''
530
531 # provide list of fixers to run;
532 # defaults to all from lib2to3.fixers
533 fixer_names = None
534
535 # options dictionary
536 options = None
537
538 # list of fixers to invoke even though they are marked as explicit
539 explicit = None
540
541 def run_2to3(self, files):
542 return run_2to3(files, self.fixer_names, self.options, self.explicit)