[388] | 1 | """Provide access to Python's configuration information.
|
---|
| 2 |
|
---|
| 3 | """
|
---|
| 4 | import sys
|
---|
| 5 | import os
|
---|
| 6 | from os.path import pardir, realpath
|
---|
| 7 |
|
---|
| 8 | _INSTALL_SCHEMES = {
|
---|
| 9 | 'posix_prefix': {
|
---|
| 10 | 'stdlib': '{base}/lib/python{py_version_short}',
|
---|
| 11 | 'platstdlib': '{platbase}/lib/python{py_version_short}',
|
---|
| 12 | 'purelib': '{base}/lib/python{py_version_short}/site-packages',
|
---|
| 13 | 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
|
---|
| 14 | 'include': '{base}/include/python{py_version_short}',
|
---|
| 15 | 'platinclude': '{platbase}/include/python{py_version_short}',
|
---|
| 16 | 'scripts': '{base}/bin',
|
---|
| 17 | 'data': '{base}',
|
---|
| 18 | },
|
---|
| 19 | 'posix_home': {
|
---|
| 20 | 'stdlib': '{base}/lib/python',
|
---|
| 21 | 'platstdlib': '{base}/lib/python',
|
---|
| 22 | 'purelib': '{base}/lib/python',
|
---|
| 23 | 'platlib': '{base}/lib/python',
|
---|
| 24 | 'include': '{base}/include/python',
|
---|
| 25 | 'platinclude': '{base}/include/python',
|
---|
| 26 | 'scripts': '{base}/bin',
|
---|
| 27 | 'data' : '{base}',
|
---|
| 28 | },
|
---|
| 29 | 'nt': {
|
---|
| 30 | 'stdlib': '{base}/Lib',
|
---|
| 31 | 'platstdlib': '{base}/Lib',
|
---|
| 32 | 'purelib': '{base}/Lib/site-packages',
|
---|
| 33 | 'platlib': '{base}/Lib/site-packages',
|
---|
| 34 | 'include': '{base}/Include',
|
---|
| 35 | 'platinclude': '{base}/Include',
|
---|
| 36 | 'scripts': '{base}/Scripts',
|
---|
| 37 | 'data' : '{base}',
|
---|
| 38 | },
|
---|
| 39 | 'os2': {
|
---|
[394] | 40 | 'stdlib': '{base}/lib/python{py_version_short}',
|
---|
| 41 | 'platstdlib': '{platbase}/lib/python{py_version_short}',
|
---|
| 42 | 'purelib': '{base}/lib/python{py_version_short}/site-packages',
|
---|
| 43 | 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
|
---|
| 44 | 'include': '{base}/include/python{py_version_short}',
|
---|
| 45 | 'platinclude': '{platbase}/include/python{py_version_short}',
|
---|
| 46 | 'scripts': '{base}/bin',
|
---|
| 47 | 'data': '{base}',
|
---|
[388] | 48 | },
|
---|
[394] | 49 | 'os2_user': {
|
---|
[388] | 50 | 'stdlib': '{userbase}/lib/python{py_version_short}',
|
---|
| 51 | 'platstdlib': '{userbase}/lib/python{py_version_short}',
|
---|
| 52 | 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
|
---|
| 53 | 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
|
---|
| 54 | 'include': '{userbase}/include/python{py_version_short}',
|
---|
| 55 | 'scripts': '{userbase}/bin',
|
---|
| 56 | 'data' : '{userbase}',
|
---|
| 57 | },
|
---|
| 58 | 'nt_user': {
|
---|
| 59 | 'stdlib': '{userbase}/Python{py_version_nodot}',
|
---|
| 60 | 'platstdlib': '{userbase}/Python{py_version_nodot}',
|
---|
| 61 | 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
|
---|
| 62 | 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
|
---|
| 63 | 'include': '{userbase}/Python{py_version_nodot}/Include',
|
---|
| 64 | 'scripts': '{userbase}/Scripts',
|
---|
| 65 | 'data' : '{userbase}',
|
---|
| 66 | },
|
---|
| 67 | 'posix_user': {
|
---|
| 68 | 'stdlib': '{userbase}/lib/python{py_version_short}',
|
---|
| 69 | 'platstdlib': '{userbase}/lib/python{py_version_short}',
|
---|
| 70 | 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
|
---|
| 71 | 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
|
---|
| 72 | 'include': '{userbase}/include/python{py_version_short}',
|
---|
| 73 | 'scripts': '{userbase}/bin',
|
---|
| 74 | 'data' : '{userbase}',
|
---|
| 75 | },
|
---|
| 76 | 'osx_framework_user': {
|
---|
| 77 | 'stdlib': '{userbase}/lib/python',
|
---|
| 78 | 'platstdlib': '{userbase}/lib/python',
|
---|
| 79 | 'purelib': '{userbase}/lib/python/site-packages',
|
---|
| 80 | 'platlib': '{userbase}/lib/python/site-packages',
|
---|
| 81 | 'include': '{userbase}/include',
|
---|
| 82 | 'scripts': '{userbase}/bin',
|
---|
| 83 | 'data' : '{userbase}',
|
---|
| 84 | },
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 | _SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
|
---|
| 88 | 'scripts', 'data')
|
---|
| 89 | _PY_VERSION = sys.version.split()[0]
|
---|
| 90 | _PY_VERSION_SHORT = sys.version[:3]
|
---|
| 91 | _PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
|
---|
| 92 | _PREFIX = os.path.normpath(sys.prefix)
|
---|
| 93 | _EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
|
---|
| 94 | _CONFIG_VARS = None
|
---|
| 95 | _USER_BASE = None
|
---|
| 96 |
|
---|
| 97 | def _safe_realpath(path):
|
---|
| 98 | try:
|
---|
| 99 | return realpath(path)
|
---|
| 100 | except OSError:
|
---|
| 101 | return path
|
---|
| 102 |
|
---|
| 103 | if sys.executable:
|
---|
| 104 | _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
|
---|
| 105 | else:
|
---|
| 106 | # sys.executable can be empty if argv[0] has been changed and Python is
|
---|
| 107 | # unable to retrieve the real program name
|
---|
| 108 | _PROJECT_BASE = _safe_realpath(os.getcwd())
|
---|
| 109 |
|
---|
| 110 | if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
|
---|
| 111 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
|
---|
| 112 | # PC/VS7.1
|
---|
| 113 | if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
|
---|
| 114 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
|
---|
| 115 | # PC/AMD64
|
---|
| 116 | if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
|
---|
| 117 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
|
---|
| 118 |
|
---|
| 119 | # set for cross builds
|
---|
| 120 | if "_PYTHON_PROJECT_BASE" in os.environ:
|
---|
| 121 | # the build directory for posix builds
|
---|
| 122 | _PROJECT_BASE = os.path.normpath(os.path.abspath("."))
|
---|
| 123 | def is_python_build():
|
---|
| 124 | for fn in ("Setup.dist", "Setup.local"):
|
---|
| 125 | if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
|
---|
| 126 | return True
|
---|
| 127 | return False
|
---|
| 128 |
|
---|
| 129 | _PYTHON_BUILD = is_python_build()
|
---|
| 130 |
|
---|
| 131 | if _PYTHON_BUILD:
|
---|
| 132 | for scheme in ('posix_prefix', 'posix_home'):
|
---|
| 133 | _INSTALL_SCHEMES[scheme]['include'] = '{projectbase}/Include'
|
---|
| 134 | _INSTALL_SCHEMES[scheme]['platinclude'] = '{srcdir}'
|
---|
| 135 |
|
---|
| 136 | def _subst_vars(s, local_vars):
|
---|
| 137 | try:
|
---|
| 138 | return s.format(**local_vars)
|
---|
| 139 | except KeyError:
|
---|
| 140 | try:
|
---|
| 141 | return s.format(**os.environ)
|
---|
| 142 | except KeyError, var:
|
---|
| 143 | raise AttributeError('{%s}' % var)
|
---|
| 144 |
|
---|
| 145 | def _extend_dict(target_dict, other_dict):
|
---|
| 146 | target_keys = target_dict.keys()
|
---|
| 147 | for key, value in other_dict.items():
|
---|
| 148 | if key in target_keys:
|
---|
| 149 | continue
|
---|
| 150 | target_dict[key] = value
|
---|
| 151 |
|
---|
| 152 | def _expand_vars(scheme, vars):
|
---|
| 153 | res = {}
|
---|
| 154 | if vars is None:
|
---|
| 155 | vars = {}
|
---|
| 156 | _extend_dict(vars, get_config_vars())
|
---|
| 157 |
|
---|
| 158 | for key, value in _INSTALL_SCHEMES[scheme].items():
|
---|
[394] | 159 | if os.name in ('posix', 'nt', 'os2'):
|
---|
[388] | 160 | value = os.path.expanduser(value)
|
---|
| 161 | res[key] = os.path.normpath(_subst_vars(value, vars))
|
---|
| 162 | return res
|
---|
| 163 |
|
---|
| 164 | def _get_default_scheme():
|
---|
| 165 | if os.name == 'posix':
|
---|
| 166 | # the default scheme for posix is posix_prefix
|
---|
| 167 | return 'posix_prefix'
|
---|
| 168 | return os.name
|
---|
| 169 |
|
---|
| 170 | def _getuserbase():
|
---|
| 171 | env_base = os.environ.get("PYTHONUSERBASE", None)
|
---|
| 172 | def joinuser(*args):
|
---|
| 173 | return os.path.expanduser(os.path.join(*args))
|
---|
| 174 |
|
---|
| 175 | # what about 'os2emx', 'riscos' ?
|
---|
| 176 | if os.name == "nt":
|
---|
| 177 | base = os.environ.get("APPDATA") or "~"
|
---|
| 178 | return env_base if env_base else joinuser(base, "Python")
|
---|
| 179 |
|
---|
| 180 | if sys.platform == "darwin":
|
---|
| 181 | framework = get_config_var("PYTHONFRAMEWORK")
|
---|
| 182 | if framework:
|
---|
| 183 | return env_base if env_base else \
|
---|
| 184 | joinuser("~", "Library", framework, "%d.%d"
|
---|
| 185 | % (sys.version_info[:2]))
|
---|
| 186 |
|
---|
| 187 | return env_base if env_base else joinuser("~", ".local")
|
---|
| 188 |
|
---|
| 189 |
|
---|
| 190 | def _parse_makefile(filename, vars=None):
|
---|
| 191 | """Parse a Makefile-style file.
|
---|
| 192 |
|
---|
| 193 | A dictionary containing name/value pairs is returned. If an
|
---|
| 194 | optional dictionary is passed in as the second argument, it is
|
---|
| 195 | used instead of a new dictionary.
|
---|
| 196 | """
|
---|
| 197 | import re
|
---|
| 198 | # Regexes needed for parsing Makefile (and similar syntaxes,
|
---|
| 199 | # like old-style Setup files).
|
---|
| 200 | _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
|
---|
| 201 | _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
|
---|
| 202 | _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
|
---|
| 203 |
|
---|
| 204 | if vars is None:
|
---|
| 205 | vars = {}
|
---|
| 206 | done = {}
|
---|
| 207 | notdone = {}
|
---|
| 208 |
|
---|
| 209 | with open(filename) as f:
|
---|
| 210 | lines = f.readlines()
|
---|
| 211 |
|
---|
| 212 | for line in lines:
|
---|
| 213 | if line.startswith('#') or line.strip() == '':
|
---|
| 214 | continue
|
---|
| 215 | m = _variable_rx.match(line)
|
---|
| 216 | if m:
|
---|
| 217 | n, v = m.group(1, 2)
|
---|
| 218 | v = v.strip()
|
---|
| 219 | # `$$' is a literal `$' in make
|
---|
| 220 | tmpv = v.replace('$$', '')
|
---|
| 221 |
|
---|
| 222 | if "$" in tmpv:
|
---|
| 223 | notdone[n] = v
|
---|
| 224 | else:
|
---|
| 225 | try:
|
---|
| 226 | v = int(v)
|
---|
| 227 | except ValueError:
|
---|
| 228 | # insert literal `$'
|
---|
| 229 | done[n] = v.replace('$$', '$')
|
---|
| 230 | else:
|
---|
| 231 | done[n] = v
|
---|
| 232 |
|
---|
| 233 | # do variable interpolation here
|
---|
| 234 | while notdone:
|
---|
| 235 | for name in notdone.keys():
|
---|
| 236 | value = notdone[name]
|
---|
| 237 | m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
|
---|
| 238 | if m:
|
---|
| 239 | n = m.group(1)
|
---|
| 240 | found = True
|
---|
| 241 | if n in done:
|
---|
| 242 | item = str(done[n])
|
---|
| 243 | elif n in notdone:
|
---|
| 244 | # get it on a subsequent round
|
---|
| 245 | found = False
|
---|
| 246 | elif n in os.environ:
|
---|
| 247 | # do it like make: fall back to environment
|
---|
| 248 | item = os.environ[n]
|
---|
| 249 | else:
|
---|
| 250 | done[n] = item = ""
|
---|
| 251 | if found:
|
---|
| 252 | after = value[m.end():]
|
---|
| 253 | value = value[:m.start()] + item + after
|
---|
| 254 | if "$" in after:
|
---|
| 255 | notdone[name] = value
|
---|
| 256 | else:
|
---|
| 257 | try: value = int(value)
|
---|
| 258 | except ValueError:
|
---|
| 259 | done[name] = value.strip()
|
---|
| 260 | else:
|
---|
| 261 | done[name] = value
|
---|
| 262 | del notdone[name]
|
---|
| 263 | else:
|
---|
| 264 | # bogus variable reference; just drop it since we can't deal
|
---|
| 265 | del notdone[name]
|
---|
| 266 | # strip spurious spaces
|
---|
| 267 | for k, v in done.items():
|
---|
| 268 | if isinstance(v, str):
|
---|
| 269 | done[k] = v.strip()
|
---|
| 270 |
|
---|
| 271 | # save the results in the global dictionary
|
---|
| 272 | vars.update(done)
|
---|
| 273 | return vars
|
---|
| 274 |
|
---|
| 275 |
|
---|
| 276 | def _get_makefile_filename():
|
---|
| 277 | if _PYTHON_BUILD:
|
---|
| 278 | return os.path.join(_PROJECT_BASE, "Makefile")
|
---|
| 279 | return os.path.join(get_path('platstdlib'), "config", "Makefile")
|
---|
| 280 |
|
---|
| 281 | def _generate_posix_vars():
|
---|
| 282 | """Generate the Python module containing build-time variables."""
|
---|
| 283 | import pprint
|
---|
| 284 | vars = {}
|
---|
| 285 | # load the installed Makefile:
|
---|
| 286 | makefile = _get_makefile_filename()
|
---|
| 287 | try:
|
---|
| 288 | _parse_makefile(makefile, vars)
|
---|
| 289 | except IOError, e:
|
---|
| 290 | msg = "invalid Python installation: unable to open %s" % makefile
|
---|
| 291 | if hasattr(e, "strerror"):
|
---|
| 292 | msg = msg + " (%s)" % e.strerror
|
---|
| 293 | raise IOError(msg)
|
---|
| 294 |
|
---|
| 295 | # load the installed pyconfig.h:
|
---|
| 296 | config_h = get_config_h_filename()
|
---|
| 297 | try:
|
---|
| 298 | with open(config_h) as f:
|
---|
| 299 | parse_config_h(f, vars)
|
---|
| 300 | except IOError, e:
|
---|
| 301 | msg = "invalid Python installation: unable to open %s" % config_h
|
---|
| 302 | if hasattr(e, "strerror"):
|
---|
| 303 | msg = msg + " (%s)" % e.strerror
|
---|
| 304 | raise IOError(msg)
|
---|
| 305 |
|
---|
| 306 | # On AIX, there are wrong paths to the linker scripts in the Makefile
|
---|
| 307 | # -- these paths are relative to the Python source, but when installed
|
---|
| 308 | # the scripts are in another directory.
|
---|
| 309 | if _PYTHON_BUILD:
|
---|
| 310 | vars['LDSHARED'] = vars['BLDSHARED']
|
---|
| 311 |
|
---|
| 312 | # There's a chicken-and-egg situation on OS X with regards to the
|
---|
| 313 | # _sysconfigdata module after the changes introduced by #15298:
|
---|
| 314 | # get_config_vars() is called by get_platform() as part of the
|
---|
| 315 | # `make pybuilddir.txt` target -- which is a precursor to the
|
---|
| 316 | # _sysconfigdata.py module being constructed. Unfortunately,
|
---|
| 317 | # get_config_vars() eventually calls _init_posix(), which attempts
|
---|
| 318 | # to import _sysconfigdata, which we won't have built yet. In order
|
---|
| 319 | # for _init_posix() to work, if we're on Darwin, just mock up the
|
---|
| 320 | # _sysconfigdata module manually and populate it with the build vars.
|
---|
| 321 | # This is more than sufficient for ensuring the subsequent call to
|
---|
| 322 | # get_platform() succeeds.
|
---|
| 323 | name = '_sysconfigdata'
|
---|
| 324 | if 'darwin' in sys.platform:
|
---|
| 325 | import imp
|
---|
| 326 | module = imp.new_module(name)
|
---|
| 327 | module.build_time_vars = vars
|
---|
| 328 | sys.modules[name] = module
|
---|
| 329 |
|
---|
| 330 | pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version[:3])
|
---|
| 331 | if hasattr(sys, "gettotalrefcount"):
|
---|
| 332 | pybuilddir += '-pydebug'
|
---|
| 333 | try:
|
---|
| 334 | os.makedirs(pybuilddir)
|
---|
| 335 | except OSError:
|
---|
| 336 | pass
|
---|
| 337 | destfile = os.path.join(pybuilddir, name + '.py')
|
---|
| 338 |
|
---|
| 339 | with open(destfile, 'wb') as f:
|
---|
| 340 | f.write('# system configuration generated and used by'
|
---|
| 341 | ' the sysconfig module\n')
|
---|
| 342 | f.write('build_time_vars = ')
|
---|
| 343 | pprint.pprint(vars, stream=f)
|
---|
| 344 |
|
---|
| 345 | # Create file used for sys.path fixup -- see Modules/getpath.c
|
---|
| 346 | with open('pybuilddir.txt', 'w') as f:
|
---|
| 347 | f.write(pybuilddir)
|
---|
| 348 |
|
---|
| 349 | def _init_posix(vars):
|
---|
| 350 | """Initialize the module as appropriate for POSIX systems."""
|
---|
| 351 | # _sysconfigdata is generated at build time, see _generate_posix_vars()
|
---|
| 352 | from _sysconfigdata import build_time_vars
|
---|
| 353 | vars.update(build_time_vars)
|
---|
| 354 |
|
---|
| 355 | def _init_non_posix(vars):
|
---|
| 356 | """Initialize the module as appropriate for NT"""
|
---|
| 357 | # set basic install directories
|
---|
| 358 | vars['LIBDEST'] = get_path('stdlib')
|
---|
| 359 | vars['BINLIBDEST'] = get_path('platstdlib')
|
---|
| 360 | vars['INCLUDEPY'] = get_path('include')
|
---|
| 361 | vars['SO'] = '.pyd'
|
---|
| 362 | vars['EXE'] = '.exe'
|
---|
| 363 | vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
|
---|
| 364 | vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
|
---|
| 365 |
|
---|
| 366 | #
|
---|
| 367 | # public APIs
|
---|
| 368 | #
|
---|
| 369 |
|
---|
| 370 |
|
---|
| 371 | def parse_config_h(fp, vars=None):
|
---|
| 372 | """Parse a config.h-style file.
|
---|
| 373 |
|
---|
| 374 | A dictionary containing name/value pairs is returned. If an
|
---|
| 375 | optional dictionary is passed in as the second argument, it is
|
---|
| 376 | used instead of a new dictionary.
|
---|
| 377 | """
|
---|
| 378 | import re
|
---|
| 379 | if vars is None:
|
---|
| 380 | vars = {}
|
---|
| 381 | define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
|
---|
| 382 | undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
|
---|
| 383 |
|
---|
| 384 | while True:
|
---|
| 385 | line = fp.readline()
|
---|
| 386 | if not line:
|
---|
| 387 | break
|
---|
| 388 | m = define_rx.match(line)
|
---|
| 389 | if m:
|
---|
| 390 | n, v = m.group(1, 2)
|
---|
| 391 | try: v = int(v)
|
---|
| 392 | except ValueError: pass
|
---|
| 393 | vars[n] = v
|
---|
| 394 | else:
|
---|
| 395 | m = undef_rx.match(line)
|
---|
| 396 | if m:
|
---|
| 397 | vars[m.group(1)] = 0
|
---|
| 398 | return vars
|
---|
| 399 |
|
---|
| 400 | def get_config_h_filename():
|
---|
| 401 | """Returns the path of pyconfig.h."""
|
---|
| 402 | if _PYTHON_BUILD:
|
---|
| 403 | if os.name == "nt":
|
---|
| 404 | inc_dir = os.path.join(_PROJECT_BASE, "PC")
|
---|
| 405 | else:
|
---|
| 406 | inc_dir = _PROJECT_BASE
|
---|
| 407 | else:
|
---|
| 408 | inc_dir = get_path('platinclude')
|
---|
| 409 | return os.path.join(inc_dir, 'pyconfig.h')
|
---|
| 410 |
|
---|
| 411 | def get_scheme_names():
|
---|
| 412 | """Returns a tuple containing the schemes names."""
|
---|
| 413 | schemes = _INSTALL_SCHEMES.keys()
|
---|
| 414 | schemes.sort()
|
---|
| 415 | return tuple(schemes)
|
---|
| 416 |
|
---|
| 417 | def get_path_names():
|
---|
| 418 | """Returns a tuple containing the paths names."""
|
---|
| 419 | return _SCHEME_KEYS
|
---|
| 420 |
|
---|
| 421 | def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
|
---|
| 422 | """Returns a mapping containing an install scheme.
|
---|
| 423 |
|
---|
| 424 | ``scheme`` is the install scheme name. If not provided, it will
|
---|
| 425 | return the default scheme for the current platform.
|
---|
| 426 | """
|
---|
| 427 | if expand:
|
---|
| 428 | return _expand_vars(scheme, vars)
|
---|
| 429 | else:
|
---|
| 430 | return _INSTALL_SCHEMES[scheme]
|
---|
| 431 |
|
---|
| 432 | def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
|
---|
| 433 | """Returns a path corresponding to the scheme.
|
---|
| 434 |
|
---|
| 435 | ``scheme`` is the install scheme name.
|
---|
| 436 | """
|
---|
| 437 | return get_paths(scheme, vars, expand)[name]
|
---|
| 438 |
|
---|
| 439 | def get_config_vars(*args):
|
---|
| 440 | """With no arguments, return a dictionary of all configuration
|
---|
| 441 | variables relevant for the current platform.
|
---|
| 442 |
|
---|
| 443 | On Unix, this means every variable defined in Python's installed Makefile;
|
---|
| 444 | On Windows and Mac OS it's a much smaller set.
|
---|
| 445 |
|
---|
| 446 | With arguments, return a list of values that result from looking up
|
---|
| 447 | each argument in the configuration variable dictionary.
|
---|
| 448 | """
|
---|
| 449 | import re
|
---|
| 450 | global _CONFIG_VARS
|
---|
| 451 | if _CONFIG_VARS is None:
|
---|
| 452 | _CONFIG_VARS = {}
|
---|
| 453 | # Normalized versions of prefix and exec_prefix are handy to have;
|
---|
| 454 | # in fact, these are the standard versions used most places in the
|
---|
| 455 | # Distutils.
|
---|
| 456 | _CONFIG_VARS['prefix'] = _PREFIX
|
---|
| 457 | _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
|
---|
| 458 | _CONFIG_VARS['py_version'] = _PY_VERSION
|
---|
| 459 | _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
|
---|
| 460 | _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
|
---|
| 461 | _CONFIG_VARS['base'] = _PREFIX
|
---|
| 462 | _CONFIG_VARS['platbase'] = _EXEC_PREFIX
|
---|
| 463 | _CONFIG_VARS['projectbase'] = _PROJECT_BASE
|
---|
| 464 |
|
---|
[394] | 465 | if os.name == 'nt':
|
---|
[388] | 466 | _init_non_posix(_CONFIG_VARS)
|
---|
[394] | 467 | if os.name in ('posix', 'os2'):
|
---|
[388] | 468 | _init_posix(_CONFIG_VARS)
|
---|
| 469 |
|
---|
| 470 | # Setting 'userbase' is done below the call to the
|
---|
| 471 | # init function to enable using 'get_config_var' in
|
---|
| 472 | # the init-function.
|
---|
| 473 | _CONFIG_VARS['userbase'] = _getuserbase()
|
---|
| 474 |
|
---|
| 475 | if 'srcdir' not in _CONFIG_VARS:
|
---|
| 476 | _CONFIG_VARS['srcdir'] = _PROJECT_BASE
|
---|
| 477 |
|
---|
| 478 | # Convert srcdir into an absolute path if it appears necessary.
|
---|
| 479 | # Normally it is relative to the build directory. However, during
|
---|
| 480 | # testing, for example, we might be running a non-installed python
|
---|
| 481 | # from a different directory.
|
---|
| 482 | if _PYTHON_BUILD and os.name == "posix":
|
---|
| 483 | base = _PROJECT_BASE
|
---|
| 484 | try:
|
---|
| 485 | cwd = os.getcwd()
|
---|
| 486 | except OSError:
|
---|
| 487 | cwd = None
|
---|
| 488 | if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
|
---|
| 489 | base != cwd):
|
---|
| 490 | # srcdir is relative and we are not in the same directory
|
---|
| 491 | # as the executable. Assume executable is in the build
|
---|
| 492 | # directory and make srcdir absolute.
|
---|
| 493 | srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
|
---|
| 494 | _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
|
---|
| 495 |
|
---|
| 496 | # OS X platforms require special customization to handle
|
---|
| 497 | # multi-architecture, multi-os-version installers
|
---|
| 498 | if sys.platform == 'darwin':
|
---|
| 499 | import _osx_support
|
---|
| 500 | _osx_support.customize_config_vars(_CONFIG_VARS)
|
---|
| 501 |
|
---|
| 502 | if args:
|
---|
| 503 | vals = []
|
---|
| 504 | for name in args:
|
---|
| 505 | vals.append(_CONFIG_VARS.get(name))
|
---|
| 506 | return vals
|
---|
| 507 | else:
|
---|
| 508 | return _CONFIG_VARS
|
---|
| 509 |
|
---|
| 510 | def get_config_var(name):
|
---|
| 511 | """Return the value of a single variable using the dictionary returned by
|
---|
| 512 | 'get_config_vars()'.
|
---|
| 513 |
|
---|
| 514 | Equivalent to get_config_vars().get(name)
|
---|
| 515 | """
|
---|
| 516 | return get_config_vars().get(name)
|
---|
| 517 |
|
---|
| 518 | def get_platform():
|
---|
| 519 | """Return a string that identifies the current platform.
|
---|
| 520 |
|
---|
| 521 | This is used mainly to distinguish platform-specific build directories and
|
---|
| 522 | platform-specific built distributions. Typically includes the OS name
|
---|
| 523 | and version and the architecture (as supplied by 'os.uname()'),
|
---|
| 524 | although the exact information included depends on the OS; eg. for IRIX
|
---|
| 525 | the architecture isn't particularly important (IRIX only runs on SGI
|
---|
| 526 | hardware), but for Linux the kernel version isn't particularly
|
---|
| 527 | important.
|
---|
| 528 |
|
---|
| 529 | Examples of returned values:
|
---|
| 530 | linux-i586
|
---|
| 531 | linux-alpha (?)
|
---|
| 532 | solaris-2.6-sun4u
|
---|
| 533 | irix-5.3
|
---|
| 534 | irix64-6.2
|
---|
| 535 |
|
---|
| 536 | Windows will return one of:
|
---|
| 537 | win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
|
---|
| 538 | win-ia64 (64bit Windows on Itanium)
|
---|
| 539 | win32 (all others - specifically, sys.platform is returned)
|
---|
| 540 |
|
---|
| 541 | For other non-POSIX platforms, currently just returns 'sys.platform'.
|
---|
| 542 | """
|
---|
| 543 | import re
|
---|
| 544 | if os.name == 'nt':
|
---|
| 545 | # sniff sys.version for architecture.
|
---|
| 546 | prefix = " bit ("
|
---|
| 547 | i = sys.version.find(prefix)
|
---|
| 548 | if i == -1:
|
---|
| 549 | return sys.platform
|
---|
| 550 | j = sys.version.find(")", i)
|
---|
| 551 | look = sys.version[i+len(prefix):j].lower()
|
---|
| 552 | if look == 'amd64':
|
---|
| 553 | return 'win-amd64'
|
---|
| 554 | if look == 'itanium':
|
---|
| 555 | return 'win-ia64'
|
---|
| 556 | return sys.platform
|
---|
| 557 |
|
---|
| 558 | # Set for cross builds explicitly
|
---|
| 559 | if "_PYTHON_HOST_PLATFORM" in os.environ:
|
---|
| 560 | return os.environ["_PYTHON_HOST_PLATFORM"]
|
---|
| 561 |
|
---|
| 562 | if os.name != "posix" or not hasattr(os, 'uname'):
|
---|
| 563 | # XXX what about the architecture? NT is Intel or Alpha,
|
---|
| 564 | # Mac OS is M68k or PPC, etc.
|
---|
| 565 | return sys.platform
|
---|
| 566 |
|
---|
| 567 | # Try to distinguish various flavours of Unix
|
---|
| 568 | osname, host, release, version, machine = os.uname()
|
---|
| 569 |
|
---|
| 570 | # Convert the OS name to lowercase, remove '/' characters
|
---|
| 571 | # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
|
---|
| 572 | osname = osname.lower().replace('/', '')
|
---|
| 573 | machine = machine.replace(' ', '_')
|
---|
| 574 | machine = machine.replace('/', '-')
|
---|
| 575 |
|
---|
| 576 | if osname[:5] == "linux":
|
---|
| 577 | # At least on Linux/Intel, 'machine' is the processor --
|
---|
| 578 | # i386, etc.
|
---|
| 579 | # XXX what about Alpha, SPARC, etc?
|
---|
| 580 | return "%s-%s" % (osname, machine)
|
---|
| 581 | elif osname[:5] == "sunos":
|
---|
| 582 | if release[0] >= "5": # SunOS 5 == Solaris 2
|
---|
| 583 | osname = "solaris"
|
---|
| 584 | release = "%d.%s" % (int(release[0]) - 3, release[2:])
|
---|
| 585 | # We can't use "platform.architecture()[0]" because a
|
---|
| 586 | # bootstrap problem. We use a dict to get an error
|
---|
| 587 | # if some suspicious happens.
|
---|
| 588 | bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
|
---|
| 589 | machine += ".%s" % bitness[sys.maxint]
|
---|
| 590 | # fall through to standard osname-release-machine representation
|
---|
| 591 | elif osname[:4] == "irix": # could be "irix64"!
|
---|
| 592 | return "%s-%s" % (osname, release)
|
---|
| 593 | elif osname[:3] == "aix":
|
---|
| 594 | return "%s-%s.%s" % (osname, version, release)
|
---|
| 595 | elif osname[:6] == "cygwin":
|
---|
| 596 | osname = "cygwin"
|
---|
| 597 | rel_re = re.compile (r'[\d.]+')
|
---|
| 598 | m = rel_re.match(release)
|
---|
| 599 | if m:
|
---|
| 600 | release = m.group()
|
---|
| 601 | elif osname[:6] == "darwin":
|
---|
| 602 | import _osx_support
|
---|
| 603 | osname, release, machine = _osx_support.get_platform_osx(
|
---|
| 604 | get_config_vars(),
|
---|
| 605 | osname, release, machine)
|
---|
| 606 |
|
---|
| 607 | return "%s-%s-%s" % (osname, release, machine)
|
---|
| 608 |
|
---|
| 609 |
|
---|
| 610 | def get_python_version():
|
---|
| 611 | return _PY_VERSION_SHORT
|
---|
| 612 |
|
---|
| 613 |
|
---|
| 614 | def _print_dict(title, data):
|
---|
| 615 | for index, (key, value) in enumerate(sorted(data.items())):
|
---|
| 616 | if index == 0:
|
---|
| 617 | print '%s: ' % (title)
|
---|
| 618 | print '\t%s = "%s"' % (key, value)
|
---|
| 619 |
|
---|
| 620 |
|
---|
| 621 | def _main():
|
---|
| 622 | """Display all information sysconfig detains."""
|
---|
| 623 | if '--generate-posix-vars' in sys.argv:
|
---|
| 624 | _generate_posix_vars()
|
---|
| 625 | return
|
---|
| 626 | print 'Platform: "%s"' % get_platform()
|
---|
| 627 | print 'Python version: "%s"' % get_python_version()
|
---|
| 628 | print 'Current installation scheme: "%s"' % _get_default_scheme()
|
---|
| 629 | print
|
---|
| 630 | _print_dict('Paths', get_paths())
|
---|
| 631 | print
|
---|
| 632 | _print_dict('Variables', get_config_vars())
|
---|
| 633 |
|
---|
| 634 |
|
---|
| 635 | if __name__ == '__main__':
|
---|
| 636 | _main()
|
---|