util.py revision 989835c9fc4e18f5b73dda9d1f6c769e78eecf77
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 152689e3ddce70e8acc5bc231a80221980d5bdfec3Greg Ward 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 3359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 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() 4459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward osname = string.lower(osname) 4559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward if osname[:5] == "linux": 4659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # At least on Linux/Intel, 'machine' is the processor -- 4759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # i386, etc. 4859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # XXX what about Alpha, SPARC, etc? 4959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward return "%s-%s" % (osname, machine) 5059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward elif osname[:5] == "sunos": 5159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward if release[0] >= "5": # SunOS 5 == Solaris 2 5259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward osname = "solaris" 5359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward release = "%d.%s" % (int(release[0]) - 3, release[2:]) 5459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # fall through to standard osname-release-machine representation 5559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward elif osname[:4] == "irix": # could be "irix64"! 5659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward return "%s-%s" % (osname, release) 57989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling elif osname[:6] == "cygwin": 58989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling rel_re = re.compile (r'[\d.]+') 59989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling m = rel_re.match(release) 60989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling if m: 61989835c9fc4e18f5b73dda9d1f6c769e78eecf77Andrew M. Kuchling release = m.group() 6259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 6359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward return "%s-%s-%s" % (osname, release, machine) 6459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 6559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward# get_platform () 665091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward 675091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward 68d8dfb4c4b8d661acee263e3feb77974ced69e97dGreg Warddef convert_path (pathname): 69b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward """Return 'pathname' as a name that will work on the native filesystem, 70b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward i.e. split it on '/' and put it back together again using the current 71b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward directory separator. Needed because filenames in the setup script are 72b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward always supplied in Unix style, and have to be converted to the local 73b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward convention before we can actually use them in the filesystem. Raises 744752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward ValueError on non-Unix-ish systems if 'pathname' either starts or 754752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward ends with a slash. 76b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward """ 777ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward if os.sep == '/': 787ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward return pathname 795091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward if pathname[0] == '/': 8002a1a2b077e969e5fef8504cece5852bf641552dGreg Ward raise ValueError, "path '%s' cannot be absolute" % pathname 815091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward if pathname[-1] == '/': 8202a1a2b077e969e5fef8504cece5852bf641552dGreg Ward raise ValueError, "path '%s' cannot end with '/'" % pathname 837ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward 847ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward paths = string.split(pathname, '/') 857ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward return apply(os.path.join, paths) 865091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward 87d8dfb4c4b8d661acee263e3feb77974ced69e97dGreg Ward# convert_path () 881b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 891b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 9067f75d4bcb3630c0f5b6761fb758072cc342157eGreg Warddef change_root (new_root, pathname): 9167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward """Return 'pathname' with 'new_root' prepended. If 'pathname' is 9267f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward relative, this is equivalent to "os.path.join(new_root,pathname)". 9367f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward Otherwise, it requires making 'pathname' relative and then joining the 944b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward two, which is tricky on DOS/Windows and Mac OS. 954b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward """ 964b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward if os.name == 'posix': 97be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward if not os.path.isabs(pathname): 98be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward return os.path.join(new_root, pathname) 994b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward else: 100be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward return os.path.join(new_root, pathname[1:]) 10167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 10267f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward elif os.name == 'nt': 103be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward (drive, path) = os.path.splitdrive(pathname) 1044b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward if path[0] == '\\': 1054b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward path = path[1:] 106be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward return os.path.join(new_root, path) 10767f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 10867f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward elif os.name == 'mac': 109f5855746fe0851e5a80b32061cb819021285ff25Greg Ward if not os.path.isabs(pathname): 110f5855746fe0851e5a80b32061cb819021285ff25Greg Ward return os.path.join(new_root, pathname) 111f5855746fe0851e5a80b32061cb819021285ff25Greg Ward else: 112f5855746fe0851e5a80b32061cb819021285ff25Greg Ward # Chop off volume name from start of path 113f5855746fe0851e5a80b32061cb819021285ff25Greg Ward elements = string.split(pathname, ":", 1) 114f5855746fe0851e5a80b32061cb819021285ff25Greg Ward pathname = ":" + elements[1] 115f5855746fe0851e5a80b32061cb819021285ff25Greg Ward return os.path.join(new_root, pathname) 11667f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 11767f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward else: 11867f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward raise DistutilsPlatformError, \ 11967f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward "nothing known about platform '%s'" % os.name 12067f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 12167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 122e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith_environ_checked = 0 123e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smithdef check_environ (): 1241b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward """Ensure that 'os.environ' has all the environment variables we 125b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward guarantee that users can use in config files, command-line options, 126b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward etc. Currently this includes: 127b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward HOME - user's home directory (Unix only) 128b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward PLAT - description of the current platform, including hardware 129b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward and OS (see 'get_platform()') 1301b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward """ 131e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith global _environ_checked 132e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith if _environ_checked: 133e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith return 134e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith 1351b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward if os.name == 'posix' and not os.environ.has_key('HOME'): 1361b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward import pwd 137be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward os.environ['HOME'] = pwd.getpwuid(os.getuid())[5] 1381b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 1391b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward if not os.environ.has_key('PLAT'): 140be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward os.environ['PLAT'] = get_platform() 1411b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 142e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith _environ_checked = 1 143e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith 1441b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 1451b4ede5f24814dc4baa8832414093aa745c3755cGreg Warddef subst_vars (str, local_vars): 146b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward """Perform shell/Perl-style variable substitution on 'string'. Every 1474752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward occurrence of '$' followed by a name is considered a variable, and 1484752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward variable is substituted by the value found in the 'local_vars' 1494752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward dictionary, or in 'os.environ' if it's not in 'local_vars'. 1504752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward 'os.environ' is first checked/augmented to guarantee that it contains 1514752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward certain values: see 'check_environ()'. Raise ValueError for any 1524752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward variables not found in either 'local_vars' or 'os.environ'. 153b8b263b92f33162d0b1bd35f44a17e5538b9713fGreg Ward """ 154be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward check_environ() 1551b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward def _subst (match, local_vars=local_vars): 1561b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward var_name = match.group(1) 157be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward if local_vars.has_key(var_name): 158be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward return str(local_vars[var_name]) 1591b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward else: 1601b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward return os.environ[var_name] 1611b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 1624752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward try: 1634752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, str) 1644752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward except KeyError, var: 1654752769d08c3ef950d31b926751d5e4d1dae294fGreg Ward raise ValueError, "invalid variable '$%s'" % var 1661b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 1671b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward# subst_vars () 1687c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward 1697c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward 170e905513be0718c5a8edafe70efc0fe0d4f290573Greg Warddef grok_environment_error (exc, prefix="error: "): 171e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward """Generate a useful error message from an EnvironmentError (IOError or 172e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward OSError) exception object. Handles Python 1.5.1 and 1.5.2 styles, and 173e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward does what it can to deal with exception objects that don't have a 174e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward filename (which happens when the error is due to a two-file operation, 175e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward such as 'rename()' or 'link()'. Returns the error message as a string 176e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward prefixed with 'prefix'. 177e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward """ 178e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward # check for Python 1.5.2-style {IO,OS}Error exception objects 179be86bdea734bc53b25698ff5961183cbb5352ffdGreg Ward if hasattr(exc, 'filename') and hasattr(exc, 'strerror'): 180e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward if exc.filename: 181e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward error = prefix + "%s: %s" % (exc.filename, exc.strerror) 182e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward else: 183e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward # two-argument functions in posix module don't 184e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward # include the filename in the exception object! 185e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward error = prefix + "%s" % exc.strerror 186e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward else: 187e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward error = prefix + str(exc[-1]) 188e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward 189e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward return error 1906a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 1916a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 1926a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward# Needed by 'split_quoted()' 1932b042ded19bc7efa43551da297c29dc142b7d73cGreg Ward_wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace) 1946a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward_squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") 1956a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward_dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') 1966a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 1976a2a3dbec59f267e05c0c507457dfd234263237bGreg Warddef split_quoted (s): 1986a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward """Split a string up according to Unix shell-like rules for quotes and 1996a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward backslashes. In short: words are delimited by spaces, as long as those 2006a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward spaces are not escaped by a backslash, or inside a quoted string. 2016a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward Single and double quotes are equivalent, and the quote characters can 2026a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward be backslash-escaped. The backslash is stripped from any two-character 2036a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward escape sequence, leaving only the escaped character. The quote 2046a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward characters are stripped from any quoted string. Returns a list of 2056a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words. 2066a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward """ 2076a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2086a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward # This is a nice algorithm for splitting up a single string, since it 2096a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward # doesn't require character-by-character examination. It was a little 2106a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward # bit of a brain-bender to get it working right, though... 2116a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2126a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward s = string.strip(s) 2136a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words = [] 2146a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward pos = 0 2156a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2166a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward while s: 2176a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward m = _wordchars_re.match(s, pos) 2186a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward end = m.end() 2196a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward if end == len(s): 2206a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words.append(s[:end]) 2216a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward break 2226a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2232b042ded19bc7efa43551da297c29dc142b7d73cGreg Ward if s[end] in string.whitespace: # unescaped, unquoted whitespace: now 2246a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words.append(s[:end]) # we definitely have a word delimiter 2256a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward s = string.lstrip(s[end:]) 2266a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward pos = 0 2276a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2286a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward elif s[end] == '\\': # preserve whatever is being escaped; 2296a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward # will become part of the current word 2306a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward s = s[:end] + s[end+1:] 2316a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward pos = end+1 2326a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2336a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward else: 2346a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward if s[end] == "'": # slurp singly-quoted string 2356a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward m = _squote_re.match(s, end) 2366a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward elif s[end] == '"': # slurp doubly-quoted string 2376a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward m = _dquote_re.match(s, end) 2386a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward else: 2396a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward raise RuntimeError, \ 2406a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward "this can't happen (bad char '%c')" % s[end] 2416a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2426a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward if m is None: 2436a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward raise ValueError, \ 2446a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward "bad string (mismatched %s quotes?)" % s[end] 2456a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2466a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward (beg, end) = m.span() 2476a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward s = s[:beg] + s[beg+1:end-1] + s[end:] 2486a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward pos = m.end() - 2 2496a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2506a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward if pos >= len(s): 2516a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words.append(s) 2526a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward break 2536a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2546a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward return words 2556a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2566a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward# split_quoted () 2571c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2581c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2591c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Warddef execute (func, args, msg=None, verbose=0, dry_run=0): 2601c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward """Perform some action that affects the outside world (eg. by writing 2611c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward to the filesystem). Such actions are special because they are disabled 2621c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward by the 'dry_run' flag, and announce themselves if 'verbose' is true. 2631c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward This method takes care of all that bureaucracy for you; all you have to 2641c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward do is supply the function to call and an argument tuple for it (to 2651c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward embody the "external action" being performed), and an optional message 2661c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward to print. 2671c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward """ 2681c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward # Generate a message if we weren't passed one 2691c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward if msg is None: 2701c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward msg = "%s%s" % (func.__name__, `args`) 2711c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward if msg[-2:] == ',)': # correct for singleton tuple 2721c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward msg = msg[0:-2] + ')' 2731c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2741c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward # Print it if verbosity level is high enough 2751c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward if verbose: 2761c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward print msg 2771c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2781c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward # And do it, as long as we're not in dry-run mode 2791c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward if not dry_run: 2801c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward apply(func, args) 2811c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2821c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward# execute() 283817dc098efd0c2cba674cee32950fc5626e12881Greg Ward 284817dc098efd0c2cba674cee32950fc5626e12881Greg Ward 285817dc098efd0c2cba674cee32950fc5626e12881Greg Warddef strtobool (val): 286817dc098efd0c2cba674cee32950fc5626e12881Greg Ward """Convert a string representation of truth to true (1) or false (0). 287817dc098efd0c2cba674cee32950fc5626e12881Greg Ward True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values 288817dc098efd0c2cba674cee32950fc5626e12881Greg Ward are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if 289817dc098efd0c2cba674cee32950fc5626e12881Greg Ward 'val' is anything else. 290817dc098efd0c2cba674cee32950fc5626e12881Greg Ward """ 291817dc098efd0c2cba674cee32950fc5626e12881Greg Ward val = string.lower(val) 292817dc098efd0c2cba674cee32950fc5626e12881Greg Ward if val in ('y', 'yes', 't', 'true', 'on', '1'): 293817dc098efd0c2cba674cee32950fc5626e12881Greg Ward return 1 294817dc098efd0c2cba674cee32950fc5626e12881Greg Ward elif val in ('n', 'no', 'f', 'false', 'off', '0'): 295817dc098efd0c2cba674cee32950fc5626e12881Greg Ward return 0 296817dc098efd0c2cba674cee32950fc5626e12881Greg Ward else: 297817dc098efd0c2cba674cee32950fc5626e12881Greg Ward raise ValueError, "invalid truth value %s" % `val` 2981297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 2991297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3001297b5ce67642dba35615121825fb1621e28e6b8Greg Warddef byte_compile (py_files, 3011297b5ce67642dba35615121825fb1621e28e6b8Greg Ward optimize=0, force=0, 3021297b5ce67642dba35615121825fb1621e28e6b8Greg Ward prefix=None, base_dir=None, 3031297b5ce67642dba35615121825fb1621e28e6b8Greg Ward verbose=1, dry_run=0, 3041297b5ce67642dba35615121825fb1621e28e6b8Greg Ward direct=None): 305f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward """Byte-compile a collection of Python source files to either .pyc 306f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward or .pyo files in the same directory. 'py_files' is a list of files 307f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward to compile; any files that don't end in ".py" are silently skipped. 308f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward 'optimize' must be one of the following: 3091297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 0 - don't optimize (generate .pyc) 3101297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 1 - normal optimization (like "python -O") 3111297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 2 - extra optimization (like "python -OO") 3121297b5ce67642dba35615121825fb1621e28e6b8Greg Ward If 'force' is true, all files are recompiled regardless of 3131297b5ce67642dba35615121825fb1621e28e6b8Greg Ward timestamps. 3141297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3151297b5ce67642dba35615121825fb1621e28e6b8Greg Ward The source filename encoded in each bytecode file defaults to the 3161297b5ce67642dba35615121825fb1621e28e6b8Greg Ward filenames listed in 'py_files'; you can modify these with 'prefix' and 3171297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 'basedir'. 'prefix' is a string that will be stripped off of each 3181297b5ce67642dba35615121825fb1621e28e6b8Greg Ward source filename, and 'base_dir' is a directory name that will be 3191297b5ce67642dba35615121825fb1621e28e6b8Greg Ward prepended (after 'prefix' is stripped). You can supply either or both 3201297b5ce67642dba35615121825fb1621e28e6b8Greg Ward (or neither) of 'prefix' and 'base_dir', as you wish. 3211297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3221297b5ce67642dba35615121825fb1621e28e6b8Greg Ward If 'verbose' is true, prints out a report of each file. If 'dry_run' 3231297b5ce67642dba35615121825fb1621e28e6b8Greg Ward is true, doesn't actually do anything that would affect the filesystem. 3241297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3251297b5ce67642dba35615121825fb1621e28e6b8Greg Ward Byte-compilation is either done directly in this interpreter process 3261297b5ce67642dba35615121825fb1621e28e6b8Greg Ward with the standard py_compile module, or indirectly by writing a 3271297b5ce67642dba35615121825fb1621e28e6b8Greg Ward temporary script and executing it. Normally, you should let 3281297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 'byte_compile()' figure out to use direct compilation or not (see 3291297b5ce67642dba35615121825fb1621e28e6b8Greg Ward the source for details). The 'direct' flag is used by the script 3301297b5ce67642dba35615121825fb1621e28e6b8Greg Ward generated in indirect mode; unless you know what you're doing, leave 3311297b5ce67642dba35615121825fb1621e28e6b8Greg Ward it set to None. 3321297b5ce67642dba35615121825fb1621e28e6b8Greg Ward """ 3331297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3341297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # First, if the caller didn't force us into direct or indirect mode, 3351297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # figure out which mode we should be in. We take a conservative 3361297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # approach: choose direct mode *only* if the current interpreter is 3371297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # in debug mode and optimize is 0. If we're not in debug mode (-O 3381297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # or -OO), we don't know which level of optimization this 3391297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # interpreter is running with, so we can't do direct 3401297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # byte-compilation and be certain that it's the right thing. Thus, 3411297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # always compile indirectly if the current interpreter is in either 3421297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # optimize mode, or if either optimization level was requested by 3431297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # the caller. 3441297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if direct is None: 3451297b5ce67642dba35615121825fb1621e28e6b8Greg Ward direct = (__debug__ and optimize == 0) 3461297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3471297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # "Indirect" byte-compilation: write a temporary script and then 3481297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # run it with the appropriate flags. 3491297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if not direct: 3501297b5ce67642dba35615121825fb1621e28e6b8Greg Ward from tempfile import mktemp 3511297b5ce67642dba35615121825fb1621e28e6b8Greg Ward script_name = mktemp(".py") 3521297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if verbose: 3531297b5ce67642dba35615121825fb1621e28e6b8Greg Ward print "writing byte-compilation script '%s'" % script_name 3541297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if not dry_run: 3551297b5ce67642dba35615121825fb1621e28e6b8Greg Ward script = open(script_name, "w") 3561297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3571297b5ce67642dba35615121825fb1621e28e6b8Greg Ward script.write("""\ 3581297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfrom distutils.util import byte_compile 3591297b5ce67642dba35615121825fb1621e28e6b8Greg Wardfiles = [ 3601297b5ce67642dba35615121825fb1621e28e6b8Greg Ward""") 3619216cfe7ba0257f10790f919e50283114a3476ddGreg Ward 3629216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # XXX would be nice to write absolute filenames, just for 3639216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # safety's sake (script should be more robust in the face of 3649216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # chdir'ing before running it). But this requires abspath'ing 3659216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # 'prefix' as well, and that breaks the hack in build_lib's 3669216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # 'byte_compile()' method that carefully tacks on a trailing 3679216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # slash (os.sep really) to make sure the prefix here is "just 3689216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # right". This whole prefix business is rather delicate -- the 3699216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # problem is that it's really a directory, but I'm treating it 3709216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # as a dumb string, so trailing slashes and so forth matter. 3719216cfe7ba0257f10790f919e50283114a3476ddGreg Ward 3729216cfe7ba0257f10790f919e50283114a3476ddGreg Ward #py_files = map(os.path.abspath, py_files) 3739216cfe7ba0257f10790f919e50283114a3476ddGreg Ward #if prefix: 3749216cfe7ba0257f10790f919e50283114a3476ddGreg Ward # prefix = os.path.abspath(prefix) 3759216cfe7ba0257f10790f919e50283114a3476ddGreg Ward 3761297b5ce67642dba35615121825fb1621e28e6b8Greg Ward script.write(string.join(map(repr, py_files), ",\n") + "]\n") 3771297b5ce67642dba35615121825fb1621e28e6b8Greg Ward script.write(""" 3781297b5ce67642dba35615121825fb1621e28e6b8Greg Wardbyte_compile(files, optimize=%s, force=%s, 3791297b5ce67642dba35615121825fb1621e28e6b8Greg Ward prefix=%s, base_dir=%s, 3801297b5ce67642dba35615121825fb1621e28e6b8Greg Ward verbose=%s, dry_run=0, 3811297b5ce67642dba35615121825fb1621e28e6b8Greg Ward direct=1) 3821297b5ce67642dba35615121825fb1621e28e6b8Greg Ward""" % (`optimize`, `force`, `prefix`, `base_dir`, `verbose`)) 3831297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3841297b5ce67642dba35615121825fb1621e28e6b8Greg Ward script.close() 3851297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3861297b5ce67642dba35615121825fb1621e28e6b8Greg Ward cmd = [sys.executable, script_name] 3871297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if optimize == 1: 3881297b5ce67642dba35615121825fb1621e28e6b8Greg Ward cmd.insert(1, "-O") 3891297b5ce67642dba35615121825fb1621e28e6b8Greg Ward elif optimize == 2: 3901297b5ce67642dba35615121825fb1621e28e6b8Greg Ward cmd.insert(1, "-OO") 3911297b5ce67642dba35615121825fb1621e28e6b8Greg Ward spawn(cmd, verbose=verbose, dry_run=dry_run) 3929216cfe7ba0257f10790f919e50283114a3476ddGreg Ward execute(os.remove, (script_name,), "removing %s" % script_name, 3939216cfe7ba0257f10790f919e50283114a3476ddGreg Ward verbose=verbose, dry_run=dry_run) 3941297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 3951297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # "Direct" byte-compilation: use the py_compile module to compile 3961297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # right here, right now. Note that the script generated in indirect 3971297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # mode simply calls 'byte_compile()' in direct mode, a weird sort of 3981297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # cross-process recursion. Hey, it works! 3991297b5ce67642dba35615121825fb1621e28e6b8Greg Ward else: 4001297b5ce67642dba35615121825fb1621e28e6b8Greg Ward from py_compile import compile 4011297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 4021297b5ce67642dba35615121825fb1621e28e6b8Greg Ward for file in py_files: 4031297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if file[-3:] != ".py": 404f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward # This lets us be lazy and not filter filenames in 405f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward # the "install_lib" command. 406f217e2124a9b57dc13513ea4f9e430413135269eGreg Ward continue 4071297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 4081297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # Terminology from the py_compile module: 4091297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # cfile - byte-compiled file 4101297b5ce67642dba35615121825fb1621e28e6b8Greg Ward # dfile - purported source filename (same as 'file' by default) 4111297b5ce67642dba35615121825fb1621e28e6b8Greg Ward cfile = file + (__debug__ and "c" or "o") 4121297b5ce67642dba35615121825fb1621e28e6b8Greg Ward dfile = file 4131297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if prefix: 4141297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if file[:len(prefix)] != prefix: 4151297b5ce67642dba35615121825fb1621e28e6b8Greg Ward raise ValueError, \ 4161297b5ce67642dba35615121825fb1621e28e6b8Greg Ward ("invalid prefix: filename %s doesn't start with %s" 4171297b5ce67642dba35615121825fb1621e28e6b8Greg Ward % (`file`, `prefix`)) 4181297b5ce67642dba35615121825fb1621e28e6b8Greg Ward dfile = dfile[len(prefix):] 4191297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if base_dir: 4201297b5ce67642dba35615121825fb1621e28e6b8Greg Ward dfile = os.path.join(base_dir, dfile) 4211297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 4221297b5ce67642dba35615121825fb1621e28e6b8Greg Ward cfile_base = os.path.basename(cfile) 4231297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if direct: 4241297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if force or newer(file, cfile): 4251297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if verbose: 4261297b5ce67642dba35615121825fb1621e28e6b8Greg Ward print "byte-compiling %s to %s" % (file, cfile_base) 4271297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if not dry_run: 4281297b5ce67642dba35615121825fb1621e28e6b8Greg Ward compile(file, cfile, dfile) 4291297b5ce67642dba35615121825fb1621e28e6b8Greg Ward else: 4301297b5ce67642dba35615121825fb1621e28e6b8Greg Ward if verbose: 4311297b5ce67642dba35615121825fb1621e28e6b8Greg Ward print "skipping byte-compilation of %s to %s" % \ 4321297b5ce67642dba35615121825fb1621e28e6b8Greg Ward (file, cfile_base) 4331297b5ce67642dba35615121825fb1621e28e6b8Greg Ward 4341297b5ce67642dba35615121825fb1621e28e6b8Greg Ward# byte_compile () 435