12689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward"""distutils.util
22689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
3aebf706b4e845d7525d2d8e792f0e23fcfb3e6afGreg WardMiscellaneous utility functions -- anything that doesn't fit into
44752769d08c3ef950d31b926751d5e4d1dae294fGreg Wardone of the other *util.py modules.
54752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward"""
62689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
73ce77fd05ed00168f618b63401d770ccc4f04b09Greg Ward__revision__ = "$Id$"
82689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
9f830aa54558b0d4358f427e46171e95c8218f2deJesus Ceaimport sys, os, string, re
101297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfrom distutils.errors import DistutilsPlatformError
111297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfrom distutils.dep_util import newer
12dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadéfrom distutils.spawn import spawn
13cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hyltonfrom distutils import log
14b9c1cfc42881370322ff6894568b45dcfec5ba2eTarek Ziadéfrom distutils.errors import DistutilsByteCompileError
15aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward
16dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef get_platform ():
17dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    """Return a string that identifies the current platform.  This is used
18dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    mainly to distinguish platform-specific build directories and
19dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    platform-specific built distributions.  Typically includes the OS name
20dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    and version and the architecture (as supplied by 'os.uname()'),
21dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    although the exact information included depends on the OS; eg. for IRIX
22dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    the architecture isn't particularly important (IRIX only runs on SGI
23dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    hardware), but for Linux the kernel version isn't particularly
24dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    important.
25dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
26dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    Examples of returned values:
27dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé       linux-i586
28dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé       linux-alpha (?)
29dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé       solaris-2.6-sun4u
30dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé       irix-5.3
31dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé       irix64-6.2
32dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
33dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    Windows will return one of:
34dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
35dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé       win-ia64 (64bit Windows on Itanium)
36dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé       win32 (all others - specifically, sys.platform is returned)
37dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
38dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    For other non-POSIX platforms, currently just returns 'sys.platform'.
39dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    """
40dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    if os.name == 'nt':
41dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        # sniff sys.version for architecture.
42dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        prefix = " bit ("
43dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        i = string.find(sys.version, prefix)
44dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        if i == -1:
45dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé            return sys.platform
46dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        j = string.find(sys.version, ")", i)
47dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        look = sys.version[i+len(prefix):j].lower()
48dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        if look=='amd64':
49dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé            return 'win-amd64'
50dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        if look=='itanium':
51dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé            return 'win-ia64'
52dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        return sys.platform
53dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
54d65e2bab3b438f883ef28245f51795b14a4c498fdoko@python.org    # Set for cross builds explicitly
55d65e2bab3b438f883ef28245f51795b14a4c498fdoko@python.org    if "_PYTHON_HOST_PLATFORM" in os.environ:
56d65e2bab3b438f883ef28245f51795b14a4c498fdoko@python.org        return os.environ["_PYTHON_HOST_PLATFORM"]
57d65e2bab3b438f883ef28245f51795b14a4c498fdoko@python.org
58dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    if os.name != "posix" or not hasattr(os, 'uname'):
59dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        # XXX what about the architecture? NT is Intel or Alpha,
60dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        # Mac OS is M68k or PPC, etc.
61dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        return sys.platform
62dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
63dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    # Try to distinguish various flavours of Unix
64dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
65dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    (osname, host, release, version, machine) = os.uname()
66dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
67dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    # Convert the OS name to lowercase, remove '/' characters
68dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
69dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    osname = string.lower(osname)
70dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    osname = string.replace(osname, '/', '')
71dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    machine = string.replace(machine, ' ', '_')
72dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    machine = string.replace(machine, '/', '-')
73dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
74dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    if osname[:5] == "linux":
75dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        # At least on Linux/Intel, 'machine' is the processor --
76dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        # i386, etc.
77dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        # XXX what about Alpha, SPARC, etc?
78dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        return  "%s-%s" % (osname, machine)
79dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    elif osname[:5] == "sunos":
80dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        if release[0] >= "5":           # SunOS 5 == Solaris 2
81dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé            osname = "solaris"
82dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé            release = "%d.%s" % (int(release[0]) - 3, release[2:])
83f830aa54558b0d4358f427e46171e95c8218f2deJesus Cea            # We can't use "platform.architecture()[0]" because a
84f830aa54558b0d4358f427e46171e95c8218f2deJesus Cea            # bootstrap problem. We use a dict to get an error
85f830aa54558b0d4358f427e46171e95c8218f2deJesus Cea            # if some suspicious happens.
86f830aa54558b0d4358f427e46171e95c8218f2deJesus Cea            bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
87f830aa54558b0d4358f427e46171e95c8218f2deJesus Cea            machine += ".%s" % bitness[sys.maxint]
88dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        # fall through to standard osname-release-machine representation
89dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    elif osname[:4] == "irix":              # could be "irix64"!
90dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        return "%s-%s" % (osname, release)
91dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    elif osname[:3] == "aix":
92dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        return "%s-%s.%s" % (osname, version, release)
93dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    elif osname[:6] == "cygwin":
94dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        osname = "cygwin"
95dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        rel_re = re.compile (r'[\d.]+')
96dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        m = rel_re.match(release)
97dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        if m:
98dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé            release = m.group()
99dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    elif osname[:6] == "darwin":
10018fae3f9542fc7bb0d9da53a5de30041651a85b6Ned Deily        import _osx_support, distutils.sysconfig
10118fae3f9542fc7bb0d9da53a5de30041651a85b6Ned Deily        osname, release, machine = _osx_support.get_platform_osx(
10218fae3f9542fc7bb0d9da53a5de30041651a85b6Ned Deily                                        distutils.sysconfig.get_config_vars(),
10318fae3f9542fc7bb0d9da53a5de30041651a85b6Ned Deily                                        osname, release, machine)
10492e68af56a2b95627c2220c3e190d7e3c2d4643eTarek Ziadé
105dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    return "%s-%s-%s" % (osname, release, machine)
106dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
107dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé# get_platform ()
1080276c7ad0b56024f5373ad8f7edca5d77c58df22Tarek Ziadé
1095091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
110dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef convert_path (pathname):
111dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    """Return 'pathname' as a name that will work on the native filesystem,
112b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    i.e. split it on '/' and put it back together again using the current
113b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    directory separator.  Needed because filenames in the setup script are
114b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    always supplied in Unix style, and have to be converted to the local
115b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    convention before we can actually use them in the filesystem.  Raises
1164752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    ValueError on non-Unix-ish systems if 'pathname' either starts or
1174752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    ends with a slash.
118b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    """
1197ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward    if os.sep == '/':
1207ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward        return pathname
121b0df6a1afa585c5f4d097aeb68e41996a9fff9d7Neal Norwitz    if not pathname:
122b0df6a1afa585c5f4d097aeb68e41996a9fff9d7Neal Norwitz        return pathname
123b0df6a1afa585c5f4d097aeb68e41996a9fff9d7Neal Norwitz    if pathname[0] == '/':
124dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        raise ValueError, "path '%s' cannot be absolute" % pathname
125b0df6a1afa585c5f4d097aeb68e41996a9fff9d7Neal Norwitz    if pathname[-1] == '/':
126dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        raise ValueError, "path '%s' cannot end with '/'" % pathname
1277ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward
128dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    paths = string.split(pathname, '/')
129b4cd5c1a3aa11a7b7a180fe1d241968392ab8e33Jack Jansen    while '.' in paths:
130b4cd5c1a3aa11a7b7a180fe1d241968392ab8e33Jack Jansen        paths.remove('.')
131b4cd5c1a3aa11a7b7a180fe1d241968392ab8e33Jack Jansen    if not paths:
132b4cd5c1a3aa11a7b7a180fe1d241968392ab8e33Jack Jansen        return os.curdir
1338d1da0f5c3b8c6e3fa29e6ae7f891f699a041bb6Florent Xicluna    return os.path.join(*paths)
1345091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
135dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé# convert_path ()
1361b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1371b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
138dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef change_root (new_root, pathname):
139dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    """Return 'pathname' with 'new_root' prepended.  If 'pathname' is
140dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    relative, this is equivalent to "os.path.join(new_root,pathname)".
14167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    Otherwise, it requires making 'pathname' relative and then joining the
1424b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward    two, which is tricky on DOS/Windows and Mac OS.
1434b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward    """
1444b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward    if os.name == 'posix':
145be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        if not os.path.isabs(pathname):
146be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward            return os.path.join(new_root, pathname)
1474b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward        else:
148be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward            return os.path.join(new_root, pathname[1:])
14967f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
15067f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    elif os.name == 'nt':
151be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        (drive, path) = os.path.splitdrive(pathname)
1524b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward        if path[0] == '\\':
1534b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward            path = path[1:]
154be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        return os.path.join(new_root, path)
15567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
1562544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg    elif os.name == 'os2':
1572544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg        (drive, path) = os.path.splitdrive(pathname)
1582544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg        if path[0] == os.sep:
1592544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg            path = path[1:]
1602544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg        return os.path.join(new_root, path)
1612544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg
16267f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    else:
163dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        raise DistutilsPlatformError, \
164dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé              "nothing known about platform '%s'" % os.name
16567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
1663757fbba2572133443c250858fcd65c50bf68058Tarek Ziadé
167dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé_environ_checked = 0
168dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef check_environ ():
169dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    """Ensure that 'os.environ' has all the environment variables we
170dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    guarantee that users can use in config files, command-line options,
171b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    etc.  Currently this includes:
172b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward      HOME - user's home directory (Unix only)
173b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward      PLAT - description of the current platform, including hardware
174b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward             and OS (see 'get_platform()')
1751b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    """
176e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    global _environ_checked
177e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    if _environ_checked:
178e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith        return
179e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith
1808bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum    if os.name == 'posix' and 'HOME' not in os.environ:
1811b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        import pwd
182be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
1831b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1848bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum    if 'PLAT' not in os.environ:
185dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        os.environ['PLAT'] = get_platform()
1861b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
187e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    _environ_checked = 1
188e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith
1891b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
190dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef subst_vars (s, local_vars):
191dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    """Perform shell/Perl-style variable substitution on 'string'.  Every
192dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    occurrence of '$' followed by a name is considered a variable, and
1934752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    variable is substituted by the value found in the 'local_vars'
1944752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    dictionary, or in 'os.environ' if it's not in 'local_vars'.
1954752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    'os.environ' is first checked/augmented to guarantee that it contains
1964752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    certain values: see 'check_environ()'.  Raise ValueError for any
1974752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    variables not found in either 'local_vars' or 'os.environ'.
198b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    """
199be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward    check_environ()
2001b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    def _subst (match, local_vars=local_vars):
2011b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        var_name = match.group(1)
2028bc0965adfbe55926a475370c70a8366462dacccGuido van Rossum        if var_name in local_vars:
203be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward            return str(local_vars[var_name])
2041b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        else:
2051b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward            return os.environ[var_name]
2061b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
2074752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    try:
2085e2d0764cd95b40de64fff54e14091e0e6bdf6f6Jeremy Hylton        return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
2094752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    except KeyError, var:
210dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé        raise ValueError, "invalid variable '$%s'" % var
211dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
212dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé# subst_vars ()
2137c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward
2147c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward
215dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef grok_environment_error (exc, prefix="error: "):
2163d1134e39551cd4277538f1fa9137fdf238d07fbÉric Araujo    # Function kept for backward compatibility.
2173d1134e39551cd4277538f1fa9137fdf238d07fbÉric Araujo    # Used to try clever things with EnvironmentErrors,
2183d1134e39551cd4277538f1fa9137fdf238d07fbÉric Araujo    # but nowadays str(exception) produces good messages.
2193d1134e39551cd4277538f1fa9137fdf238d07fbÉric Araujo    return prefix + str(exc)
2206a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
221dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
2226a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward# Needed by 'split_quoted()'
2231c0f1f97fb9021a2084298e04aa920d5f478f0c6Martin v. Löwis_wordchars_re = _squote_re = _dquote_re = None
2241c0f1f97fb9021a2084298e04aa920d5f478f0c6Martin v. Löwisdef _init_regex():
2251c0f1f97fb9021a2084298e04aa920d5f478f0c6Martin v. Löwis    global _wordchars_re, _squote_re, _dquote_re
2261c0f1f97fb9021a2084298e04aa920d5f478f0c6Martin v. Löwis    _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
2271c0f1f97fb9021a2084298e04aa920d5f478f0c6Martin v. Löwis    _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
2281c0f1f97fb9021a2084298e04aa920d5f478f0c6Martin v. Löwis    _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
2296a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
230dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef split_quoted (s):
2316a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    """Split a string up according to Unix shell-like rules for quotes and
232dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    backslashes.  In short: words are delimited by spaces, as long as those
2336a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    spaces are not escaped by a backslash, or inside a quoted string.
2346a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    Single and double quotes are equivalent, and the quote characters can
2356a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    be backslash-escaped.  The backslash is stripped from any two-character
2366a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    escape sequence, leaving only the escaped character.  The quote
2376a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    characters are stripped from any quoted string.  Returns a list of
2386a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    words.
2396a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    """
240dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé
2416a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    # This is a nice algorithm for splitting up a single string, since it
2426a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    # doesn't require character-by-character examination.  It was a little
2436a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    # bit of a brain-bender to get it working right, though...
2441c0f1f97fb9021a2084298e04aa920d5f478f0c6Martin v. Löwis    if _wordchars_re is None: _init_regex()
2456a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
246dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    s = string.strip(s)
2476a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    words = []
2486a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    pos = 0
2496a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2506a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    while s:
2516a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        m = _wordchars_re.match(s, pos)
2526a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        end = m.end()
2536a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        if end == len(s):
2546a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            words.append(s[:end])
2556a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            break
2566a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2572b042ded19bc7efa43551da297c29dc142b7d73cGreg Ward        if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
2586a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            words.append(s[:end])       # we definitely have a word delimiter
259dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé            s = string.lstrip(s[end:])
2606a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            pos = 0
2616a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2626a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        elif s[end] == '\\':            # preserve whatever is being escaped;
2636a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                                        # will become part of the current word
2646a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            s = s[:end] + s[end+1:]
2656a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            pos = end+1
2666a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2676a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        else:
2686a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            if s[end] == "'":           # slurp singly-quoted string
2696a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                m = _squote_re.match(s, end)
2706a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            elif s[end] == '"':         # slurp doubly-quoted string
2716a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                m = _dquote_re.match(s, end)
2726a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            else:
273dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                raise RuntimeError, \
274dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                      "this can't happen (bad char '%c')" % s[end]
2756a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2766a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            if m is None:
277dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                raise ValueError, \
278dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                      "bad string (mismatched %s quotes?)" % s[end]
2796a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2806a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            (beg, end) = m.span()
2816a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            s = s[:beg] + s[beg+1:end-1] + s[end:]
2826a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            pos = m.end() - 2
2836a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2846a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        if pos >= len(s):
2856a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            words.append(s)
2866a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            break
2876a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2886a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    return words
2896a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
290dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé# split_quoted ()
2911c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward
2921c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward
293dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef execute (func, args, msg=None, verbose=0, dry_run=0):
294dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    """Perform some action that affects the outside world (eg.  by
295dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    writing to the filesystem).  Such actions are special because they
296dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    are disabled by the 'dry_run' flag.  This method takes care of all
297cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    that bureaucracy for you; all you have to do is supply the
298cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    function to call and an argument tuple for it (to embody the
299cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    "external action" being performed), and an optional message to
300cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    print.
3011c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward    """
3021c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward    if msg is None:
30370a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald        msg = "%s%r" % (func.__name__, args)
304b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake        if msg[-2:] == ',)':        # correct for singleton tuple
3051c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward            msg = msg[0:-2] + ')'
3061c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward
307cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    log.info(msg)
3081c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward    if not dry_run:
3091f3b4e12e8ba9cd896625ba02ea1ab6849ca3a07Florent Xicluna        func(*args)
3101c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward
311817dc098efd0c2cba674cee32950fc5626e12881Greg Ward
312dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef strtobool (val):
313817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    """Convert a string representation of truth to true (1) or false (0).
314182b5aca27d376b08a2904bed42b751496f932f3Tim Peters
315817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
316817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    are 'n', 'no', 'f', 'false', 'off', and '0'.  Raises ValueError if
317817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    'val' is anything else.
318817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    """
319dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    val = string.lower(val)
320817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    if val in ('y', 'yes', 't', 'true', 'on', '1'):
321817dc098efd0c2cba674cee32950fc5626e12881Greg Ward        return 1
322817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    elif val in ('n', 'no', 'f', 'false', 'off', '0'):
323817dc098efd0c2cba674cee32950fc5626e12881Greg Ward        return 0
324817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    else:
32570a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald        raise ValueError, "invalid truth value %r" % (val,)
3261297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3271297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
328dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef byte_compile (py_files,
329dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                  optimize=0, force=0,
330dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                  prefix=None, base_dir=None,
331dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                  verbose=1, dry_run=0,
332dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                  direct=None):
333f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward    """Byte-compile a collection of Python source files to either .pyc
334dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    or .pyo files in the same directory.  'py_files' is a list of files
335dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    to compile; any files that don't end in ".py" are silently skipped.
336dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    'optimize' must be one of the following:
3371297b5ce67642dba35615121825fb1621e28e6b8Greg Ward      0 - don't optimize (generate .pyc)
3381297b5ce67642dba35615121825fb1621e28e6b8Greg Ward      1 - normal optimization (like "python -O")
3391297b5ce67642dba35615121825fb1621e28e6b8Greg Ward      2 - extra optimization (like "python -OO")
3401297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    If 'force' is true, all files are recompiled regardless of
3411297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    timestamps.
3421297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3431297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    The source filename encoded in each bytecode file defaults to the
3441297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    filenames listed in 'py_files'; you can modify these with 'prefix' and
3451297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    'basedir'.  'prefix' is a string that will be stripped off of each
3461297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    source filename, and 'base_dir' is a directory name that will be
3471297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    prepended (after 'prefix' is stripped).  You can supply either or both
3481297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    (or neither) of 'prefix' and 'base_dir', as you wish.
3491297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
350cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    If 'dry_run' is true, doesn't actually do anything that would
351cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    affect the filesystem.
3521297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3531297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    Byte-compilation is either done directly in this interpreter process
3541297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    with the standard py_compile module, or indirectly by writing a
3551297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    temporary script and executing it.  Normally, you should let
3561297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    'byte_compile()' figure out to use direct compilation or not (see
3571297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    the source for details).  The 'direct' flag is used by the script
3581297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    generated in indirect mode; unless you know what you're doing, leave
3591297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    it set to None.
3601297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    """
361b9c1cfc42881370322ff6894568b45dcfec5ba2eTarek Ziadé    # nothing is done if sys.dont_write_bytecode is True
362b9c1cfc42881370322ff6894568b45dcfec5ba2eTarek Ziadé    if sys.dont_write_bytecode:
3631733c9362b7520278120423550de28da44d15f33Tarek Ziadé        raise DistutilsByteCompileError('byte-compiling is disabled.')
364b9c1cfc42881370322ff6894568b45dcfec5ba2eTarek Ziadé
3651297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # First, if the caller didn't force us into direct or indirect mode,
3661297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # figure out which mode we should be in.  We take a conservative
3671297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # approach: choose direct mode *only* if the current interpreter is
3681297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # in debug mode and optimize is 0.  If we're not in debug mode (-O
3691297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # or -OO), we don't know which level of optimization this
3701297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # interpreter is running with, so we can't do direct
3711297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # byte-compilation and be certain that it's the right thing.  Thus,
3721297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # always compile indirectly if the current interpreter is in either
3731297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # optimize mode, or if either optimization level was requested by
3741297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # the caller.
3751297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    if direct is None:
3761297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        direct = (__debug__ and optimize == 0)
3771297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3781297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # "Indirect" byte-compilation: write a temporary script and then
3791297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # run it with the appropriate flags.
3801297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    if not direct:
3810375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg        try:
3820375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg            from tempfile import mkstemp
3830375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg            (script_fd, script_name) = mkstemp(".py")
3840375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg        except ImportError:
3850375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg            from tempfile import mktemp
3860375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg            (script_fd, script_name) = None, mktemp(".py")
387cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.info("writing byte-compilation script '%s'", script_name)
3881297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        if not dry_run:
3890375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg            if script_fd is not None:
3900375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg                script = os.fdopen(script_fd, "w")
3910375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg            else:
3920375079e934156491ffe04771d7f4470f391377eMarc-André Lemburg                script = open(script_name, "w")
3931297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3941297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            script.write("""\
3951297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfrom distutils.util import byte_compile
3961297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfiles = [
3971297b5ce67642dba35615121825fb1621e28e6b8Greg Ward""")
3989216cfe7ba0257f10790f919e50283114a3476ddGreg Ward
3999216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # XXX would be nice to write absolute filenames, just for
4009216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # safety's sake (script should be more robust in the face of
4019216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # chdir'ing before running it).  But this requires abspath'ing
4029216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # 'prefix' as well, and that breaks the hack in build_lib's
4039216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # 'byte_compile()' method that carefully tacks on a trailing
4049216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # slash (os.sep really) to make sure the prefix here is "just
4059216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # right".  This whole prefix business is rather delicate -- the
4069216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # problem is that it's really a directory, but I'm treating it
4079216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # as a dumb string, so trailing slashes and so forth matter.
4089216cfe7ba0257f10790f919e50283114a3476ddGreg Ward
4099216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            #py_files = map(os.path.abspath, py_files)
4109216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            #if prefix:
4119216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            #    prefix = os.path.abspath(prefix)
4129216cfe7ba0257f10790f919e50283114a3476ddGreg Ward
413dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé            script.write(string.join(map(repr, py_files), ",\n") + "]\n")
4141297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            script.write("""
41570a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwaldbyte_compile(files, optimize=%r, force=%r,
41670a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald             prefix=%r, base_dir=%r,
41770a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald             verbose=%r, dry_run=0,
4181297b5ce67642dba35615121825fb1621e28e6b8Greg Ward             direct=1)
41970a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald""" % (optimize, force, prefix, base_dir, verbose))
4201297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4211297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            script.close()
4221297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4231297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        cmd = [sys.executable, script_name]
4241297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        if optimize == 1:
4251297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            cmd.insert(1, "-O")
4261297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        elif optimize == 2:
4271297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            cmd.insert(1, "-OO")
428cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        spawn(cmd, dry_run=dry_run)
4299216cfe7ba0257f10790f919e50283114a3476ddGreg Ward        execute(os.remove, (script_name,), "removing %s" % script_name,
430cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton                dry_run=dry_run)
431b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
4321297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # "Direct" byte-compilation: use the py_compile module to compile
4331297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # right here, right now.  Note that the script generated in indirect
4341297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # mode simply calls 'byte_compile()' in direct mode, a weird sort of
4351297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # cross-process recursion.  Hey, it works!
4361297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    else:
4371297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        from py_compile import compile
4381297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4391297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        for file in py_files:
4401297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            if file[-3:] != ".py":
441f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward                # This lets us be lazy and not filter filenames in
442f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward                # the "install_lib" command.
443f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward                continue
4441297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4451297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            # Terminology from the py_compile module:
4461297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            #   cfile - byte-compiled file
4471297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            #   dfile - purported source filename (same as 'file' by default)
4481297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            cfile = file + (__debug__ and "c" or "o")
4491297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            dfile = file
4501297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            if prefix:
4511297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                if file[:len(prefix)] != prefix:
452dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                    raise ValueError, \
453dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                          ("invalid prefix: filename %r doesn't start with %r"
454dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé                           % (file, prefix))
4551297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                dfile = dfile[len(prefix):]
4561297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            if base_dir:
4571297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                dfile = os.path.join(base_dir, dfile)
4581297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4591297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            cfile_base = os.path.basename(cfile)
4601297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            if direct:
4611297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                if force or newer(file, cfile):
462cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton                    log.info("byte-compiling %s to %s", file, cfile_base)
4631297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                    if not dry_run:
4641297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                        compile(file, cfile, dfile)
4651297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                else:
466cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton                    log.debug("skipping byte-compilation of %s to %s",
467cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton                              file, cfile_base)
4681297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
469dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé# byte_compile ()
470df66df0a286c5d09022e7efe839759797318506cAndrew M. Kuchling
471dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadédef rfc822_escape (header):
472df66df0a286c5d09022e7efe839759797318506cAndrew M. Kuchling    """Return a version of the string escaped for inclusion in an
47388b0884787f06667f59ebaab5413f3bedcdd631cAndrew M. Kuchling    RFC-822 header, by ensuring there are 8 spaces space after each newline.
474df66df0a286c5d09022e7efe839759797318506cAndrew M. Kuchling    """
475dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    lines = string.split(header, '\n')
476dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    header = string.join(lines, '\n' + 8*' ')
477dd7bef9bf56933851e68094ffc70f8f20bc6b036Tarek Ziadé    return header
478