util.py revision b0df6a1afa585c5f4d097aeb68e41996a9fff9d7
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
72689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# created 1999/03/08, Greg Ward
82689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
93ce77fd05ed00168f618b63401d770ccc4f04b09Greg Ward__revision__ = "$Id$"
102689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
111297b5ce67642dba35615121825fb1621e28e6b8Greg Wardimport sys, os, string, re
121297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfrom distutils.errors import DistutilsPlatformError
131297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfrom distutils.dep_util import newer
147c1a6d477771955e3773849ef636fceda81bb3d5Greg Wardfrom distutils.spawn import spawn
15cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hyltonfrom distutils import log
16aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward
17585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Warddef get_platform ():
1859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    """Return a string that identifies the current platform.  This is used
1959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    mainly to distinguish platform-specific build directories and
2059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    platform-specific built distributions.  Typically includes the OS name
2159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    and version and the architecture (as supplied by 'os.uname()'),
2259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    although the exact information included depends on the OS; eg. for IRIX
2359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    the architecture isn't particularly important (IRIX only runs on SGI
2459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    hardware), but for Linux the kernel version isn't particularly
2559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    important.
2659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward
2759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    Examples of returned values:
2859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward       linux-i586
2959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward       linux-alpha (?)
3059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward       solaris-2.6-sun4u
3159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward       irix-5.3
3259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward       irix64-6.2
33b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
3459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    For non-POSIX platforms, currently just returns 'sys.platform'.
35b75c485f0bc6394f616d4a0bc746e613fd7b1021Greg Ward    """
36ec84c21ce2d022ea95bb67ab711f7580036611e5Greg Ward    if os.name != "posix" or not hasattr(os, 'uname'):
3759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        # XXX what about the architecture? NT is Intel or Alpha,
3859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        # Mac OS is M68k or PPC, etc.
3959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        return sys.platform
4059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward
4159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    # Try to distinguish various flavours of Unix
4259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward
4359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    (osname, host, release, version, machine) = os.uname()
4483c158fdc9d9acb737172a1a365014514afd4fc9Andrew M. Kuchling
4583c158fdc9d9acb737172a1a365014514afd4fc9Andrew M. Kuchling    # Convert the OS name to lowercase and remove '/' characters
4683c158fdc9d9acb737172a1a365014514afd4fc9Andrew M. Kuchling    # (to accommodate BSD/OS)
47b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake    osname = string.lower(osname)
4883c158fdc9d9acb737172a1a365014514afd4fc9Andrew M. Kuchling    osname = string.replace(osname, '/', '')
49b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
5059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    if osname[:5] == "linux":
5159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        # At least on Linux/Intel, 'machine' is the processor --
5259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        # i386, etc.
5359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        # XXX what about Alpha, SPARC, etc?
5459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        return  "%s-%s" % (osname, machine)
5559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    elif osname[:5] == "sunos":
5659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        if release[0] >= "5":           # SunOS 5 == Solaris 2
5759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward            osname = "solaris"
5859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward            release = "%d.%s" % (int(release[0]) - 3, release[2:])
5959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        # fall through to standard osname-release-machine representation
6059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    elif osname[:4] == "irix":              # could be "irix64"!
6159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward        return "%s-%s" % (osname, release)
62b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake    elif osname[:3] == "aix":
639767e76808f58bae054cacb2276491d5dd6e177dAndrew M. Kuchling        return "%s-%s.%s" % (osname, version, release)
64989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling    elif osname[:6] == "cygwin":
655a3e4cb0a2b922bbbcaf3e3afa9693b57e189ea4Andrew M. Kuchling        osname = "cygwin"
66989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling        rel_re = re.compile (r'[\d.]+')
67989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling        m = rel_re.match(release)
68989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling        if m:
69989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling            release = m.group()
70b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
7159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward    return "%s-%s-%s" % (osname, release, machine)
7259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward
7359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward# get_platform ()
745091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
755091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
76d8dfb4c4b8d661acee263e3feb77974ced69e97dGreg Warddef convert_path (pathname):
77b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    """Return 'pathname' as a name that will work on the native filesystem,
78b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    i.e. split it on '/' and put it back together again using the current
79b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    directory separator.  Needed because filenames in the setup script are
80b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    always supplied in Unix style, and have to be converted to the local
81b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    convention before we can actually use them in the filesystem.  Raises
824752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    ValueError on non-Unix-ish systems if 'pathname' either starts or
834752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    ends with a slash.
84b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    """
857ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward    if os.sep == '/':
867ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward        return pathname
87b0df6a1afa585c5f4d097aeb68e41996a9fff9d7Neal Norwitz    if not pathname:
88b0df6a1afa585c5f4d097aeb68e41996a9fff9d7Neal Norwitz        return pathname
89b0df6a1afa585c5f4d097aeb68e41996a9fff9d7Neal Norwitz    if pathname[0] == '/':
9002a1a2b077e969e5fef8504cece5852bf641552dGreg Ward        raise ValueError, "path '%s' cannot be absolute" % pathname
91b0df6a1afa585c5f4d097aeb68e41996a9fff9d7Neal Norwitz    if pathname[-1] == '/':
9202a1a2b077e969e5fef8504cece5852bf641552dGreg Ward        raise ValueError, "path '%s' cannot end with '/'" % pathname
937ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward
947ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward    paths = string.split(pathname, '/')
95b4cd5c1a3aa11a7b7a180fe1d241968392ab8e33Jack Jansen    while '.' in paths:
96b4cd5c1a3aa11a7b7a180fe1d241968392ab8e33Jack Jansen        paths.remove('.')
97b4cd5c1a3aa11a7b7a180fe1d241968392ab8e33Jack Jansen    if not paths:
98b4cd5c1a3aa11a7b7a180fe1d241968392ab8e33Jack Jansen        return os.curdir
997ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward    return apply(os.path.join, paths)
1005091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
101d8dfb4c4b8d661acee263e3feb77974ced69e97dGreg Ward# convert_path ()
1021b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1031b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
10467f75d4bcb3630c0f5b6761fb758072cc342157eGreg Warddef change_root (new_root, pathname):
10567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    """Return 'pathname' with 'new_root' prepended.  If 'pathname' is
10667f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    relative, this is equivalent to "os.path.join(new_root,pathname)".
10767f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    Otherwise, it requires making 'pathname' relative and then joining the
1084b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward    two, which is tricky on DOS/Windows and Mac OS.
1094b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward    """
1104b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward    if os.name == 'posix':
111be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        if not os.path.isabs(pathname):
112be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward            return os.path.join(new_root, pathname)
1134b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward        else:
114be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward            return os.path.join(new_root, pathname[1:])
11567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
11667f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    elif os.name == 'nt':
117be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        (drive, path) = os.path.splitdrive(pathname)
1184b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward        if path[0] == '\\':
1194b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward            path = path[1:]
120be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        return os.path.join(new_root, path)
12167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
1222544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg    elif os.name == 'os2':
1232544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg        (drive, path) = os.path.splitdrive(pathname)
1242544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg        if path[0] == os.sep:
1252544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg            path = path[1:]
1262544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg        return os.path.join(new_root, path)
1272544f51036c51d87be53f6a5e35e867c8333378aMarc-André Lemburg
12867f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    elif os.name == 'mac':
129f5855746fe0851e5a80b32061cb819021285ff25Greg Ward        if not os.path.isabs(pathname):
130f5855746fe0851e5a80b32061cb819021285ff25Greg Ward            return os.path.join(new_root, pathname)
131f5855746fe0851e5a80b32061cb819021285ff25Greg Ward        else:
132f5855746fe0851e5a80b32061cb819021285ff25Greg Ward            # Chop off volume name from start of path
133f5855746fe0851e5a80b32061cb819021285ff25Greg Ward            elements = string.split(pathname, ":", 1)
134f5855746fe0851e5a80b32061cb819021285ff25Greg Ward            pathname = ":" + elements[1]
135f5855746fe0851e5a80b32061cb819021285ff25Greg Ward            return os.path.join(new_root, pathname)
13667f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
13767f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    else:
13867f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward        raise DistutilsPlatformError, \
13967f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward              "nothing known about platform '%s'" % os.name
14067f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
14167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
142e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith_environ_checked = 0
143e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smithdef check_environ ():
1441b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    """Ensure that 'os.environ' has all the environment variables we
145b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    guarantee that users can use in config files, command-line options,
146b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    etc.  Currently this includes:
147b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward      HOME - user's home directory (Unix only)
148b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward      PLAT - description of the current platform, including hardware
149b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward             and OS (see 'get_platform()')
1501b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    """
151e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    global _environ_checked
152e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    if _environ_checked:
153e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith        return
154e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith
1551b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    if os.name == 'posix' and not os.environ.has_key('HOME'):
1561b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        import pwd
157be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
1581b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1591b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    if not os.environ.has_key('PLAT'):
160be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        os.environ['PLAT'] = get_platform()
1611b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
162e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    _environ_checked = 1
163e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith
1641b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1655e2d0764cd95b40de64fff54e14091e0e6bdf6f6Jeremy Hyltondef subst_vars (s, local_vars):
166b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    """Perform shell/Perl-style variable substitution on 'string'.  Every
1674752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    occurrence of '$' followed by a name is considered a variable, and
1684752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    variable is substituted by the value found in the 'local_vars'
1694752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    dictionary, or in 'os.environ' if it's not in 'local_vars'.
1704752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    'os.environ' is first checked/augmented to guarantee that it contains
1714752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    certain values: see 'check_environ()'.  Raise ValueError for any
1724752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    variables not found in either 'local_vars' or 'os.environ'.
173b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward    """
174be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward    check_environ()
1751b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    def _subst (match, local_vars=local_vars):
1761b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        var_name = match.group(1)
177be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward        if local_vars.has_key(var_name):
178be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward            return str(local_vars[var_name])
1791b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        else:
1801b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward            return os.environ[var_name]
1811b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1824752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    try:
1835e2d0764cd95b40de64fff54e14091e0e6bdf6f6Jeremy Hylton        return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
1844752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward    except KeyError, var:
1854752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward        raise ValueError, "invalid variable '$%s'" % var
1861b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1871b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward# subst_vars ()
1887c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward
1897c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward
190e905513be0718c5a8edafe70efc0fe0d4f290573Greg Warddef grok_environment_error (exc, prefix="error: "):
191e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    """Generate a useful error message from an EnvironmentError (IOError or
192e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    OSError) exception object.  Handles Python 1.5.1 and 1.5.2 styles, and
193e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    does what it can to deal with exception objects that don't have a
194e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    filename (which happens when the error is due to a two-file operation,
195e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    such as 'rename()' or 'link()'.  Returns the error message as a string
196e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    prefixed with 'prefix'.
197e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    """
198e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    # check for Python 1.5.2-style {IO,OS}Error exception objects
199be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward    if hasattr(exc, 'filename') and hasattr(exc, 'strerror'):
200e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward        if exc.filename:
201e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward            error = prefix + "%s: %s" % (exc.filename, exc.strerror)
202e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward        else:
203e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward            # two-argument functions in posix module don't
204e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward            # include the filename in the exception object!
205e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward            error = prefix + "%s" % exc.strerror
206e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    else:
207e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward        error = prefix + str(exc[-1])
208e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward
209e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward    return error
2106a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2116a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2126a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward# Needed by 'split_quoted()'
2132b042ded19bc7efa43551da297c29dc142b7d73cGreg Ward_wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
2146a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward_squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
2156a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward_dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
2166a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2176a2a3dbec59f267e05c0c507457dfd234263237bGreg Warddef split_quoted (s):
2186a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    """Split a string up according to Unix shell-like rules for quotes and
2196a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    backslashes.  In short: words are delimited by spaces, as long as those
2206a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    spaces are not escaped by a backslash, or inside a quoted string.
2216a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    Single and double quotes are equivalent, and the quote characters can
2226a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    be backslash-escaped.  The backslash is stripped from any two-character
2236a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    escape sequence, leaving only the escaped character.  The quote
2246a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    characters are stripped from any quoted string.  Returns a list of
2256a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    words.
2266a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    """
2276a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2286a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    # This is a nice algorithm for splitting up a single string, since it
2296a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    # doesn't require character-by-character examination.  It was a little
2306a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    # bit of a brain-bender to get it working right, though...
2316a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2326a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    s = string.strip(s)
2336a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    words = []
2346a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    pos = 0
2356a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2366a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    while s:
2376a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        m = _wordchars_re.match(s, pos)
2386a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        end = m.end()
2396a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        if end == len(s):
2406a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            words.append(s[:end])
2416a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            break
2426a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2432b042ded19bc7efa43551da297c29dc142b7d73cGreg Ward        if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
2446a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            words.append(s[:end])       # we definitely have a word delimiter
2456a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            s = string.lstrip(s[end:])
2466a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            pos = 0
2476a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2486a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        elif s[end] == '\\':            # preserve whatever is being escaped;
2496a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                                        # will become part of the current word
2506a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            s = s[:end] + s[end+1:]
2516a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            pos = end+1
2526a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2536a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        else:
2546a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            if s[end] == "'":           # slurp singly-quoted string
2556a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                m = _squote_re.match(s, end)
2566a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            elif s[end] == '"':         # slurp doubly-quoted string
2576a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                m = _dquote_re.match(s, end)
2586a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            else:
2596a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                raise RuntimeError, \
2606a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                      "this can't happen (bad char '%c')" % s[end]
2616a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2626a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            if m is None:
2636a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                raise ValueError, \
2646a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward                      "bad string (mismatched %s quotes?)" % s[end]
2656a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2666a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            (beg, end) = m.span()
2676a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            s = s[:beg] + s[beg+1:end-1] + s[end:]
2686a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            pos = m.end() - 2
2696a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2706a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward        if pos >= len(s):
2716a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            words.append(s)
2726a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward            break
2736a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2746a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward    return words
2756a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward
2766a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward# split_quoted ()
2771c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward
2781c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward
2791c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Warddef execute (func, args, msg=None, verbose=0, dry_run=0):
280cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    """Perform some action that affects the outside world (eg.  by
281cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    writing to the filesystem).  Such actions are special because they
282cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    are disabled by the 'dry_run' flag.  This method takes care of all
283cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    that bureaucracy for you; all you have to do is supply the
284cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    function to call and an argument tuple for it (to embody the
285cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    "external action" being performed), and an optional message to
286cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    print.
2871c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward    """
2881c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward    if msg is None:
2891c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward        msg = "%s%s" % (func.__name__, `args`)
290b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake        if msg[-2:] == ',)':        # correct for singleton tuple
2911c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward            msg = msg[0:-2] + ')'
2921c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward
293cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    log.info(msg)
2941c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward    if not dry_run:
2951c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward        apply(func, args)
2961c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward
297817dc098efd0c2cba674cee32950fc5626e12881Greg Ward
298817dc098efd0c2cba674cee32950fc5626e12881Greg Warddef strtobool (val):
299817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    """Convert a string representation of truth to true (1) or false (0).
300cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton
301817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
302817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    are 'n', 'no', 'f', 'false', 'off', and '0'.  Raises ValueError if
303817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    'val' is anything else.
304817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    """
305817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    val = string.lower(val)
306817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    if val in ('y', 'yes', 't', 'true', 'on', '1'):
307817dc098efd0c2cba674cee32950fc5626e12881Greg Ward        return 1
308817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    elif val in ('n', 'no', 'f', 'false', 'off', '0'):
309817dc098efd0c2cba674cee32950fc5626e12881Greg Ward        return 0
310817dc098efd0c2cba674cee32950fc5626e12881Greg Ward    else:
311817dc098efd0c2cba674cee32950fc5626e12881Greg Ward        raise ValueError, "invalid truth value %s" % `val`
3121297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3131297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3141297b5ce67642dba35615121825fb1621e28e6b8Greg Warddef byte_compile (py_files,
3151297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                  optimize=0, force=0,
3161297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                  prefix=None, base_dir=None,
3171297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                  verbose=1, dry_run=0,
3181297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                  direct=None):
319f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward    """Byte-compile a collection of Python source files to either .pyc
320f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward    or .pyo files in the same directory.  'py_files' is a list of files
321f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward    to compile; any files that don't end in ".py" are silently skipped.
322f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward    'optimize' must be one of the following:
3231297b5ce67642dba35615121825fb1621e28e6b8Greg Ward      0 - don't optimize (generate .pyc)
3241297b5ce67642dba35615121825fb1621e28e6b8Greg Ward      1 - normal optimization (like "python -O")
3251297b5ce67642dba35615121825fb1621e28e6b8Greg Ward      2 - extra optimization (like "python -OO")
3261297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    If 'force' is true, all files are recompiled regardless of
3271297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    timestamps.
3281297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3291297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    The source filename encoded in each bytecode file defaults to the
3301297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    filenames listed in 'py_files'; you can modify these with 'prefix' and
3311297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    'basedir'.  'prefix' is a string that will be stripped off of each
3321297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    source filename, and 'base_dir' is a directory name that will be
3331297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    prepended (after 'prefix' is stripped).  You can supply either or both
3341297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    (or neither) of 'prefix' and 'base_dir', as you wish.
3351297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
336cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    If 'dry_run' is true, doesn't actually do anything that would
337cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton    affect the filesystem.
3381297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3391297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    Byte-compilation is either done directly in this interpreter process
3401297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    with the standard py_compile module, or indirectly by writing a
3411297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    temporary script and executing it.  Normally, you should let
3421297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    'byte_compile()' figure out to use direct compilation or not (see
3431297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    the source for details).  The 'direct' flag is used by the script
3441297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    generated in indirect mode; unless you know what you're doing, leave
3451297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    it set to None.
3461297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    """
3471297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3481297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # First, if the caller didn't force us into direct or indirect mode,
3491297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # figure out which mode we should be in.  We take a conservative
3501297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # approach: choose direct mode *only* if the current interpreter is
3511297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # in debug mode and optimize is 0.  If we're not in debug mode (-O
3521297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # or -OO), we don't know which level of optimization this
3531297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # interpreter is running with, so we can't do direct
3541297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # byte-compilation and be certain that it's the right thing.  Thus,
3551297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # always compile indirectly if the current interpreter is in either
3561297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # optimize mode, or if either optimization level was requested by
3571297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # the caller.
3581297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    if direct is None:
3591297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        direct = (__debug__ and optimize == 0)
3601297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3611297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # "Indirect" byte-compilation: write a temporary script and then
3621297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # run it with the appropriate flags.
3631297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    if not direct:
3643b0a3293c369f3c3f4753e3cb9172cb4e242af76Guido van Rossum        from tempfile import mkstemp
3653b0a3293c369f3c3f4753e3cb9172cb4e242af76Guido van Rossum        (script_fd, script_name) = mkstemp(".py")
366cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        log.info("writing byte-compilation script '%s'", script_name)
3671297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        if not dry_run:
3683b0a3293c369f3c3f4753e3cb9172cb4e242af76Guido van Rossum            script = os.fdopen(script_fd, "w")
3691297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3701297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            script.write("""\
3711297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfrom distutils.util import byte_compile
3721297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfiles = [
3731297b5ce67642dba35615121825fb1621e28e6b8Greg Ward""")
3749216cfe7ba0257f10790f919e50283114a3476ddGreg Ward
3759216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # XXX would be nice to write absolute filenames, just for
3769216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # safety's sake (script should be more robust in the face of
3779216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # chdir'ing before running it).  But this requires abspath'ing
3789216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # 'prefix' as well, and that breaks the hack in build_lib's
3799216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # 'byte_compile()' method that carefully tacks on a trailing
3809216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # slash (os.sep really) to make sure the prefix here is "just
3819216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # right".  This whole prefix business is rather delicate -- the
3829216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # problem is that it's really a directory, but I'm treating it
3839216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            # as a dumb string, so trailing slashes and so forth matter.
3849216cfe7ba0257f10790f919e50283114a3476ddGreg Ward
3859216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            #py_files = map(os.path.abspath, py_files)
3869216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            #if prefix:
3879216cfe7ba0257f10790f919e50283114a3476ddGreg Ward            #    prefix = os.path.abspath(prefix)
3889216cfe7ba0257f10790f919e50283114a3476ddGreg Ward
3891297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            script.write(string.join(map(repr, py_files), ",\n") + "]\n")
3901297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            script.write("""
3911297b5ce67642dba35615121825fb1621e28e6b8Greg Wardbyte_compile(files, optimize=%s, force=%s,
3921297b5ce67642dba35615121825fb1621e28e6b8Greg Ward             prefix=%s, base_dir=%s,
3931297b5ce67642dba35615121825fb1621e28e6b8Greg Ward             verbose=%s, dry_run=0,
3941297b5ce67642dba35615121825fb1621e28e6b8Greg Ward             direct=1)
3951297b5ce67642dba35615121825fb1621e28e6b8Greg Ward""" % (`optimize`, `force`, `prefix`, `base_dir`, `verbose`))
3961297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3971297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            script.close()
3981297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
3991297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        cmd = [sys.executable, script_name]
4001297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        if optimize == 1:
4011297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            cmd.insert(1, "-O")
4021297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        elif optimize == 2:
4031297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            cmd.insert(1, "-OO")
404cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton        spawn(cmd, dry_run=dry_run)
4059216cfe7ba0257f10790f919e50283114a3476ddGreg Ward        execute(os.remove, (script_name,), "removing %s" % script_name,
406cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton                dry_run=dry_run)
407b94b849d65af71b4b432a74fdaef8ccd88209cc0Fred Drake
4081297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # "Direct" byte-compilation: use the py_compile module to compile
4091297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # right here, right now.  Note that the script generated in indirect
4101297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # mode simply calls 'byte_compile()' in direct mode, a weird sort of
4111297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    # cross-process recursion.  Hey, it works!
4121297b5ce67642dba35615121825fb1621e28e6b8Greg Ward    else:
4131297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        from py_compile import compile
4141297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4151297b5ce67642dba35615121825fb1621e28e6b8Greg Ward        for file in py_files:
4161297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            if file[-3:] != ".py":
417f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward                # This lets us be lazy and not filter filenames in
418f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward                # the "install_lib" command.
419f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward                continue
4201297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4211297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            # Terminology from the py_compile module:
4221297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            #   cfile - byte-compiled file
4231297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            #   dfile - purported source filename (same as 'file' by default)
4241297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            cfile = file + (__debug__ and "c" or "o")
4251297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            dfile = file
4261297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            if prefix:
4271297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                if file[:len(prefix)] != prefix:
4281297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                    raise ValueError, \
4291297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                          ("invalid prefix: filename %s doesn't start with %s"
4301297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                           % (`file`, `prefix`))
4311297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                dfile = dfile[len(prefix):]
4321297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            if base_dir:
4331297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                dfile = os.path.join(base_dir, dfile)
4341297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4351297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            cfile_base = os.path.basename(cfile)
4361297b5ce67642dba35615121825fb1621e28e6b8Greg Ward            if direct:
4371297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                if force or newer(file, cfile):
438cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton                    log.info("byte-compiling %s to %s", file, cfile_base)
4391297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                    if not dry_run:
4401297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                        compile(file, cfile, dfile)
4411297b5ce67642dba35615121825fb1621e28e6b8Greg Ward                else:
442cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton                    log.debug("skipping byte-compilation of %s to %s",
443cd8a1148e19116db109f27d26c02e1de536dc76eJeremy Hylton                              file, cfile_base)
4441297b5ce67642dba35615121825fb1621e28e6b8Greg Ward
4451297b5ce67642dba35615121825fb1621e28e6b8Greg Ward# byte_compile ()
446df66df0a286c5d09022e7efe839759797318506cAndrew M. Kuchling
447df66df0a286c5d09022e7efe839759797318506cAndrew M. Kuchlingdef rfc822_escape (header):
448df66df0a286c5d09022e7efe839759797318506cAndrew M. Kuchling    """Return a version of the string escaped for inclusion in an
44988b0884787f06667f59ebaab5413f3bedcdd631cAndrew M. Kuchling    RFC-822 header, by ensuring there are 8 spaces space after each newline.
450df66df0a286c5d09022e7efe839759797318506cAndrew M. Kuchling    """
45188b0884787f06667f59ebaab5413f3bedcdd631cAndrew M. Kuchling    lines = string.split(header, '\n')
45288b0884787f06667f59ebaab5413f3bedcdd631cAndrew M. Kuchling    lines = map(string.strip, lines)
45388b0884787f06667f59ebaab5413f3bedcdd631cAndrew M. Kuchling    header = string.join(lines, '\n' + 8*' ')
454df66df0a286c5d09022e7efe839759797318506cAndrew M. Kuchling    return header
455