1"""distutils.util 2 3Miscellaneous utility functions -- anything that doesn't fit into 4one of the other *util.py modules. 5""" 6 7import os 8import re 9import string 10import sys 11from distutils.errors import DistutilsPlatformError 12 13def get_host_platform(): 14 """Return a string that identifies the current platform. This is used mainly to 15 distinguish platform-specific build directories and platform-specific built 16 distributions. Typically includes the OS name and version and the 17 architecture (as supplied by 'os.uname()'), although the exact information 18 included depends on the OS; eg. on Linux, the kernel version isn't 19 particularly important. 20 21 Examples of returned values: 22 linux-i586 23 linux-alpha (?) 24 solaris-2.6-sun4u 25 26 Windows will return one of: 27 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) 28 win32 (all others - specifically, sys.platform is returned) 29 30 For other non-POSIX platforms, currently just returns 'sys.platform'. 31 32 """ 33 if os.name == 'nt': 34 if 'amd64' in sys.version.lower(): 35 return 'win-amd64' 36 if '(arm)' in sys.version.lower(): 37 return 'win-arm32' 38 if '(arm64)' in sys.version.lower(): 39 return 'win-arm64' 40 return sys.platform 41 42 # Set for cross builds explicitly 43 if "_PYTHON_HOST_PLATFORM" in os.environ: 44 return os.environ["_PYTHON_HOST_PLATFORM"] 45 46 if os.name != "posix" or not hasattr(os, 'uname'): 47 # XXX what about the architecture? NT is Intel or Alpha, 48 # Mac OS is M68k or PPC, etc. 49 return sys.platform 50 51 # Try to distinguish various flavours of Unix 52 53 (osname, host, release, version, machine) = os.uname() 54 55 # Convert the OS name to lowercase, remove '/' characters, and translate 56 # spaces (for "Power Macintosh") 57 osname = osname.lower().replace('/', '') 58 machine = machine.replace(' ', '_') 59 machine = machine.replace('/', '-') 60 61 if osname[:5] == "linux": 62 # At least on Linux/Intel, 'machine' is the processor -- 63 # i386, etc. 64 # XXX what about Alpha, SPARC, etc? 65 return "%s-%s" % (osname, machine) 66 elif osname[:5] == "sunos": 67 if release[0] >= "5": # SunOS 5 == Solaris 2 68 osname = "solaris" 69 release = "%d.%s" % (int(release[0]) - 3, release[2:]) 70 # We can't use "platform.architecture()[0]" because a 71 # bootstrap problem. We use a dict to get an error 72 # if some suspicious happens. 73 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"} 74 machine += ".%s" % bitness[sys.maxsize] 75 # fall through to standard osname-release-machine representation 76 elif osname[:3] == "aix": 77 from _aix_support import aix_platform 78 return aix_platform() 79 elif osname[:6] == "cygwin": 80 osname = "cygwin" 81 rel_re = re.compile (r'[\d.]+', re.ASCII) 82 m = rel_re.match(release) 83 if m: 84 release = m.group() 85 elif osname[:6] == "darwin": 86 import _osx_support, sysconfig 87 osname, release, machine = _osx_support.get_platform_osx( 88 sysconfig.get_config_vars(), 89 osname, release, machine) 90 91 return "%s-%s-%s" % (osname, release, machine) 92 93def get_platform(): 94 if os.name == 'nt': 95 TARGET_TO_PLAT = { 96 'x86' : 'win32', 97 'x64' : 'win-amd64', 98 'arm' : 'win-arm32', 99 } 100 return TARGET_TO_PLAT.get(os.environ.get('VSCMD_ARG_TGT_ARCH')) or get_host_platform() 101 else: 102 return get_host_platform() 103 104 105# Needed by 'split_quoted()' 106_wordchars_re = _squote_re = _dquote_re = None 107def _init_regex(): 108 global _wordchars_re, _squote_re, _dquote_re 109 _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace) 110 _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") 111 _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') 112 113def split_quoted (s): 114 """Split a string up according to Unix shell-like rules for quotes and 115 backslashes. In short: words are delimited by spaces, as long as those 116 spaces are not escaped by a backslash, or inside a quoted string. 117 Single and double quotes are equivalent, and the quote characters can 118 be backslash-escaped. The backslash is stripped from any two-character 119 escape sequence, leaving only the escaped character. The quote 120 characters are stripped from any quoted string. Returns a list of 121 words. 122 """ 123 124 # This is a nice algorithm for splitting up a single string, since it 125 # doesn't require character-by-character examination. It was a little 126 # bit of a brain-bender to get it working right, though... 127 if _wordchars_re is None: _init_regex() 128 129 s = s.strip() 130 words = [] 131 pos = 0 132 133 while s: 134 m = _wordchars_re.match(s, pos) 135 end = m.end() 136 if end == len(s): 137 words.append(s[:end]) 138 break 139 140 if s[end] in string.whitespace: # unescaped, unquoted whitespace: now 141 words.append(s[:end]) # we definitely have a word delimiter 142 s = s[end:].lstrip() 143 pos = 0 144 145 elif s[end] == '\\': # preserve whatever is being escaped; 146 # will become part of the current word 147 s = s[:end] + s[end+1:] 148 pos = end+1 149 150 else: 151 if s[end] == "'": # slurp singly-quoted string 152 m = _squote_re.match(s, end) 153 elif s[end] == '"': # slurp doubly-quoted string 154 m = _dquote_re.match(s, end) 155 else: 156 raise RuntimeError("this can't happen (bad char '%c')" % s[end]) 157 158 if m is None: 159 raise ValueError("bad string (mismatched %s quotes?)" % s[end]) 160 161 (beg, end) = m.span() 162 s = s[:beg] + s[beg+1:end-1] + s[end:] 163 pos = m.end() - 2 164 165 if pos >= len(s): 166 words.append(s) 167 break 168 169 return words 170 171# split_quoted () 172