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