util.py revision 7ec053544cf4849a138e70329ffeec1d6ab93e62
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 14aa458bc46500a2b135cad66a4fd66cac69b8be51Greg Ward 15585df89f60ceb2e0a5b690f12f19c14093faa6fcGreg Warddef get_platform (): 1659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward """Return a string that identifies the current platform. This is used 1759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward mainly to distinguish platform-specific build directories and 1859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward platform-specific built distributions. Typically includes the OS name 1959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward and version and the architecture (as supplied by 'os.uname()'), 2059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward although the exact information included depends on the OS; eg. for IRIX 2159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward the architecture isn't particularly important (IRIX only runs on SGI 2259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward hardware), but for Linux the kernel version isn't particularly 2359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward important. 2459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 2559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward Examples of returned values: 2659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward linux-i586 2759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward linux-alpha (?) 2859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward solaris-2.6-sun4u 2959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward irix-5.3 3059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward irix64-6.2 3159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 3259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward For non-POSIX platforms, currently just returns 'sys.platform'. 33b75c485f0bc6394f616d4a0bc746e613fd7b1021Greg Ward """ 3459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward if os.name != "posix": 3559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # XXX what about the architecture? NT is Intel or Alpha, 3659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # Mac OS is M68k or PPC, etc. 3759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward return sys.platform 3859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 3959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # Try to distinguish various flavours of Unix 4059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 4159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward (osname, host, release, version, machine) = os.uname() 4259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward osname = string.lower(osname) 4359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward if osname[:5] == "linux": 4459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # At least on Linux/Intel, 'machine' is the processor -- 4559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # i386, etc. 4659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # XXX what about Alpha, SPARC, etc? 4759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward return "%s-%s" % (osname, machine) 4859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward elif osname[:5] == "sunos": 4959399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward if release[0] >= "5": # SunOS 5 == Solaris 2 5059399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward osname = "solaris" 5159399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward release = "%d.%s" % (int(release[0]) - 3, release[2:]) 5259399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward # fall through to standard osname-release-machine representation 5359399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward elif osname[:4] == "irix": # could be "irix64"! 5459399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward return "%s-%s" % (osname, release) 5559399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 5659399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward return "%s-%s-%s" % (osname, release, machine) 5759399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward 5859399bb303a51e781ab7943088fa1c4db1d41dcbGreg Ward# get_platform () 595091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward 605091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward 61d8dfb4c4b8d661acee263e3feb77974ced69e97dGreg Warddef convert_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 717ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward if os.sep == '/': 727ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward return pathname 735091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward if pathname[0] == '/': 7402a1a2b077e969e5fef8504cece5852bf641552dGreg Ward raise ValueError, "path '%s' cannot be absolute" % pathname 755091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward if pathname[-1] == '/': 7602a1a2b077e969e5fef8504cece5852bf641552dGreg Ward raise ValueError, "path '%s' cannot end with '/'" % pathname 777ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward 787ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward paths = string.split(pathname, '/') 797ec053544cf4849a138e70329ffeec1d6ab93e62Greg Ward return apply(os.path.join, paths) 805091929c2cf04bfbd545835d2435e43bda6afa05Greg Ward 81d8dfb4c4b8d661acee263e3feb77974ced69e97dGreg Ward# convert_path () 821b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 831b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 8467f75d4bcb3630c0f5b6761fb758072cc342157eGreg Warddef change_root (new_root, pathname): 8567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward """Return 'pathname' with 'new_root' prepended. If 'pathname' is 8667f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward relative, this is equivalent to "os.path.join(new_root,pathname)". 8767f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward Otherwise, it requires making 'pathname' relative and then joining the 884b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward two, which is tricky on DOS/Windows and Mac OS. 894b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward """ 904b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward if os.name == 'posix': 914b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward if not os.path.isabs (pathname): 924b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward return os.path.join (new_root, pathname) 934b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward else: 944b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward return os.path.join (new_root, pathname[1:]) 9567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 9667f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward elif os.name == 'nt': 9767f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward (drive, path) = os.path.splitdrive (pathname) 984b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward if path[0] == '\\': 994b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward path = path[1:] 1004b46ef9a4f35c50eed2e0993058be0cfe71e0b3bGreg Ward return os.path.join (new_root, path) 10167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 10267f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward elif os.name == 'mac': 103f5855746fe0851e5a80b32061cb819021285ff25Greg Ward if not os.path.isabs(pathname): 104f5855746fe0851e5a80b32061cb819021285ff25Greg Ward return os.path.join(new_root, pathname) 105f5855746fe0851e5a80b32061cb819021285ff25Greg Ward else: 106f5855746fe0851e5a80b32061cb819021285ff25Greg Ward # Chop off volume name from start of path 107f5855746fe0851e5a80b32061cb819021285ff25Greg Ward elements = string.split(pathname, ":", 1) 108f5855746fe0851e5a80b32061cb819021285ff25Greg Ward pathname = ":" + elements[1] 109f5855746fe0851e5a80b32061cb819021285ff25Greg Ward return os.path.join(new_root, pathname) 11067f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 11167f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward else: 11267f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward raise DistutilsPlatformError, \ 11367f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward "nothing known about platform '%s'" % os.name 11467f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 11567f75d4bcb3630c0f5b6761fb758072cc342157eGreg Ward 116e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith_environ_checked = 0 117e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smithdef check_environ (): 1181b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward """Ensure that 'os.environ' has all the environment variables we 1191b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward guarantee that users can use in config files, command-line 1201b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward options, etc. Currently this includes: 1211b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward HOME - user's home directory (Unix only) 122612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward PLAT - description of the current platform, including hardware 1231b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward and OS (see 'get_platform()') 1241b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward """ 1251b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 126e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith global _environ_checked 127e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith if _environ_checked: 128e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith return 129e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith 1301b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward if os.name == 'posix' and not os.environ.has_key('HOME'): 1311b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward import pwd 1321b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward os.environ['HOME'] = pwd.getpwuid (os.getuid())[5] 1331b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 1341b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward if not os.environ.has_key('PLAT'): 1351b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward os.environ['PLAT'] = get_platform () 1361b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 137e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith _environ_checked = 1 138e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith 1391b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 1401b4ede5f24814dc4baa8832414093aa745c3755cGreg Warddef subst_vars (str, local_vars): 1411b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward """Perform shell/Perl-style variable substitution on 'string'. 142612eb9f58fe38f33484f36bcba97a4b3d8e090a9Greg Ward Every occurrence of '$' followed by a name, or a name enclosed in 1431b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward braces, is considered a variable. Every variable is substituted by 1441b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward the value found in the 'local_vars' dictionary, or in 'os.environ' 1451b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward if it's not in 'local_vars'. 'os.environ' is first checked/ 1461b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward augmented to guarantee that it contains certain values: see 1471b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward '_check_environ()'. Raise ValueError for any variables not found in 1481b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward either 'local_vars' or 'os.environ'.""" 1491b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 150e7e35ac1c2e3c6b6a0836931b5c678d6af17129cGregory P. Smith check_environ () 1511b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward def _subst (match, local_vars=local_vars): 1521b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward var_name = match.group(1) 1531b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward if local_vars.has_key (var_name): 1541b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward return str (local_vars[var_name]) 1551b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward else: 1561b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward return os.environ[var_name] 1571b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 1581b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward return re.sub (r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, str) 1591b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward 1601b4ede5f24814dc4baa8832414093aa745c3755cGreg Ward# subst_vars () 1617c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward 1627c1a6d477771955e3773849ef636fceda81bb3d5Greg Ward 163e905513be0718c5a8edafe70efc0fe0d4f290573Greg Warddef grok_environment_error (exc, prefix="error: "): 164e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward """Generate a useful error message from an EnvironmentError (IOError or 165e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward OSError) exception object. Handles Python 1.5.1 and 1.5.2 styles, and 166e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward does what it can to deal with exception objects that don't have a 167e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward filename (which happens when the error is due to a two-file operation, 168e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward such as 'rename()' or 'link()'. Returns the error message as a string 169e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward prefixed with 'prefix'. 170e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward """ 171e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward # check for Python 1.5.2-style {IO,OS}Error exception objects 172e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward if hasattr (exc, 'filename') and hasattr (exc, 'strerror'): 173e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward if exc.filename: 174e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward error = prefix + "%s: %s" % (exc.filename, exc.strerror) 175e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward else: 176e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward # two-argument functions in posix module don't 177e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward # include the filename in the exception object! 178e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward error = prefix + "%s" % exc.strerror 179e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward else: 180e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward error = prefix + str(exc[-1]) 181e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward 182e905513be0718c5a8edafe70efc0fe0d4f290573Greg Ward return error 1836a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 1846a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 1856a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward# Needed by 'split_quoted()' 1862b042ded19bc7efa43551da297c29dc142b7d73cGreg Ward_wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace) 1876a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward_squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") 1886a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward_dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') 1896a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 1906a2a3dbec59f267e05c0c507457dfd234263237bGreg Warddef split_quoted (s): 1916a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward """Split a string up according to Unix shell-like rules for quotes and 1926a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward backslashes. In short: words are delimited by spaces, as long as those 1936a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward spaces are not escaped by a backslash, or inside a quoted string. 1946a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward Single and double quotes are equivalent, and the quote characters can 1956a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward be backslash-escaped. The backslash is stripped from any two-character 1966a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward escape sequence, leaving only the escaped character. The quote 1976a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward characters are stripped from any quoted string. Returns a list of 1986a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words. 1996a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward """ 2006a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2016a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward # This is a nice algorithm for splitting up a single string, since it 2026a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward # doesn't require character-by-character examination. It was a little 2036a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward # bit of a brain-bender to get it working right, though... 2046a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2056a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward s = string.strip(s) 2066a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words = [] 2076a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward pos = 0 2086a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2096a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward while s: 2106a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward m = _wordchars_re.match(s, pos) 2116a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward end = m.end() 2126a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward if end == len(s): 2136a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words.append(s[:end]) 2146a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward break 2156a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2162b042ded19bc7efa43551da297c29dc142b7d73cGreg Ward if s[end] in string.whitespace: # unescaped, unquoted whitespace: now 2176a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words.append(s[:end]) # we definitely have a word delimiter 2186a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward s = string.lstrip(s[end:]) 2196a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward pos = 0 2206a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2216a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward elif s[end] == '\\': # preserve whatever is being escaped; 2226a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward # will become part of the current word 2236a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward s = s[:end] + s[end+1:] 2246a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward pos = end+1 2256a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2266a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward else: 2276a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward if s[end] == "'": # slurp singly-quoted string 2286a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward m = _squote_re.match(s, end) 2296a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward elif s[end] == '"': # slurp doubly-quoted string 2306a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward m = _dquote_re.match(s, end) 2316a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward else: 2326a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward raise RuntimeError, \ 2336a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward "this can't happen (bad char '%c')" % s[end] 2346a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2356a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward if m is None: 2366a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward raise ValueError, \ 2376a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward "bad string (mismatched %s quotes?)" % s[end] 2386a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2396a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward (beg, end) = m.span() 2406a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward s = s[:beg] + s[beg+1:end-1] + s[end:] 2416a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward pos = m.end() - 2 2426a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2436a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward if pos >= len(s): 2446a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward words.append(s) 2456a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward break 2466a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2476a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward return words 2486a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward 2496a2a3dbec59f267e05c0c507457dfd234263237bGreg Ward# split_quoted () 2501c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2511c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2521c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Warddef execute (func, args, msg=None, verbose=0, dry_run=0): 2531c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward """Perform some action that affects the outside world (eg. by writing 2541c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward to the filesystem). Such actions are special because they are disabled 2551c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward by the 'dry_run' flag, and announce themselves if 'verbose' is true. 2561c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward This method takes care of all that bureaucracy for you; all you have to 2571c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward do is supply the function to call and an argument tuple for it (to 2581c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward embody the "external action" being performed), and an optional message 2591c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward to print. 2601c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward """ 2611c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward # Generate a message if we weren't passed one 2621c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward if msg is None: 2631c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward msg = "%s%s" % (func.__name__, `args`) 2641c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward if msg[-2:] == ',)': # correct for singleton tuple 2651c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward msg = msg[0:-2] + ')' 2661c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2671c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward # Print it if verbosity level is high enough 2681c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward if verbose: 2691c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward print msg 2701c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2711c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward # And do it, as long as we're not in dry-run mode 2721c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward if not dry_run: 2731c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward apply(func, args) 2741c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward 2751c16ac360a3fc63bfb1008c3a935907fe9064f26Greg Ward# execute() 276