Home | History | Annotate | Download | only in Lib
      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': {
     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}/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():
    159         if os.name in ('posix', 'nt'):
    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     """Return the path of the Makefile."""
    278     if _PYTHON_BUILD:
    279         return os.path.join(_PROJECT_BASE, "Makefile")
    280     return os.path.join(get_path('platstdlib'), "config", "Makefile")
    281 
    282 # Issue #22199: retain undocumented private name for compatibility
    283 _get_makefile_filename = get_makefile_filename
    284 
    285 def _generate_posix_vars():
    286     """Generate the Python module containing build-time variables."""
    287     import pprint
    288     vars = {}
    289     # load the installed Makefile:
    290     makefile = get_makefile_filename()
    291     try:
    292         _parse_makefile(makefile, vars)
    293     except IOError, e:
    294         msg = "invalid Python installation: unable to open %s" % makefile
    295         if hasattr(e, "strerror"):
    296             msg = msg + " (%s)" % e.strerror
    297         raise IOError(msg)
    298 
    299     # load the installed pyconfig.h:
    300     config_h = get_config_h_filename()
    301     try:
    302         with open(config_h) as f:
    303             parse_config_h(f, vars)
    304     except IOError, e:
    305         msg = "invalid Python installation: unable to open %s" % config_h
    306         if hasattr(e, "strerror"):
    307             msg = msg + " (%s)" % e.strerror
    308         raise IOError(msg)
    309 
    310     # On AIX, there are wrong paths to the linker scripts in the Makefile
    311     # -- these paths are relative to the Python source, but when installed
    312     # the scripts are in another directory.
    313     if _PYTHON_BUILD:
    314         vars['LDSHARED'] = vars['BLDSHARED']
    315 
    316     # There's a chicken-and-egg situation on OS X with regards to the
    317     # _sysconfigdata module after the changes introduced by #15298:
    318     # get_config_vars() is called by get_platform() as part of the
    319     # `make pybuilddir.txt` target -- which is a precursor to the
    320     # _sysconfigdata.py module being constructed.  Unfortunately,
    321     # get_config_vars() eventually calls _init_posix(), which attempts
    322     # to import _sysconfigdata, which we won't have built yet.  In order
    323     # for _init_posix() to work, if we're on Darwin, just mock up the
    324     # _sysconfigdata module manually and populate it with the build vars.
    325     # This is more than sufficient for ensuring the subsequent call to
    326     # get_platform() succeeds.
    327     name = '_sysconfigdata'
    328     if 'darwin' in sys.platform:
    329         import imp
    330         module = imp.new_module(name)
    331         module.build_time_vars = vars
    332         sys.modules[name] = module
    333 
    334     pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version[:3])
    335     if hasattr(sys, "gettotalrefcount"):
    336         pybuilddir += '-pydebug'
    337     try:
    338         os.makedirs(pybuilddir)
    339     except OSError:
    340         pass
    341     destfile = os.path.join(pybuilddir, name + '.py')
    342 
    343     with open(destfile, 'wb') as f:
    344         f.write('# system configuration generated and used by'
    345                 ' the sysconfig module\n')
    346         f.write('build_time_vars = ')
    347         pprint.pprint(vars, stream=f)
    348 
    349     # Create file used for sys.path fixup -- see Modules/getpath.c
    350     with open('pybuilddir.txt', 'w') as f:
    351         f.write(pybuilddir)
    352 
    353 def _init_posix(vars):
    354     """Initialize the module as appropriate for POSIX systems."""
    355     # _sysconfigdata is generated at build time, see _generate_posix_vars()
    356     from _sysconfigdata import build_time_vars
    357     vars.update(build_time_vars)
    358 
    359 def _init_non_posix(vars):
    360     """Initialize the module as appropriate for NT"""
    361     # set basic install directories
    362     vars['LIBDEST'] = get_path('stdlib')
    363     vars['BINLIBDEST'] = get_path('platstdlib')
    364     vars['INCLUDEPY'] = get_path('include')
    365     vars['SO'] = '.pyd'
    366     vars['EXE'] = '.exe'
    367     vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
    368     vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
    369 
    370 #
    371 # public APIs
    372 #
    373 
    374 
    375 def parse_config_h(fp, vars=None):
    376     """Parse a config.h-style file.
    377 
    378     A dictionary containing name/value pairs is returned.  If an
    379     optional dictionary is passed in as the second argument, it is
    380     used instead of a new dictionary.
    381     """
    382     import re
    383     if vars is None:
    384         vars = {}
    385     define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
    386     undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
    387 
    388     while True:
    389         line = fp.readline()
    390         if not line:
    391             break
    392         m = define_rx.match(line)
    393         if m:
    394             n, v = m.group(1, 2)
    395             try: v = int(v)
    396             except ValueError: pass
    397             vars[n] = v
    398         else:
    399             m = undef_rx.match(line)
    400             if m:
    401                 vars[m.group(1)] = 0
    402     return vars
    403 
    404 def get_config_h_filename():
    405     """Returns the path of pyconfig.h."""
    406     if _PYTHON_BUILD:
    407         if os.name == "nt":
    408             inc_dir = os.path.join(_PROJECT_BASE, "PC")
    409         else:
    410             inc_dir = _PROJECT_BASE
    411     else:
    412         inc_dir = get_path('platinclude')
    413     return os.path.join(inc_dir, 'pyconfig.h')
    414 
    415 def get_scheme_names():
    416     """Returns a tuple containing the schemes names."""
    417     schemes = _INSTALL_SCHEMES.keys()
    418     schemes.sort()
    419     return tuple(schemes)
    420 
    421 def get_path_names():
    422     """Returns a tuple containing the paths names."""
    423     return _SCHEME_KEYS
    424 
    425 def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
    426     """Returns a mapping containing an install scheme.
    427 
    428     ``scheme`` is the install scheme name. If not provided, it will
    429     return the default scheme for the current platform.
    430     """
    431     if expand:
    432         return _expand_vars(scheme, vars)
    433     else:
    434         return _INSTALL_SCHEMES[scheme]
    435 
    436 def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
    437     """Returns a path corresponding to the scheme.
    438 
    439     ``scheme`` is the install scheme name.
    440     """
    441     return get_paths(scheme, vars, expand)[name]
    442 
    443 def get_config_vars(*args):
    444     """With no arguments, return a dictionary of all configuration
    445     variables relevant for the current platform.
    446 
    447     On Unix, this means every variable defined in Python's installed Makefile;
    448     On Windows and Mac OS it's a much smaller set.
    449 
    450     With arguments, return a list of values that result from looking up
    451     each argument in the configuration variable dictionary.
    452     """
    453     import re
    454     global _CONFIG_VARS
    455     if _CONFIG_VARS is None:
    456         _CONFIG_VARS = {}
    457         # Normalized versions of prefix and exec_prefix are handy to have;
    458         # in fact, these are the standard versions used most places in the
    459         # Distutils.
    460         _CONFIG_VARS['prefix'] = _PREFIX
    461         _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
    462         _CONFIG_VARS['py_version'] = _PY_VERSION
    463         _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
    464         _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
    465         _CONFIG_VARS['base'] = _PREFIX
    466         _CONFIG_VARS['platbase'] = _EXEC_PREFIX
    467         _CONFIG_VARS['projectbase'] = _PROJECT_BASE
    468 
    469         if os.name in ('nt', 'os2'):
    470             _init_non_posix(_CONFIG_VARS)
    471         if os.name == 'posix':
    472             _init_posix(_CONFIG_VARS)
    473 
    474         # Setting 'userbase' is done below the call to the
    475         # init function to enable using 'get_config_var' in
    476         # the init-function.
    477         _CONFIG_VARS['userbase'] = _getuserbase()
    478 
    479         if 'srcdir' not in _CONFIG_VARS:
    480             _CONFIG_VARS['srcdir'] = _PROJECT_BASE
    481 
    482         # Convert srcdir into an absolute path if it appears necessary.
    483         # Normally it is relative to the build directory.  However, during
    484         # testing, for example, we might be running a non-installed python
    485         # from a different directory.
    486         if _PYTHON_BUILD and os.name == "posix":
    487             base = _PROJECT_BASE
    488             try:
    489                 cwd = os.getcwd()
    490             except OSError:
    491                 cwd = None
    492             if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
    493                 base != cwd):
    494                 # srcdir is relative and we are not in the same directory
    495                 # as the executable. Assume executable is in the build
    496                 # directory and make srcdir absolute.
    497                 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
    498                 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
    499 
    500         # OS X platforms require special customization to handle
    501         # multi-architecture, multi-os-version installers
    502         if sys.platform == 'darwin':
    503             import _osx_support
    504             _osx_support.customize_config_vars(_CONFIG_VARS)
    505 
    506     if args:
    507         vals = []
    508         for name in args:
    509             vals.append(_CONFIG_VARS.get(name))
    510         return vals
    511     else:
    512         return _CONFIG_VARS
    513 
    514 def get_config_var(name):
    515     """Return the value of a single variable using the dictionary returned by
    516     'get_config_vars()'.
    517 
    518     Equivalent to get_config_vars().get(name)
    519     """
    520     return get_config_vars().get(name)
    521 
    522 def get_platform():
    523     """Return a string that identifies the current platform.
    524 
    525     This is used mainly to distinguish platform-specific build directories and
    526     platform-specific built distributions.  Typically includes the OS name
    527     and version and the architecture (as supplied by 'os.uname()'),
    528     although the exact information included depends on the OS; eg. for IRIX
    529     the architecture isn't particularly important (IRIX only runs on SGI
    530     hardware), but for Linux the kernel version isn't particularly
    531     important.
    532 
    533     Examples of returned values:
    534        linux-i586
    535        linux-alpha (?)
    536        solaris-2.6-sun4u
    537        irix-5.3
    538        irix64-6.2
    539 
    540     Windows will return one of:
    541        win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
    542        win-ia64 (64bit Windows on Itanium)
    543        win32 (all others - specifically, sys.platform is returned)
    544 
    545     For other non-POSIX platforms, currently just returns 'sys.platform'.
    546     """
    547     import re
    548     if os.name == 'nt':
    549         # sniff sys.version for architecture.
    550         prefix = " bit ("
    551         i = sys.version.find(prefix)
    552         if i == -1:
    553             return sys.platform
    554         j = sys.version.find(")", i)
    555         look = sys.version[i+len(prefix):j].lower()
    556         if look == 'amd64':
    557             return 'win-amd64'
    558         if look == 'itanium':
    559             return 'win-ia64'
    560         return sys.platform
    561 
    562     # Set for cross builds explicitly
    563     if "_PYTHON_HOST_PLATFORM" in os.environ:
    564         return os.environ["_PYTHON_HOST_PLATFORM"]
    565 
    566     if os.name != "posix" or not hasattr(os, 'uname'):
    567         # XXX what about the architecture? NT is Intel or Alpha,
    568         # Mac OS is M68k or PPC, etc.
    569         return sys.platform
    570 
    571     # Try to distinguish various flavours of Unix
    572     osname, host, release, version, machine = os.uname()
    573 
    574     # Convert the OS name to lowercase, remove '/' characters
    575     # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
    576     osname = osname.lower().replace('/', '')
    577     machine = machine.replace(' ', '_')
    578     machine = machine.replace('/', '-')
    579 
    580     if osname[:5] == "linux":
    581         # At least on Linux/Intel, 'machine' is the processor --
    582         # i386, etc.
    583         # XXX what about Alpha, SPARC, etc?
    584         return  "%s-%s" % (osname, machine)
    585     elif osname[:5] == "sunos":
    586         if release[0] >= "5":           # SunOS 5 == Solaris 2
    587             osname = "solaris"
    588             release = "%d.%s" % (int(release[0]) - 3, release[2:])
    589             # We can't use "platform.architecture()[0]" because a
    590             # bootstrap problem. We use a dict to get an error
    591             # if some suspicious happens.
    592             bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
    593             machine += ".%s" % bitness[sys.maxint]
    594         # fall through to standard osname-release-machine representation
    595     elif osname[:4] == "irix":              # could be "irix64"!
    596         return "%s-%s" % (osname, release)
    597     elif osname[:3] == "aix":
    598         return "%s-%s.%s" % (osname, version, release)
    599     elif osname[:6] == "cygwin":
    600         osname = "cygwin"
    601         rel_re = re.compile (r'[\d.]+')
    602         m = rel_re.match(release)
    603         if m:
    604             release = m.group()
    605     elif osname[:6] == "darwin":
    606         import _osx_support
    607         osname, release, machine = _osx_support.get_platform_osx(
    608                                             get_config_vars(),
    609                                             osname, release, machine)
    610 
    611     return "%s-%s-%s" % (osname, release, machine)
    612 
    613 
    614 def get_python_version():
    615     return _PY_VERSION_SHORT
    616 
    617 
    618 def _print_dict(title, data):
    619     for index, (key, value) in enumerate(sorted(data.items())):
    620         if index == 0:
    621             print '%s: ' % (title)
    622         print '\t%s = "%s"' % (key, value)
    623 
    624 
    625 def _main():
    626     """Display all information sysconfig detains."""
    627     if '--generate-posix-vars' in sys.argv:
    628         _generate_posix_vars()
    629         return
    630     print 'Platform: "%s"' % get_platform()
    631     print 'Python version: "%s"' % get_python_version()
    632     print 'Current installation scheme: "%s"' % _get_default_scheme()
    633     print
    634     _print_dict('Paths', get_paths())
    635     print
    636     _print_dict('Variables', get_config_vars())
    637 
    638 
    639 if __name__ == '__main__':
    640     _main()
    641