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