• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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