comparison env/lib/python3.9/site-packages/distlib/_backport/sysconfig.py @ 0:4f3585e2f14b draft default tip

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