Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/distlib/_backport/sysconfig.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:18:57 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d30785e31577 |
---|---|
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() |