util.py revision e7e35ac1c2e3c6b6a0836931b5c678d6af17129c
12689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward"""distutils.util
22689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
3aebf706b4e845d7525d2d8e792f0e23fcfb3e6afGreg WardMiscellaneous utility functions -- anything that doesn't fit into
4aebf706b4e845d7525d2d8e792f0e23fcfb3e6afGreg Wardone of the other *util.py modules."""
52689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
62689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward# created 1999/03/08, Greg Ward
72689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
83ce77fd05ed00168f618b63401d770ccc4f04b09Greg Ward__revision__ = "$Id$"
92689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
10a7540bd043622de917fdc929310e1b5ca214ab83Greg Wardimport sys, os, string, re, shutil
112689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Wardfrom distutils.errors import *
127c1a6d477771955e3773849ef636fceda81bb3d5Greg Wardfrom distutils.spawn import spawn
132689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward
14aebf706b4e845d7525d2d8e792f0e23fcfb3e6afGreg Ward# for backwards compatibility:
15aebf706b4e845d7525d2d8e792f0e23fcfb3e6afGreg Wardfrom distutils.file_util import *
16aebf706b4e845d7525d2d8e792f0e23fcfb3e6afGreg Wardfrom distutils.dir_util import *
17aebf706b4e845d7525d2d8e792f0e23fcfb3e6afGreg Wardfrom distutils.dep_util import *
18aebf706b4e845d7525d2d8e792f0e23fcfb3e6afGreg Wardfrom distutils.archive_util import *
19585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward
20585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward
21aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward# Need to define 'abspath()', because it was new with Python 1.5.2
22aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Wardif hasattr (os.path, 'abspath'):
23aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward    abspath = os.path.abspath
24aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Wardelse:
25aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward    def abspath(path):
26aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward        if not os.path.isabs(path):
27aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward            path = os.path.join(os.getcwd(), path)
28aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward        return os.path.normpath(path)
29aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward
30aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward
31aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward# More backwards compatability hacks
32aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Warddef extend (list, new_list):
33aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward    """Appends the list 'new_list' to 'list', just like the 'extend()'
34aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward       list method does in Python 1.5.2 -- but this works on earlier
35aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward       versions of Python too."""
36aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward
37aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward    if hasattr (list, 'extend'):
38aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward        list.extend (new_list)
39aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward    else:
40aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward        list[len(list):] = new_list
41aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward
42aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward# extend ()
43aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward
44aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward
45585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Warddef get_platform ():
46585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward    """Return a string (suitable for tacking onto directory names) that
47585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward       identifies the current platform.  Under Unix, identifies both the OS
48585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward       and hardware architecture, e.g. "linux-i586", "solaris-sparc",
49585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward       "irix-mips".  For Windows and Mac OS, just returns 'sys.platform' --
50585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward       i.e. "???" or "???"."""
51585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward
52585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward    if os.name == 'posix':
536ce00b44405a478039d81a6c096620338b5d03a7Greg Ward        (OS, _, rel, _, arch) = os.uname()
546ce00b44405a478039d81a6c096620338b5d03a7Greg Ward        return "%s%c-%s" % (string.lower (OS), rel[0], string.lower (arch))
55585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward    else:
56585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward        return sys.platform
57585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward
58585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Ward# get_platform()
595091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
605091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
615091929c2cf04bfbd545835d2435e43bda6afa05Greg Warddef native_path (pathname):
625091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward    """Return 'pathname' as a name that will work on the native
635091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward       filesystem, i.e. split it on '/' and put it back together again
645091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward       using the current directory separator.  Needed because filenames in
655091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward       the setup script are always supplied in Unix style, and have to be
665091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward       converted to the local convention before we can actually use them in
6702a1a2b077e969e5fef8504cece5852bf641552dGreg Ward       the filesystem.  Raises ValueError if 'pathname' is
685091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward       absolute (starts with '/') or contains local directory separators
695091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward       (unless the local separator is '/', of course)."""
705091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
715091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward    if pathname[0] == '/':
7202a1a2b077e969e5fef8504cece5852bf641552dGreg Ward        raise ValueError, "path '%s' cannot be absolute" % pathname
735091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward    if pathname[-1] == '/':
7402a1a2b077e969e5fef8504cece5852bf641552dGreg Ward        raise ValueError, "path '%s' cannot end with '/'" % pathname
75464023fb64dd590b91cab7059dffdf0756eecbceGreg Ward    if os.sep != '/':
76464023fb64dd590b91cab7059dffdf0756eecbceGreg Ward       if os.sep in pathname:
77464023fb64dd590b91cab7059dffdf0756eecbceGreg Ward            raise ValueError, \
78464023fb64dd590b91cab7059dffdf0756eecbceGreg Ward              "path '%s' cannot contain '%c' character" % (pathname, os.sep)
79464023fb64dd590b91cab7059dffdf0756eecbceGreg Ward       else:
80464023fb64dd590b91cab7059dffdf0756eecbceGreg Ward            paths = string.split (pathname, '/')
81464023fb64dd590b91cab7059dffdf0756eecbceGreg Ward            return apply (os.path.join, paths)
825091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward    else:
835091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward        return pathname
845091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward
855091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward# native_path ()
861b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
871b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
8867f75d4bcb3630c0f5b6761fb758072cc342157eGreg Warddef change_root (new_root, pathname):
8967f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
9067f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    """Return 'pathname' with 'new_root' prepended.  If 'pathname' is
9167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    relative, this is equivalent to "os.path.join(new_root,pathname)".
9267f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    Otherwise, it requires making 'pathname' relative and then joining the
9367f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    two, which is tricky on DOS/Windows and Mac OS."""
9467f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
9567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    if not abspath (pathname):
9667f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward        return os.path.join (new_root, pathname)
9767f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
9867f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    elif os.name == 'posix':
9967f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward        return os.path.join (new_root, pathname[1:])
10067f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
10167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    elif os.name == 'nt':
10267f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward        (root_drive, root_path) = os.path.splitdrive (new_root)
10367f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward        (drive, path) = os.path.splitdrive (pathname)
10467f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward        raise RuntimeError, "I give up -- not sure how to do this on Windows"
10567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
10667f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    elif os.name == 'mac':
10767f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward        raise RuntimeError, "no clue how to do this on Mac OS"
10867f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
10967f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward    else:
11067f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward        raise DistutilsPlatformError, \
11167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward              "nothing known about platform '%s'" % os.name
11267f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
11367f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward
114e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith_environ_checked = 0
115e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smithdef check_environ ():
1161b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    """Ensure that 'os.environ' has all the environment variables we
1171b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       guarantee that users can use in config files, command-line
1181b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       options, etc.  Currently this includes:
1191b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward         HOME - user's home directory (Unix only)
1201b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward         PLAT - desription of the current platform, including hardware
1211b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward                and OS (see 'get_platform()')
1221b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    """
1231b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
124e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    global _environ_checked
125e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    if _environ_checked:
126e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith        return
127e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith
1281b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    if os.name == 'posix' and not os.environ.has_key('HOME'):
1291b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        import pwd
1301b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        os.environ['HOME'] = pwd.getpwuid (os.getuid())[5]
1311b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1321b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    if not os.environ.has_key('PLAT'):
1331b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        os.environ['PLAT'] = get_platform ()
1341b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
135e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    _environ_checked = 1
136e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith
1371b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1381b4ede5f24814dc4baa8832414093aa745c3755cGreg Warddef subst_vars (str, local_vars):
1391b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    """Perform shell/Perl-style variable substitution on 'string'.
1401b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       Every occurence of '$' followed by a name, or a name enclosed in
1411b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       braces, is considered a variable.  Every variable is substituted by
1421b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       the value found in the 'local_vars' dictionary, or in 'os.environ'
1431b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       if it's not in 'local_vars'.  'os.environ' is first checked/
1441b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       augmented to guarantee that it contains certain values: see
1451b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       '_check_environ()'.  Raise ValueError for any variables not found in
1461b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward       either 'local_vars' or 'os.environ'."""
1471b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
148e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith    check_environ ()
1491b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    def _subst (match, local_vars=local_vars):
1501b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        var_name = match.group(1)
1511b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        if local_vars.has_key (var_name):
1521b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward            return str (local_vars[var_name])
1531b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward        else:
1541b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward            return os.environ[var_name]
1551b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1561b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward    return re.sub (r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, str)
1571b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward
1581b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward# subst_vars ()
1597c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward
1607c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward
161