blob: 6f15ce8b5ed77d98cf0d15b56bbfc751fdca18d9 [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
Greg Ward3ce77fd2000-03-02 01:49:45 +00007__revision__ = "$Id$"
Greg Ward2689e3d1999-03-22 14:52:19 +00008
Greg Ward1297b5c2000-09-30 20:37:56 +00009import sys, os, string, re
10from distutils.errors import DistutilsPlatformError
11from distutils.dep_util import newer
Greg Ward7c1a6d42000-03-29 02:48:40 +000012from distutils.spawn import spawn
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000013from distutils import log
Greg Wardaa458bc2000-04-22 15:14:58 +000014
Greg Ward585df892000-03-01 14:40:15 +000015def get_platform ():
Greg Ward59399bb2000-09-15 01:16:14 +000016 """Return a string that identifies the current platform. This is used
17 mainly to distinguish platform-specific build directories and
18 platform-specific built distributions. Typically includes the OS name
19 and version and the architecture (as supplied by 'os.uname()'),
20 although the exact information included depends on the OS; eg. for IRIX
21 the architecture isn't particularly important (IRIX only runs on SGI
22 hardware), but for Linux the kernel version isn't particularly
23 important.
24
25 Examples of returned values:
26 linux-i586
27 linux-alpha (?)
28 solaris-2.6-sun4u
29 irix-5.3
30 irix64-6.2
Fred Drakeb94b8492001-12-06 20:51:35 +000031
Greg Ward59399bb2000-09-15 01:16:14 +000032 For non-POSIX platforms, currently just returns 'sys.platform'.
Greg Wardb75c4852000-06-18 15:45:55 +000033 """
Greg Wardec84c212000-09-30 17:09:39 +000034 if os.name != "posix" or not hasattr(os, 'uname'):
Greg Ward59399bb2000-09-15 01:16:14 +000035 # XXX what about the architecture? NT is Intel or Alpha,
36 # Mac OS is M68k or PPC, etc.
37 return sys.platform
38
39 # Try to distinguish various flavours of Unix
40
41 (osname, host, release, version, machine) = os.uname()
Andrew M. Kuchling83c158f2001-02-27 19:25:42 +000042
Andrew M. Kuchlingb8c7b9f2003-01-06 13:28:12 +000043 # Convert the OS name to lowercase, remove '/' characters
44 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
Neal Norwitz9d72bb42007-04-17 08:48:32 +000045 osname = osname.lower().replace('/', '')
46 machine = machine.replace(' ', '_')
47 machine = machine.replace('/', '-')
Fred Drakeb94b8492001-12-06 20:51:35 +000048
Greg Ward59399bb2000-09-15 01:16:14 +000049 if osname[:5] == "linux":
50 # At least on Linux/Intel, 'machine' is the processor --
51 # i386, etc.
52 # XXX what about Alpha, SPARC, etc?
53 return "%s-%s" % (osname, machine)
54 elif osname[:5] == "sunos":
55 if release[0] >= "5": # SunOS 5 == Solaris 2
56 osname = "solaris"
57 release = "%d.%s" % (int(release[0]) - 3, release[2:])
58 # fall through to standard osname-release-machine representation
59 elif osname[:4] == "irix": # could be "irix64"!
60 return "%s-%s" % (osname, release)
Fred Drakeb94b8492001-12-06 20:51:35 +000061 elif osname[:3] == "aix":
Andrew M. Kuchling9767e762001-02-27 18:48:00 +000062 return "%s-%s.%s" % (osname, version, release)
Andrew M. Kuchling989835c2001-01-19 16:26:12 +000063 elif osname[:6] == "cygwin":
Andrew M. Kuchling5a3e4cb2001-07-20 19:29:04 +000064 osname = "cygwin"
Andrew M. Kuchling989835c2001-01-19 16:26:12 +000065 rel_re = re.compile (r'[\d.]+')
66 m = rel_re.match(release)
67 if m:
68 release = m.group()
Thomas Wouters477c8d52006-05-27 19:21:47 +000069 elif osname[:6] == "darwin":
70 #
71 # For our purposes, we'll assume that the system version from
72 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
73 # to. This makes the compatibility story a bit more sane because the
74 # machine is going to compile and link as if it were
75 # MACOSX_DEPLOYMENT_TARGET.
76 from distutils.sysconfig import get_config_vars
77 cfgvars = get_config_vars()
78
79 macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET')
80 if not macver:
81 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
82
83 if not macver:
84 # Get the system version. Reading this plist is a documented
85 # way to get the system version (see the documentation for
86 # the Gestalt Manager)
87 try:
88 f = open('/System/Library/CoreServices/SystemVersion.plist')
89 except IOError:
90 # We're on a plain darwin box, fall back to the default
91 # behaviour.
92 pass
93 else:
94 m = re.search(
95 r'<key>ProductUserVisibleVersion</key>\s*' +
96 r'<string>(.*?)</string>', f.read())
97 f.close()
98 if m is not None:
99 macver = '.'.join(m.group(1).split('.')[:2])
100 # else: fall back to the default behaviour
101
102 if macver:
103 from distutils.sysconfig import get_config_vars
104 release = macver
105 osname = "macosx"
106
107
108 if (release + '.') < '10.4.' and \
109 get_config_vars().get('UNIVERSALSDK', '').strip():
110 # The universal build will build fat binaries, but not on
111 # systems before 10.4
112 machine = 'fat'
113
114 elif machine in ('PowerPC', 'Power_Macintosh'):
115 # Pick a sane name for the PPC architecture.
116 machine = 'ppc'
Fred Drakeb94b8492001-12-06 20:51:35 +0000117
Greg Ward59399bb2000-09-15 01:16:14 +0000118 return "%s-%s-%s" % (osname, release, machine)
119
120# get_platform ()
Greg Ward50919292000-03-07 03:27:08 +0000121
122
Greg Wardd8dfb4c2000-05-31 02:32:10 +0000123def convert_path (pathname):
Greg Wardb8b263b2000-09-30 18:40:42 +0000124 """Return 'pathname' as a name that will work on the native filesystem,
125 i.e. split it on '/' and put it back together again using the current
126 directory separator. Needed because filenames in the setup script are
127 always supplied in Unix style, and have to be converted to the local
128 convention before we can actually use them in the filesystem. Raises
Greg Ward47527692000-09-30 18:49:14 +0000129 ValueError on non-Unix-ish systems if 'pathname' either starts or
130 ends with a slash.
Greg Wardb8b263b2000-09-30 18:40:42 +0000131 """
Greg Ward7ec05352000-09-22 01:05:43 +0000132 if os.sep == '/':
133 return pathname
Neal Norwitzb0df6a12002-08-13 17:42:57 +0000134 if not pathname:
135 return pathname
136 if pathname[0] == '/':
Greg Ward02a1a2b2000-04-15 22:15:07 +0000137 raise ValueError, "path '%s' cannot be absolute" % pathname
Neal Norwitzb0df6a12002-08-13 17:42:57 +0000138 if pathname[-1] == '/':
Greg Ward02a1a2b2000-04-15 22:15:07 +0000139 raise ValueError, "path '%s' cannot end with '/'" % pathname
Greg Ward7ec05352000-09-22 01:05:43 +0000140
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000141 paths = pathname.split('/')
Jack Jansenb4cd5c12001-01-28 12:23:32 +0000142 while '.' in paths:
143 paths.remove('.')
144 if not paths:
145 return os.curdir
Neal Norwitzd9108552006-03-17 08:00:19 +0000146 return os.path.join(*paths)
Greg Ward50919292000-03-07 03:27:08 +0000147
Greg Wardd8dfb4c2000-05-31 02:32:10 +0000148# convert_path ()
Greg Ward1b4ede52000-03-22 00:22:44 +0000149
150
Greg Ward67f75d42000-04-27 01:53:46 +0000151def change_root (new_root, pathname):
Greg Ward67f75d42000-04-27 01:53:46 +0000152 """Return 'pathname' with 'new_root' prepended. If 'pathname' is
153 relative, this is equivalent to "os.path.join(new_root,pathname)".
154 Otherwise, it requires making 'pathname' relative and then joining the
Greg Ward4b46ef92000-05-31 02:14:32 +0000155 two, which is tricky on DOS/Windows and Mac OS.
156 """
157 if os.name == 'posix':
Greg Wardbe86bde2000-09-26 01:56:15 +0000158 if not os.path.isabs(pathname):
159 return os.path.join(new_root, pathname)
Greg Ward4b46ef92000-05-31 02:14:32 +0000160 else:
Greg Wardbe86bde2000-09-26 01:56:15 +0000161 return os.path.join(new_root, pathname[1:])
Greg Ward67f75d42000-04-27 01:53:46 +0000162
163 elif os.name == 'nt':
Greg Wardbe86bde2000-09-26 01:56:15 +0000164 (drive, path) = os.path.splitdrive(pathname)
Greg Ward4b46ef92000-05-31 02:14:32 +0000165 if path[0] == '\\':
166 path = path[1:]
Greg Wardbe86bde2000-09-26 01:56:15 +0000167 return os.path.join(new_root, path)
Greg Ward67f75d42000-04-27 01:53:46 +0000168
Marc-André Lemburg2544f512002-01-31 18:56:00 +0000169 elif os.name == 'os2':
170 (drive, path) = os.path.splitdrive(pathname)
171 if path[0] == os.sep:
172 path = path[1:]
173 return os.path.join(new_root, path)
174
Greg Ward67f75d42000-04-27 01:53:46 +0000175 elif os.name == 'mac':
Greg Wardf5855742000-09-21 01:23:35 +0000176 if not os.path.isabs(pathname):
177 return os.path.join(new_root, pathname)
178 else:
179 # Chop off volume name from start of path
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000180 elements = pathname.split(":", 1)
Greg Wardf5855742000-09-21 01:23:35 +0000181 pathname = ":" + elements[1]
182 return os.path.join(new_root, pathname)
Greg Ward67f75d42000-04-27 01:53:46 +0000183
184 else:
185 raise DistutilsPlatformError, \
186 "nothing known about platform '%s'" % os.name
187
188
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000189_environ_checked = 0
190def check_environ ():
Greg Ward1b4ede52000-03-22 00:22:44 +0000191 """Ensure that 'os.environ' has all the environment variables we
Greg Wardb8b263b2000-09-30 18:40:42 +0000192 guarantee that users can use in config files, command-line options,
193 etc. Currently this includes:
194 HOME - user's home directory (Unix only)
195 PLAT - description of the current platform, including hardware
196 and OS (see 'get_platform()')
Greg Ward1b4ede52000-03-22 00:22:44 +0000197 """
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000198 global _environ_checked
199 if _environ_checked:
200 return
201
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000202 if os.name == 'posix' and 'HOME' not in os.environ:
Greg Ward1b4ede52000-03-22 00:22:44 +0000203 import pwd
Greg Wardbe86bde2000-09-26 01:56:15 +0000204 os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
Greg Ward1b4ede52000-03-22 00:22:44 +0000205
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000206 if 'PLAT' not in os.environ:
Greg Wardbe86bde2000-09-26 01:56:15 +0000207 os.environ['PLAT'] = get_platform()
Greg Ward1b4ede52000-03-22 00:22:44 +0000208
Gregory P. Smithe7e35ac2000-05-12 00:40:00 +0000209 _environ_checked = 1
210
Greg Ward1b4ede52000-03-22 00:22:44 +0000211
Jeremy Hylton5e2d0762001-01-25 20:10:32 +0000212def subst_vars (s, local_vars):
Greg Wardb8b263b2000-09-30 18:40:42 +0000213 """Perform shell/Perl-style variable substitution on 'string'. Every
Greg Ward47527692000-09-30 18:49:14 +0000214 occurrence of '$' followed by a name is considered a variable, and
215 variable is substituted by the value found in the 'local_vars'
216 dictionary, or in 'os.environ' if it's not in 'local_vars'.
217 'os.environ' is first checked/augmented to guarantee that it contains
218 certain values: see 'check_environ()'. Raise ValueError for any
219 variables not found in either 'local_vars' or 'os.environ'.
Greg Wardb8b263b2000-09-30 18:40:42 +0000220 """
Greg Wardbe86bde2000-09-26 01:56:15 +0000221 check_environ()
Greg Ward1b4ede52000-03-22 00:22:44 +0000222 def _subst (match, local_vars=local_vars):
223 var_name = match.group(1)
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000224 if var_name in local_vars:
Greg Wardbe86bde2000-09-26 01:56:15 +0000225 return str(local_vars[var_name])
Greg Ward1b4ede52000-03-22 00:22:44 +0000226 else:
227 return os.environ[var_name]
228
Greg Ward47527692000-09-30 18:49:14 +0000229 try:
Jeremy Hylton5e2d0762001-01-25 20:10:32 +0000230 return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
Guido van Rossumb940e112007-01-10 16:19:56 +0000231 except KeyError as var:
Greg Ward47527692000-09-30 18:49:14 +0000232 raise ValueError, "invalid variable '$%s'" % var
Greg Ward1b4ede52000-03-22 00:22:44 +0000233
234# subst_vars ()
Greg Ward7c1a6d42000-03-29 02:48:40 +0000235
236
Greg Warde9055132000-06-17 02:16:46 +0000237def grok_environment_error (exc, prefix="error: "):
238 """Generate a useful error message from an EnvironmentError (IOError or
239 OSError) exception object. Handles Python 1.5.1 and 1.5.2 styles, and
240 does what it can to deal with exception objects that don't have a
241 filename (which happens when the error is due to a two-file operation,
242 such as 'rename()' or 'link()'. Returns the error message as a string
243 prefixed with 'prefix'.
244 """
245 # check for Python 1.5.2-style {IO,OS}Error exception objects
Greg Wardbe86bde2000-09-26 01:56:15 +0000246 if hasattr(exc, 'filename') and hasattr(exc, 'strerror'):
Greg Warde9055132000-06-17 02:16:46 +0000247 if exc.filename:
248 error = prefix + "%s: %s" % (exc.filename, exc.strerror)
249 else:
250 # two-argument functions in posix module don't
251 # include the filename in the exception object!
252 error = prefix + "%s" % exc.strerror
253 else:
254 error = prefix + str(exc[-1])
255
256 return error
Greg Ward6a2a3db2000-06-24 20:40:02 +0000257
258
259# Needed by 'split_quoted()'
Martin v. Löwis1c0f1f92004-03-25 14:58:19 +0000260_wordchars_re = _squote_re = _dquote_re = None
261def _init_regex():
262 global _wordchars_re, _squote_re, _dquote_re
263 _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
264 _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
265 _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
Greg Ward6a2a3db2000-06-24 20:40:02 +0000266
267def split_quoted (s):
268 """Split a string up according to Unix shell-like rules for quotes and
269 backslashes. In short: words are delimited by spaces, as long as those
270 spaces are not escaped by a backslash, or inside a quoted string.
271 Single and double quotes are equivalent, and the quote characters can
272 be backslash-escaped. The backslash is stripped from any two-character
273 escape sequence, leaving only the escaped character. The quote
274 characters are stripped from any quoted string. Returns a list of
275 words.
276 """
277
278 # This is a nice algorithm for splitting up a single string, since it
279 # doesn't require character-by-character examination. It was a little
280 # bit of a brain-bender to get it working right, though...
Martin v. Löwis1c0f1f92004-03-25 14:58:19 +0000281 if _wordchars_re is None: _init_regex()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000282
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000283 s = s.strip()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000284 words = []
285 pos = 0
286
287 while s:
288 m = _wordchars_re.match(s, pos)
289 end = m.end()
290 if end == len(s):
291 words.append(s[:end])
292 break
293
Greg Ward2b042de2000-08-08 14:38:13 +0000294 if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
Greg Ward6a2a3db2000-06-24 20:40:02 +0000295 words.append(s[:end]) # we definitely have a word delimiter
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000296 s = s[end:].lstrip()
Greg Ward6a2a3db2000-06-24 20:40:02 +0000297 pos = 0
298
299 elif s[end] == '\\': # preserve whatever is being escaped;
300 # will become part of the current word
301 s = s[:end] + s[end+1:]
302 pos = end+1
303
304 else:
305 if s[end] == "'": # slurp singly-quoted string
306 m = _squote_re.match(s, end)
307 elif s[end] == '"': # slurp doubly-quoted string
308 m = _dquote_re.match(s, end)
309 else:
310 raise RuntimeError, \
311 "this can't happen (bad char '%c')" % s[end]
312
313 if m is None:
314 raise ValueError, \
315 "bad string (mismatched %s quotes?)" % s[end]
316
317 (beg, end) = m.span()
318 s = s[:beg] + s[beg+1:end-1] + s[end:]
319 pos = m.end() - 2
320
321 if pos >= len(s):
322 words.append(s)
323 break
324
325 return words
326
327# split_quoted ()
Greg Ward1c16ac32000-08-02 01:37:30 +0000328
329
330def execute (func, args, msg=None, verbose=0, dry_run=0):
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000331 """Perform some action that affects the outside world (eg. by
332 writing to the filesystem). Such actions are special because they
333 are disabled by the 'dry_run' flag. This method takes care of all
334 that bureaucracy for you; all you have to do is supply the
335 function to call and an argument tuple for it (to embody the
336 "external action" being performed), and an optional message to
337 print.
Greg Ward1c16ac32000-08-02 01:37:30 +0000338 """
Greg Ward1c16ac32000-08-02 01:37:30 +0000339 if msg is None:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000340 msg = "%s%r" % (func.__name__, args)
Fred Drakeb94b8492001-12-06 20:51:35 +0000341 if msg[-2:] == ',)': # correct for singleton tuple
Greg Ward1c16ac32000-08-02 01:37:30 +0000342 msg = msg[0:-2] + ')'
343
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000344 log.info(msg)
Greg Ward1c16ac32000-08-02 01:37:30 +0000345 if not dry_run:
Neal Norwitzd9108552006-03-17 08:00:19 +0000346 func(*args)
Greg Ward1c16ac32000-08-02 01:37:30 +0000347
Greg Ward817dc092000-09-25 01:25:06 +0000348
349def strtobool (val):
350 """Convert a string representation of truth to true (1) or false (0).
Tim Peters182b5ac2004-07-18 06:16:08 +0000351
Greg Ward817dc092000-09-25 01:25:06 +0000352 True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
353 are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
354 'val' is anything else.
355 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000356 val = val.lower()
Greg Ward817dc092000-09-25 01:25:06 +0000357 if val in ('y', 'yes', 't', 'true', 'on', '1'):
358 return 1
359 elif val in ('n', 'no', 'f', 'false', 'off', '0'):
360 return 0
361 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000362 raise ValueError, "invalid truth value %r" % (val,)
Greg Ward1297b5c2000-09-30 20:37:56 +0000363
364
365def byte_compile (py_files,
366 optimize=0, force=0,
367 prefix=None, base_dir=None,
368 verbose=1, dry_run=0,
369 direct=None):
Greg Wardf217e212000-10-01 23:49:30 +0000370 """Byte-compile a collection of Python source files to either .pyc
371 or .pyo files in the same directory. 'py_files' is a list of files
372 to compile; any files that don't end in ".py" are silently skipped.
373 'optimize' must be one of the following:
Greg Ward1297b5c2000-09-30 20:37:56 +0000374 0 - don't optimize (generate .pyc)
375 1 - normal optimization (like "python -O")
376 2 - extra optimization (like "python -OO")
377 If 'force' is true, all files are recompiled regardless of
378 timestamps.
379
380 The source filename encoded in each bytecode file defaults to the
381 filenames listed in 'py_files'; you can modify these with 'prefix' and
382 'basedir'. 'prefix' is a string that will be stripped off of each
383 source filename, and 'base_dir' is a directory name that will be
384 prepended (after 'prefix' is stripped). You can supply either or both
385 (or neither) of 'prefix' and 'base_dir', as you wish.
386
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000387 If 'dry_run' is true, doesn't actually do anything that would
388 affect the filesystem.
Greg Ward1297b5c2000-09-30 20:37:56 +0000389
390 Byte-compilation is either done directly in this interpreter process
391 with the standard py_compile module, or indirectly by writing a
392 temporary script and executing it. Normally, you should let
393 'byte_compile()' figure out to use direct compilation or not (see
394 the source for details). The 'direct' flag is used by the script
395 generated in indirect mode; unless you know what you're doing, leave
396 it set to None.
397 """
398
399 # First, if the caller didn't force us into direct or indirect mode,
400 # figure out which mode we should be in. We take a conservative
401 # approach: choose direct mode *only* if the current interpreter is
402 # in debug mode and optimize is 0. If we're not in debug mode (-O
403 # or -OO), we don't know which level of optimization this
404 # interpreter is running with, so we can't do direct
405 # byte-compilation and be certain that it's the right thing. Thus,
406 # always compile indirectly if the current interpreter is in either
407 # optimize mode, or if either optimization level was requested by
408 # the caller.
409 if direct is None:
410 direct = (__debug__ and optimize == 0)
411
412 # "Indirect" byte-compilation: write a temporary script and then
413 # run it with the appropriate flags.
414 if not direct:
Marc-André Lemburg03750792002-12-03 08:45:11 +0000415 try:
416 from tempfile import mkstemp
417 (script_fd, script_name) = mkstemp(".py")
418 except ImportError:
419 from tempfile import mktemp
420 (script_fd, script_name) = None, mktemp(".py")
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000421 log.info("writing byte-compilation script '%s'", script_name)
Greg Ward1297b5c2000-09-30 20:37:56 +0000422 if not dry_run:
Marc-André Lemburg03750792002-12-03 08:45:11 +0000423 if script_fd is not None:
424 script = os.fdopen(script_fd, "w")
425 else:
426 script = open(script_name, "w")
Greg Ward1297b5c2000-09-30 20:37:56 +0000427
428 script.write("""\
429from distutils.util import byte_compile
430files = [
431""")
Greg Ward9216cfe2000-10-03 03:31:05 +0000432
433 # XXX would be nice to write absolute filenames, just for
434 # safety's sake (script should be more robust in the face of
435 # chdir'ing before running it). But this requires abspath'ing
436 # 'prefix' as well, and that breaks the hack in build_lib's
437 # 'byte_compile()' method that carefully tacks on a trailing
438 # slash (os.sep really) to make sure the prefix here is "just
439 # right". This whole prefix business is rather delicate -- the
440 # problem is that it's really a directory, but I'm treating it
441 # as a dumb string, so trailing slashes and so forth matter.
442
443 #py_files = map(os.path.abspath, py_files)
444 #if prefix:
445 # prefix = os.path.abspath(prefix)
446
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000447 script.write(",\n".join(map(repr, py_files)) + "]\n")
Greg Ward1297b5c2000-09-30 20:37:56 +0000448 script.write("""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000449byte_compile(files, optimize=%r, force=%r,
450 prefix=%r, base_dir=%r,
451 verbose=%r, dry_run=0,
Greg Ward1297b5c2000-09-30 20:37:56 +0000452 direct=1)
Walter Dörwald70a6b492004-02-12 17:35:32 +0000453""" % (optimize, force, prefix, base_dir, verbose))
Greg Ward1297b5c2000-09-30 20:37:56 +0000454
455 script.close()
456
457 cmd = [sys.executable, script_name]
458 if optimize == 1:
459 cmd.insert(1, "-O")
460 elif optimize == 2:
461 cmd.insert(1, "-OO")
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000462 spawn(cmd, dry_run=dry_run)
Greg Ward9216cfe2000-10-03 03:31:05 +0000463 execute(os.remove, (script_name,), "removing %s" % script_name,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000464 dry_run=dry_run)
Fred Drakeb94b8492001-12-06 20:51:35 +0000465
Greg Ward1297b5c2000-09-30 20:37:56 +0000466 # "Direct" byte-compilation: use the py_compile module to compile
467 # right here, right now. Note that the script generated in indirect
468 # mode simply calls 'byte_compile()' in direct mode, a weird sort of
469 # cross-process recursion. Hey, it works!
470 else:
471 from py_compile import compile
472
473 for file in py_files:
474 if file[-3:] != ".py":
Greg Wardf217e212000-10-01 23:49:30 +0000475 # This lets us be lazy and not filter filenames in
476 # the "install_lib" command.
477 continue
Greg Ward1297b5c2000-09-30 20:37:56 +0000478
479 # Terminology from the py_compile module:
480 # cfile - byte-compiled file
481 # dfile - purported source filename (same as 'file' by default)
482 cfile = file + (__debug__ and "c" or "o")
483 dfile = file
484 if prefix:
485 if file[:len(prefix)] != prefix:
486 raise ValueError, \
Walter Dörwald70a6b492004-02-12 17:35:32 +0000487 ("invalid prefix: filename %r doesn't start with %r"
488 % (file, prefix))
Greg Ward1297b5c2000-09-30 20:37:56 +0000489 dfile = dfile[len(prefix):]
490 if base_dir:
491 dfile = os.path.join(base_dir, dfile)
492
493 cfile_base = os.path.basename(cfile)
494 if direct:
495 if force or newer(file, cfile):
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000496 log.info("byte-compiling %s to %s", file, cfile_base)
Greg Ward1297b5c2000-09-30 20:37:56 +0000497 if not dry_run:
498 compile(file, cfile, dfile)
499 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000500 log.debug("skipping byte-compilation of %s to %s",
501 file, cfile_base)
Greg Ward1297b5c2000-09-30 20:37:56 +0000502
503# byte_compile ()
Andrew M. Kuchlingdf66df02001-03-22 03:03:41 +0000504
505def rfc822_escape (header):
506 """Return a version of the string escaped for inclusion in an
Andrew M. Kuchling88b08842001-03-23 17:30:26 +0000507 RFC-822 header, by ensuring there are 8 spaces space after each newline.
Andrew M. Kuchlingdf66df02001-03-22 03:03:41 +0000508 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000509 lines = [x.strip() for x in header.split('\n')]
510 sep = '\n' + 8*' '
511 return sep.join(lines)