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