PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/pip/_vendor/distlib/_backport/sysconfig.py

https://github.com/ptthiem/pip
Python | 788 lines | 728 code | 18 blank | 42 comment | 28 complexity | 8cdbb4f5d1904b5d977a0afb2bcee34b MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2012 The Python Software Foundation.
  4. # See LICENSE.txt and CONTRIBUTORS.txt.
  5. #
  6. """Access to Python's configuration information."""
  7. import codecs
  8. import os
  9. import re
  10. import sys
  11. from os.path import pardir, realpath
  12. try:
  13. import configparser
  14. except ImportError:
  15. import ConfigParser as configparser
  16. __all__ = [
  17. 'get_config_h_filename',
  18. 'get_config_var',
  19. 'get_config_vars',
  20. 'get_makefile_filename',
  21. 'get_path',
  22. 'get_path_names',
  23. 'get_paths',
  24. 'get_platform',
  25. 'get_python_version',
  26. 'get_scheme_names',
  27. 'parse_config_h',
  28. ]
  29. def _safe_realpath(path):
  30. try:
  31. return realpath(path)
  32. except OSError:
  33. return path
  34. if sys.executable:
  35. _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
  36. else:
  37. # sys.executable can be empty if argv[0] has been changed and Python is
  38. # unable to retrieve the real program name
  39. _PROJECT_BASE = _safe_realpath(os.getcwd())
  40. if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
  41. _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
  42. # PC/VS7.1
  43. if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
  44. _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
  45. # PC/AMD64
  46. if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
  47. _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
  48. def is_python_build():
  49. for fn in ("Setup.dist", "Setup.local"):
  50. if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
  51. return True
  52. return False
  53. _PYTHON_BUILD = is_python_build()
  54. _cfg_read = False
  55. def _ensure_cfg_read():
  56. global _cfg_read
  57. if not _cfg_read:
  58. from distlib.resources import finder
  59. backport_package = __name__.rsplit('.', 1)[0]
  60. _finder = finder(backport_package)
  61. _cfgfile = _finder.find('sysconfig.cfg')
  62. assert _cfgfile, 'sysconfig.cfg exists'
  63. with _cfgfile.as_stream() as s:
  64. _SCHEMES.readfp(s)
  65. if _PYTHON_BUILD:
  66. for scheme in ('posix_prefix', 'posix_home'):
  67. _SCHEMES.set(scheme, 'include', '{srcdir}/Include')
  68. _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.')
  69. _cfg_read = True
  70. _SCHEMES = configparser.RawConfigParser()
  71. _VAR_REPL = re.compile(r'\{([^{]*?)\}')
  72. def _expand_globals(config):
  73. _ensure_cfg_read()
  74. if config.has_section('globals'):
  75. globals = config.items('globals')
  76. else:
  77. globals = tuple()
  78. sections = config.sections()
  79. for section in sections:
  80. if section == 'globals':
  81. continue
  82. for option, value in globals:
  83. if config.has_option(section, option):
  84. continue
  85. config.set(section, option, value)
  86. config.remove_section('globals')
  87. # now expanding local variables defined in the cfg file
  88. #
  89. for section in config.sections():
  90. variables = dict(config.items(section))
  91. def _replacer(matchobj):
  92. name = matchobj.group(1)
  93. if name in variables:
  94. return variables[name]
  95. return matchobj.group(0)
  96. for option, value in config.items(section):
  97. config.set(section, option, _VAR_REPL.sub(_replacer, value))
  98. #_expand_globals(_SCHEMES)
  99. # FIXME don't rely on sys.version here, its format is an implementation detail
  100. # of CPython, use sys.version_info or sys.hexversion
  101. _PY_VERSION = sys.version.split()[0]
  102. _PY_VERSION_SHORT = sys.version[:3]
  103. _PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
  104. _PREFIX = os.path.normpath(sys.prefix)
  105. _EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
  106. _CONFIG_VARS = None
  107. _USER_BASE = None
  108. def _subst_vars(path, local_vars):
  109. """In the string `path`, replace tokens like {some.thing} with the
  110. corresponding value from the map `local_vars`.
  111. If there is no corresponding value, leave the token unchanged.
  112. """
  113. def _replacer(matchobj):
  114. name = matchobj.group(1)
  115. if name in local_vars:
  116. return local_vars[name]
  117. elif name in os.environ:
  118. return os.environ[name]
  119. return matchobj.group(0)
  120. return _VAR_REPL.sub(_replacer, path)
  121. def _extend_dict(target_dict, other_dict):
  122. target_keys = target_dict.keys()
  123. for key, value in other_dict.items():
  124. if key in target_keys:
  125. continue
  126. target_dict[key] = value
  127. def _expand_vars(scheme, vars):
  128. res = {}
  129. if vars is None:
  130. vars = {}
  131. _extend_dict(vars, get_config_vars())
  132. for key, value in _SCHEMES.items(scheme):
  133. if os.name in ('posix', 'nt'):
  134. value = os.path.expanduser(value)
  135. res[key] = os.path.normpath(_subst_vars(value, vars))
  136. return res
  137. def format_value(value, vars):
  138. def _replacer(matchobj):
  139. name = matchobj.group(1)
  140. if name in vars:
  141. return vars[name]
  142. return matchobj.group(0)
  143. return _VAR_REPL.sub(_replacer, value)
  144. def _get_default_scheme():
  145. if os.name == 'posix':
  146. # the default scheme for posix is posix_prefix
  147. return 'posix_prefix'
  148. return os.name
  149. def _getuserbase():
  150. env_base = os.environ.get("PYTHONUSERBASE", None)
  151. def joinuser(*args):
  152. return os.path.expanduser(os.path.join(*args))
  153. # what about 'os2emx', 'riscos' ?
  154. if os.name == "nt":
  155. base = os.environ.get("APPDATA") or "~"
  156. if env_base:
  157. return env_base
  158. else:
  159. return joinuser(base, "Python")
  160. if sys.platform == "darwin":
  161. framework = get_config_var("PYTHONFRAMEWORK")
  162. if framework:
  163. if env_base:
  164. return env_base
  165. else:
  166. return joinuser("~", "Library", framework, "%d.%d" %
  167. sys.version_info[:2])
  168. if env_base:
  169. return env_base
  170. else:
  171. return joinuser("~", ".local")
  172. def _parse_makefile(filename, vars=None):
  173. """Parse a Makefile-style file.
  174. A dictionary containing name/value pairs is returned. If an
  175. optional dictionary is passed in as the second argument, it is
  176. used instead of a new dictionary.
  177. """
  178. # Regexes needed for parsing Makefile (and similar syntaxes,
  179. # like old-style Setup files).
  180. _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
  181. _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
  182. _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
  183. if vars is None:
  184. vars = {}
  185. done = {}
  186. notdone = {}
  187. with codecs.open(filename, encoding='utf-8', errors="surrogateescape") as f:
  188. lines = f.readlines()
  189. for line in lines:
  190. if line.startswith('#') or line.strip() == '':
  191. continue
  192. m = _variable_rx.match(line)
  193. if m:
  194. n, v = m.group(1, 2)
  195. v = v.strip()
  196. # `$$' is a literal `$' in make
  197. tmpv = v.replace('$$', '')
  198. if "$" in tmpv:
  199. notdone[n] = v
  200. else:
  201. try:
  202. v = int(v)
  203. except ValueError:
  204. # insert literal `$'
  205. done[n] = v.replace('$$', '$')
  206. else:
  207. done[n] = v
  208. # do variable interpolation here
  209. variables = list(notdone.keys())
  210. # Variables with a 'PY_' prefix in the makefile. These need to
  211. # be made available without that prefix through sysconfig.
  212. # Special care is needed to ensure that variable expansion works, even
  213. # if the expansion uses the name without a prefix.
  214. renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
  215. while len(variables) > 0:
  216. for name in tuple(variables):
  217. value = notdone[name]
  218. m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
  219. if m is not None:
  220. n = m.group(1)
  221. found = True
  222. if n in done:
  223. item = str(done[n])
  224. elif n in notdone:
  225. # get it on a subsequent round
  226. found = False
  227. elif n in os.environ:
  228. # do it like make: fall back to environment
  229. item = os.environ[n]
  230. elif n in renamed_variables:
  231. if (name.startswith('PY_') and
  232. name[3:] in renamed_variables):
  233. item = ""
  234. elif 'PY_' + n in notdone:
  235. found = False
  236. else:
  237. item = str(done['PY_' + n])
  238. else:
  239. done[n] = item = ""
  240. if found:
  241. after = value[m.end():]
  242. value = value[:m.start()] + item + after
  243. if "$" in after:
  244. notdone[name] = value
  245. else:
  246. try:
  247. value = int(value)
  248. except ValueError:
  249. done[name] = value.strip()
  250. else:
  251. done[name] = value
  252. variables.remove(name)
  253. if (name.startswith('PY_') and
  254. name[3:] in renamed_variables):
  255. name = name[3:]
  256. if name not in done:
  257. done[name] = value
  258. else:
  259. # bogus variable reference (e.g. "prefix=$/opt/python");
  260. # just drop it since we can't deal
  261. done[name] = value
  262. variables.remove(name)
  263. # strip spurious spaces
  264. for k, v in done.items():
  265. if isinstance(v, str):
  266. done[k] = v.strip()
  267. # save the results in the global dictionary
  268. vars.update(done)
  269. return vars
  270. def get_makefile_filename():
  271. """Return the path of the Makefile."""
  272. if _PYTHON_BUILD:
  273. return os.path.join(_PROJECT_BASE, "Makefile")
  274. if hasattr(sys, 'abiflags'):
  275. config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
  276. else:
  277. config_dir_name = 'config'
  278. return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
  279. def _init_posix(vars):
  280. """Initialize the module as appropriate for POSIX systems."""
  281. # load the installed Makefile:
  282. makefile = get_makefile_filename()
  283. try:
  284. _parse_makefile(makefile, vars)
  285. except IOError as e:
  286. msg = "invalid Python installation: unable to open %s" % makefile
  287. if hasattr(e, "strerror"):
  288. msg = msg + " (%s)" % e.strerror
  289. raise IOError(msg)
  290. # load the installed pyconfig.h:
  291. config_h = get_config_h_filename()
  292. try:
  293. with open(config_h) as f:
  294. parse_config_h(f, vars)
  295. except IOError as e:
  296. msg = "invalid Python installation: unable to open %s" % config_h
  297. if hasattr(e, "strerror"):
  298. msg = msg + " (%s)" % e.strerror
  299. raise IOError(msg)
  300. # On AIX, there are wrong paths to the linker scripts in the Makefile
  301. # -- these paths are relative to the Python source, but when installed
  302. # the scripts are in another directory.
  303. if _PYTHON_BUILD:
  304. vars['LDSHARED'] = vars['BLDSHARED']
  305. def _init_non_posix(vars):
  306. """Initialize the module as appropriate for NT"""
  307. # set basic install directories
  308. vars['LIBDEST'] = get_path('stdlib')
  309. vars['BINLIBDEST'] = get_path('platstdlib')
  310. vars['INCLUDEPY'] = get_path('include')
  311. vars['SO'] = '.pyd'
  312. vars['EXE'] = '.exe'
  313. vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
  314. vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
  315. #
  316. # public APIs
  317. #
  318. def parse_config_h(fp, vars=None):
  319. """Parse a config.h-style file.
  320. A dictionary containing name/value pairs is returned. If an
  321. optional dictionary is passed in as the second argument, it is
  322. used instead of a new dictionary.
  323. """
  324. if vars is None:
  325. vars = {}
  326. define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
  327. undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
  328. while True:
  329. line = fp.readline()
  330. if not line:
  331. break
  332. m = define_rx.match(line)
  333. if m:
  334. n, v = m.group(1, 2)
  335. try:
  336. v = int(v)
  337. except ValueError:
  338. pass
  339. vars[n] = v
  340. else:
  341. m = undef_rx.match(line)
  342. if m:
  343. vars[m.group(1)] = 0
  344. return vars
  345. def get_config_h_filename():
  346. """Return the path of pyconfig.h."""
  347. if _PYTHON_BUILD:
  348. if os.name == "nt":
  349. inc_dir = os.path.join(_PROJECT_BASE, "PC")
  350. else:
  351. inc_dir = _PROJECT_BASE
  352. else:
  353. inc_dir = get_path('platinclude')
  354. return os.path.join(inc_dir, 'pyconfig.h')
  355. def get_scheme_names():
  356. """Return a tuple containing the schemes names."""
  357. return tuple(sorted(_SCHEMES.sections()))
  358. def get_path_names():
  359. """Return a tuple containing the paths names."""
  360. # xxx see if we want a static list
  361. return _SCHEMES.options('posix_prefix')
  362. def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
  363. """Return a mapping containing an install scheme.
  364. ``scheme`` is the install scheme name. If not provided, it will
  365. return the default scheme for the current platform.
  366. """
  367. _ensure_cfg_read()
  368. if expand:
  369. return _expand_vars(scheme, vars)
  370. else:
  371. return dict(_SCHEMES.items(scheme))
  372. def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
  373. """Return a path corresponding to the scheme.
  374. ``scheme`` is the install scheme name.
  375. """
  376. return get_paths(scheme, vars, expand)[name]
  377. def get_config_vars(*args):
  378. """With no arguments, return a dictionary of all configuration
  379. variables relevant for the current platform.
  380. On Unix, this means every variable defined in Python's installed Makefile;
  381. On Windows and Mac OS it's a much smaller set.
  382. With arguments, return a list of values that result from looking up
  383. each argument in the configuration variable dictionary.
  384. """
  385. global _CONFIG_VARS
  386. if _CONFIG_VARS is None:
  387. _CONFIG_VARS = {}
  388. # Normalized versions of prefix and exec_prefix are handy to have;
  389. # in fact, these are the standard versions used most places in the
  390. # distutils2 module.
  391. _CONFIG_VARS['prefix'] = _PREFIX
  392. _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
  393. _CONFIG_VARS['py_version'] = _PY_VERSION
  394. _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
  395. _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
  396. _CONFIG_VARS['base'] = _PREFIX
  397. _CONFIG_VARS['platbase'] = _EXEC_PREFIX
  398. _CONFIG_VARS['projectbase'] = _PROJECT_BASE
  399. try:
  400. _CONFIG_VARS['abiflags'] = sys.abiflags
  401. except AttributeError:
  402. # sys.abiflags may not be defined on all platforms.
  403. _CONFIG_VARS['abiflags'] = ''
  404. if os.name in ('nt', 'os2'):
  405. _init_non_posix(_CONFIG_VARS)
  406. if os.name == 'posix':
  407. _init_posix(_CONFIG_VARS)
  408. # Setting 'userbase' is done below the call to the
  409. # init function to enable using 'get_config_var' in
  410. # the init-function.
  411. if sys.version >= '2.6':
  412. _CONFIG_VARS['userbase'] = _getuserbase()
  413. if 'srcdir' not in _CONFIG_VARS:
  414. _CONFIG_VARS['srcdir'] = _PROJECT_BASE
  415. else:
  416. _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir'])
  417. # Convert srcdir into an absolute path if it appears necessary.
  418. # Normally it is relative to the build directory. However, during
  419. # testing, for example, we might be running a non-installed python
  420. # from a different directory.
  421. if _PYTHON_BUILD and os.name == "posix":
  422. base = _PROJECT_BASE
  423. try:
  424. cwd = os.getcwd()
  425. except OSError:
  426. cwd = None
  427. if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
  428. base != cwd):
  429. # srcdir is relative and we are not in the same directory
  430. # as the executable. Assume executable is in the build
  431. # directory and make srcdir absolute.
  432. srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
  433. _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
  434. if sys.platform == 'darwin':
  435. kernel_version = os.uname()[2] # Kernel version (8.4.3)
  436. major_version = int(kernel_version.split('.')[0])
  437. if major_version < 8:
  438. # On Mac OS X before 10.4, check if -arch and -isysroot
  439. # are in CFLAGS or LDFLAGS and remove them if they are.
  440. # This is needed when building extensions on a 10.3 system
  441. # using a universal build of python.
  442. for key in ('LDFLAGS', 'BASECFLAGS',
  443. # a number of derived variables. These need to be
  444. # patched up as well.
  445. 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
  446. flags = _CONFIG_VARS[key]
  447. flags = re.sub('-arch\s+\w+\s', ' ', flags)
  448. flags = re.sub('-isysroot [^ \t]*', ' ', flags)
  449. _CONFIG_VARS[key] = flags
  450. else:
  451. # Allow the user to override the architecture flags using
  452. # an environment variable.
  453. # NOTE: This name was introduced by Apple in OSX 10.5 and
  454. # is used by several scripting languages distributed with
  455. # that OS release.
  456. if 'ARCHFLAGS' in os.environ:
  457. arch = os.environ['ARCHFLAGS']
  458. for key in ('LDFLAGS', 'BASECFLAGS',
  459. # a number of derived variables. These need to be
  460. # patched up as well.
  461. 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
  462. flags = _CONFIG_VARS[key]
  463. flags = re.sub('-arch\s+\w+\s', ' ', flags)
  464. flags = flags + ' ' + arch
  465. _CONFIG_VARS[key] = flags
  466. # If we're on OSX 10.5 or later and the user tries to
  467. # compiles an extension using an SDK that is not present
  468. # on the current machine it is better to not use an SDK
  469. # than to fail.
  470. #
  471. # The major usecase for this is users using a Python.org
  472. # binary installer on OSX 10.6: that installer uses
  473. # the 10.4u SDK, but that SDK is not installed by default
  474. # when you install Xcode.
  475. #
  476. CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
  477. m = re.search('-isysroot\s+(\S+)', CFLAGS)
  478. if m is not None:
  479. sdk = m.group(1)
  480. if not os.path.exists(sdk):
  481. for key in ('LDFLAGS', 'BASECFLAGS',
  482. # a number of derived variables. These need to be
  483. # patched up as well.
  484. 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
  485. flags = _CONFIG_VARS[key]
  486. flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
  487. _CONFIG_VARS[key] = flags
  488. if args:
  489. vals = []
  490. for name in args:
  491. vals.append(_CONFIG_VARS.get(name))
  492. return vals
  493. else:
  494. return _CONFIG_VARS
  495. def get_config_var(name):
  496. """Return the value of a single variable using the dictionary returned by
  497. 'get_config_vars()'.
  498. Equivalent to get_config_vars().get(name)
  499. """
  500. return get_config_vars().get(name)
  501. def get_platform():
  502. """Return a string that identifies the current platform.
  503. This is used mainly to distinguish platform-specific build directories and
  504. platform-specific built distributions. Typically includes the OS name
  505. and version and the architecture (as supplied by 'os.uname()'),
  506. although the exact information included depends on the OS; eg. for IRIX
  507. the architecture isn't particularly important (IRIX only runs on SGI
  508. hardware), but for Linux the kernel version isn't particularly
  509. important.
  510. Examples of returned values:
  511. linux-i586
  512. linux-alpha (?)
  513. solaris-2.6-sun4u
  514. irix-5.3
  515. irix64-6.2
  516. Windows will return one of:
  517. win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
  518. win-ia64 (64bit Windows on Itanium)
  519. win32 (all others - specifically, sys.platform is returned)
  520. For other non-POSIX platforms, currently just returns 'sys.platform'.
  521. """
  522. if os.name == 'nt':
  523. # sniff sys.version for architecture.
  524. prefix = " bit ("
  525. i = sys.version.find(prefix)
  526. if i == -1:
  527. return sys.platform
  528. j = sys.version.find(")", i)
  529. look = sys.version[i+len(prefix):j].lower()
  530. if look == 'amd64':
  531. return 'win-amd64'
  532. if look == 'itanium':
  533. return 'win-ia64'
  534. return sys.platform
  535. if os.name != "posix" or not hasattr(os, 'uname'):
  536. # XXX what about the architecture? NT is Intel or Alpha,
  537. # Mac OS is M68k or PPC, etc.
  538. return sys.platform
  539. # Try to distinguish various flavours of Unix
  540. osname, host, release, version, machine = os.uname()
  541. # Convert the OS name to lowercase, remove '/' characters
  542. # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
  543. osname = osname.lower().replace('/', '')
  544. machine = machine.replace(' ', '_')
  545. machine = machine.replace('/', '-')
  546. if osname[:5] == "linux":
  547. # At least on Linux/Intel, 'machine' is the processor --
  548. # i386, etc.
  549. # XXX what about Alpha, SPARC, etc?
  550. return "%s-%s" % (osname, machine)
  551. elif osname[:5] == "sunos":
  552. if release[0] >= "5": # SunOS 5 == Solaris 2
  553. osname = "solaris"
  554. release = "%d.%s" % (int(release[0]) - 3, release[2:])
  555. # fall through to standard osname-release-machine representation
  556. elif osname[:4] == "irix": # could be "irix64"!
  557. return "%s-%s" % (osname, release)
  558. elif osname[:3] == "aix":
  559. return "%s-%s.%s" % (osname, version, release)
  560. elif osname[:6] == "cygwin":
  561. osname = "cygwin"
  562. rel_re = re.compile(r'[\d.]+')
  563. m = rel_re.match(release)
  564. if m:
  565. release = m.group()
  566. elif osname[:6] == "darwin":
  567. #
  568. # For our purposes, we'll assume that the system version from
  569. # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
  570. # to. This makes the compatibility story a bit more sane because the
  571. # machine is going to compile and link as if it were
  572. # MACOSX_DEPLOYMENT_TARGET.
  573. cfgvars = get_config_vars()
  574. macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
  575. if True:
  576. # Always calculate the release of the running machine,
  577. # needed to determine if we can build fat binaries or not.
  578. macrelease = macver
  579. # Get the system version. Reading this plist is a documented
  580. # way to get the system version (see the documentation for
  581. # the Gestalt Manager)
  582. try:
  583. f = open('/System/Library/CoreServices/SystemVersion.plist')
  584. except IOError:
  585. # We're on a plain darwin box, fall back to the default
  586. # behaviour.
  587. pass
  588. else:
  589. try:
  590. m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
  591. r'<string>(.*?)</string>', f.read())
  592. finally:
  593. f.close()
  594. if m is not None:
  595. macrelease = '.'.join(m.group(1).split('.')[:2])
  596. # else: fall back to the default behaviour
  597. if not macver:
  598. macver = macrelease
  599. if macver:
  600. release = macver
  601. osname = "macosx"
  602. if ((macrelease + '.') >= '10.4.' and
  603. '-arch' in get_config_vars().get('CFLAGS', '').strip()):
  604. # The universal build will build fat binaries, but not on
  605. # systems before 10.4
  606. #
  607. # Try to detect 4-way universal builds, those have machine-type
  608. # 'universal' instead of 'fat'.
  609. machine = 'fat'
  610. cflags = get_config_vars().get('CFLAGS')
  611. archs = re.findall('-arch\s+(\S+)', cflags)
  612. archs = tuple(sorted(set(archs)))
  613. if len(archs) == 1:
  614. machine = archs[0]
  615. elif archs == ('i386', 'ppc'):
  616. machine = 'fat'
  617. elif archs == ('i386', 'x86_64'):
  618. machine = 'intel'
  619. elif archs == ('i386', 'ppc', 'x86_64'):
  620. machine = 'fat3'
  621. elif archs == ('ppc64', 'x86_64'):
  622. machine = 'fat64'
  623. elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
  624. machine = 'universal'
  625. else:
  626. raise ValueError(
  627. "Don't know machine value for archs=%r" % (archs,))
  628. elif machine == 'i386':
  629. # On OSX the machine type returned by uname is always the
  630. # 32-bit variant, even if the executable architecture is
  631. # the 64-bit variant
  632. if sys.maxsize >= 2**32:
  633. machine = 'x86_64'
  634. elif machine in ('PowerPC', 'Power_Macintosh'):
  635. # Pick a sane name for the PPC architecture.
  636. # See 'i386' case
  637. if sys.maxsize >= 2**32:
  638. machine = 'ppc64'
  639. else:
  640. machine = 'ppc'
  641. return "%s-%s-%s" % (osname, release, machine)
  642. def get_python_version():
  643. return _PY_VERSION_SHORT
  644. def _print_dict(title, data):
  645. for index, (key, value) in enumerate(sorted(data.items())):
  646. if index == 0:
  647. print('%s: ' % (title))
  648. print('\t%s = "%s"' % (key, value))
  649. def _main():
  650. """Display all information sysconfig detains."""
  651. print('Platform: "%s"' % get_platform())
  652. print('Python version: "%s"' % get_python_version())
  653. print('Current installation scheme: "%s"' % _get_default_scheme())
  654. print()
  655. _print_dict('Paths', get_paths())
  656. print()
  657. _print_dict('Variables', get_config_vars())
  658. if __name__ == '__main__':
  659. _main()