blob: 9c8350d953db34436197e03e4187750f9ab521c6 [file] [log] [blame]
Tarek Ziadé5633a802010-01-23 09:23:15 +00001"""Provide access to Python's configuration information.
2
3"""
4import sys
5import os
Florent Xicluna85677612010-03-10 23:58:42 +00006from os.path import pardir, realpath
Tarek Ziadé5633a802010-01-23 09:23:15 +00007
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': {
Tarek Ziadé8f692272010-05-19 22:20:14 +000050 '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',
Tarek Ziadé5633a802010-01-23 09:23:15 +000054 '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': {
Tarek Ziadé8f692272010-05-19 22:20:14 +000068 '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',
Tarek Ziadé5633a802010-01-23 09:23:15 +000072 'include': '{userbase}/include/python{py_version_short}',
73 'scripts': '{userbase}/bin',
74 'data' : '{userbase}',
75 },
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +000076 '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 },
Tarek Ziadé5633a802010-01-23 09:23:15 +000085 }
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
Victor Stinnerd2f6ae62010-10-12 22:53:51 +000096
97def _safe_realpath(path):
98 try:
99 return realpath(path)
100 except OSError:
101 return path
102
Victor Stinner4a7e0c852010-03-11 12:34:39 +0000103if sys.executable:
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000104 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner4a7e0c852010-03-11 12:34:39 +0000105else:
106 # sys.executable can be empty if argv[0] has been changed and Python is
107 # unable to retrieve the real program name
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000108 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadé5633a802010-01-23 09:23:15 +0000109
110if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000111 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000112# PC/VS7.1
113if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000114 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Victor Stinnerf2e894c2017-05-12 11:31:08 +0200115# PC/VS9.0/amd64
116if (os.name == "nt"
117 and os.path.basename(os.path.dirname(os.path.dirname(_PROJECT_BASE))).lower() == "pc"
118 and os.path.basename(os.path.dirname(_PROJECT_BASE)).lower() == "vs9.0"):
119 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000120# PC/AMD64
121if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000122 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000123
doko@python.orgd65e2ba2013-01-31 23:52:03 +0100124# set for cross builds
125if "_PYTHON_PROJECT_BASE" in os.environ:
126 # the build directory for posix builds
127 _PROJECT_BASE = os.path.normpath(os.path.abspath("."))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000128def is_python_build():
129 for fn in ("Setup.dist", "Setup.local"):
130 if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
131 return True
132 return False
133
134_PYTHON_BUILD = is_python_build()
135
136if _PYTHON_BUILD:
137 for scheme in ('posix_prefix', 'posix_home'):
138 _INSTALL_SCHEMES[scheme]['include'] = '{projectbase}/Include'
139 _INSTALL_SCHEMES[scheme]['platinclude'] = '{srcdir}'
140
141def _subst_vars(s, local_vars):
142 try:
143 return s.format(**local_vars)
144 except KeyError:
145 try:
146 return s.format(**os.environ)
147 except KeyError, var:
148 raise AttributeError('{%s}' % var)
149
150def _extend_dict(target_dict, other_dict):
151 target_keys = target_dict.keys()
152 for key, value in other_dict.items():
153 if key in target_keys:
154 continue
155 target_dict[key] = value
156
157def _expand_vars(scheme, vars):
158 res = {}
159 if vars is None:
160 vars = {}
161 _extend_dict(vars, get_config_vars())
162
163 for key, value in _INSTALL_SCHEMES[scheme].items():
164 if os.name in ('posix', 'nt'):
165 value = os.path.expanduser(value)
166 res[key] = os.path.normpath(_subst_vars(value, vars))
167 return res
168
169def _get_default_scheme():
170 if os.name == 'posix':
171 # the default scheme for posix is posix_prefix
172 return 'posix_prefix'
173 return os.name
174
175def _getuserbase():
176 env_base = os.environ.get("PYTHONUSERBASE", None)
177 def joinuser(*args):
178 return os.path.expanduser(os.path.join(*args))
179
180 # what about 'os2emx', 'riscos' ?
181 if os.name == "nt":
182 base = os.environ.get("APPDATA") or "~"
183 return env_base if env_base else joinuser(base, "Python")
184
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +0000185 if sys.platform == "darwin":
186 framework = get_config_var("PYTHONFRAMEWORK")
187 if framework:
Ned Deily2c8bf042012-02-06 00:55:50 +0100188 return env_base if env_base else \
189 joinuser("~", "Library", framework, "%d.%d"
190 % (sys.version_info[:2]))
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +0000191
Tarek Ziadé5633a802010-01-23 09:23:15 +0000192 return env_base if env_base else joinuser("~", ".local")
193
194
195def _parse_makefile(filename, vars=None):
196 """Parse a Makefile-style file.
197
198 A dictionary containing name/value pairs is returned. If an
199 optional dictionary is passed in as the second argument, it is
200 used instead of a new dictionary.
201 """
202 import re
203 # Regexes needed for parsing Makefile (and similar syntaxes,
204 # like old-style Setup files).
205 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
206 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
207 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
208
209 if vars is None:
210 vars = {}
211 done = {}
212 notdone = {}
213
214 with open(filename) as f:
215 lines = f.readlines()
216
217 for line in lines:
218 if line.startswith('#') or line.strip() == '':
219 continue
220 m = _variable_rx.match(line)
221 if m:
222 n, v = m.group(1, 2)
223 v = v.strip()
224 # `$$' is a literal `$' in make
225 tmpv = v.replace('$$', '')
226
227 if "$" in tmpv:
228 notdone[n] = v
229 else:
230 try:
231 v = int(v)
232 except ValueError:
233 # insert literal `$'
234 done[n] = v.replace('$$', '$')
235 else:
236 done[n] = v
237
238 # do variable interpolation here
239 while notdone:
240 for name in notdone.keys():
241 value = notdone[name]
242 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
243 if m:
244 n = m.group(1)
245 found = True
246 if n in done:
247 item = str(done[n])
248 elif n in notdone:
249 # get it on a subsequent round
250 found = False
251 elif n in os.environ:
252 # do it like make: fall back to environment
253 item = os.environ[n]
254 else:
255 done[n] = item = ""
256 if found:
257 after = value[m.end():]
258 value = value[:m.start()] + item + after
259 if "$" in after:
260 notdone[name] = value
261 else:
262 try: value = int(value)
263 except ValueError:
264 done[name] = value.strip()
265 else:
266 done[name] = value
267 del notdone[name]
268 else:
269 # bogus variable reference; just drop it since we can't deal
270 del notdone[name]
Antoine Pitrou58dab672010-10-10 09:54:59 +0000271 # strip spurious spaces
272 for k, v in done.items():
273 if isinstance(v, str):
274 done[k] = v.strip()
275
Tarek Ziadé5633a802010-01-23 09:23:15 +0000276 # save the results in the global dictionary
277 vars.update(done)
278 return vars
279
Tarek Ziadé5633a802010-01-23 09:23:15 +0000280
Ned Deily9d6488a2014-08-22 13:48:06 -0700281def get_makefile_filename():
282 """Return the path of the Makefile."""
Tarek Ziadé5633a802010-01-23 09:23:15 +0000283 if _PYTHON_BUILD:
284 return os.path.join(_PROJECT_BASE, "Makefile")
Barry Warsaw42bb7ca2011-02-14 20:04:00 +0000285 return os.path.join(get_path('platstdlib'), "config", "Makefile")
Tarek Ziadé5633a802010-01-23 09:23:15 +0000286
Ned Deily9d6488a2014-08-22 13:48:06 -0700287# Issue #22199: retain undocumented private name for compatibility
288_get_makefile_filename = get_makefile_filename
289
doko@ubuntu.com6cb43432013-04-08 21:20:09 +0200290def _generate_posix_vars():
291 """Generate the Python module containing build-time variables."""
292 import pprint
293 vars = {}
Tarek Ziadé5633a802010-01-23 09:23:15 +0000294 # load the installed Makefile:
Ned Deily9d6488a2014-08-22 13:48:06 -0700295 makefile = get_makefile_filename()
Tarek Ziadé5633a802010-01-23 09:23:15 +0000296 try:
297 _parse_makefile(makefile, vars)
298 except IOError, e:
299 msg = "invalid Python installation: unable to open %s" % makefile
300 if hasattr(e, "strerror"):
301 msg = msg + " (%s)" % e.strerror
302 raise IOError(msg)
303
304 # load the installed pyconfig.h:
305 config_h = get_config_h_filename()
306 try:
Antoine Pitrouf7c24452010-10-14 21:22:52 +0000307 with open(config_h) as f:
308 parse_config_h(f, vars)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000309 except IOError, e:
310 msg = "invalid Python installation: unable to open %s" % config_h
311 if hasattr(e, "strerror"):
312 msg = msg + " (%s)" % e.strerror
313 raise IOError(msg)
314
Tarek Ziadé5633a802010-01-23 09:23:15 +0000315 # On AIX, there are wrong paths to the linker scripts in the Makefile
316 # -- these paths are relative to the Python source, but when installed
317 # the scripts are in another directory.
318 if _PYTHON_BUILD:
319 vars['LDSHARED'] = vars['BLDSHARED']
320
doko@ubuntu.com6cb43432013-04-08 21:20:09 +0200321 # There's a chicken-and-egg situation on OS X with regards to the
322 # _sysconfigdata module after the changes introduced by #15298:
323 # get_config_vars() is called by get_platform() as part of the
324 # `make pybuilddir.txt` target -- which is a precursor to the
325 # _sysconfigdata.py module being constructed. Unfortunately,
326 # get_config_vars() eventually calls _init_posix(), which attempts
327 # to import _sysconfigdata, which we won't have built yet. In order
328 # for _init_posix() to work, if we're on Darwin, just mock up the
329 # _sysconfigdata module manually and populate it with the build vars.
330 # This is more than sufficient for ensuring the subsequent call to
331 # get_platform() succeeds.
332 name = '_sysconfigdata'
333 if 'darwin' in sys.platform:
334 import imp
335 module = imp.new_module(name)
336 module.build_time_vars = vars
337 sys.modules[name] = module
338
339 pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version[:3])
340 if hasattr(sys, "gettotalrefcount"):
341 pybuilddir += '-pydebug'
342 try:
343 os.makedirs(pybuilddir)
344 except OSError:
345 pass
346 destfile = os.path.join(pybuilddir, name + '.py')
347
348 with open(destfile, 'wb') as f:
349 f.write('# system configuration generated and used by'
350 ' the sysconfig module\n')
351 f.write('build_time_vars = ')
352 pprint.pprint(vars, stream=f)
353
354 # Create file used for sys.path fixup -- see Modules/getpath.c
355 with open('pybuilddir.txt', 'w') as f:
356 f.write(pybuilddir)
357
358def _init_posix(vars):
359 """Initialize the module as appropriate for POSIX systems."""
360 # _sysconfigdata is generated at build time, see _generate_posix_vars()
361 from _sysconfigdata import build_time_vars
362 vars.update(build_time_vars)
363
Tarek Ziadé5633a802010-01-23 09:23:15 +0000364def _init_non_posix(vars):
365 """Initialize the module as appropriate for NT"""
366 # set basic install directories
367 vars['LIBDEST'] = get_path('stdlib')
368 vars['BINLIBDEST'] = get_path('platstdlib')
369 vars['INCLUDEPY'] = get_path('include')
370 vars['SO'] = '.pyd'
371 vars['EXE'] = '.exe'
372 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000373 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000374
375#
376# public APIs
377#
378
Tarek Ziadécc118172010-02-02 22:50:23 +0000379
380def parse_config_h(fp, vars=None):
381 """Parse a config.h-style file.
382
383 A dictionary containing name/value pairs is returned. If an
384 optional dictionary is passed in as the second argument, it is
385 used instead of a new dictionary.
386 """
387 import re
388 if vars is None:
389 vars = {}
390 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
391 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
392
393 while True:
394 line = fp.readline()
395 if not line:
396 break
397 m = define_rx.match(line)
398 if m:
399 n, v = m.group(1, 2)
400 try: v = int(v)
401 except ValueError: pass
402 vars[n] = v
403 else:
404 m = undef_rx.match(line)
405 if m:
406 vars[m.group(1)] = 0
407 return vars
408
409def get_config_h_filename():
410 """Returns the path of pyconfig.h."""
411 if _PYTHON_BUILD:
412 if os.name == "nt":
413 inc_dir = os.path.join(_PROJECT_BASE, "PC")
414 else:
415 inc_dir = _PROJECT_BASE
416 else:
417 inc_dir = get_path('platinclude')
418 return os.path.join(inc_dir, 'pyconfig.h')
419
Tarek Ziadé5633a802010-01-23 09:23:15 +0000420def get_scheme_names():
Tarek Ziadécc118172010-02-02 22:50:23 +0000421 """Returns a tuple containing the schemes names."""
Tarek Ziadée81b0282010-02-02 22:54:28 +0000422 schemes = _INSTALL_SCHEMES.keys()
423 schemes.sort()
424 return tuple(schemes)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000425
426def get_path_names():
Tarek Ziadécc118172010-02-02 22:50:23 +0000427 """Returns a tuple containing the paths names."""
Tarek Ziadé5633a802010-01-23 09:23:15 +0000428 return _SCHEME_KEYS
429
430def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
431 """Returns a mapping containing an install scheme.
432
433 ``scheme`` is the install scheme name. If not provided, it will
434 return the default scheme for the current platform.
435 """
436 if expand:
437 return _expand_vars(scheme, vars)
438 else:
439 return _INSTALL_SCHEMES[scheme]
440
441def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
442 """Returns a path corresponding to the scheme.
443
444 ``scheme`` is the install scheme name.
445 """
446 return get_paths(scheme, vars, expand)[name]
447
448def get_config_vars(*args):
449 """With no arguments, return a dictionary of all configuration
450 variables relevant for the current platform.
451
452 On Unix, this means every variable defined in Python's installed Makefile;
453 On Windows and Mac OS it's a much smaller set.
454
455 With arguments, return a list of values that result from looking up
456 each argument in the configuration variable dictionary.
457 """
458 import re
459 global _CONFIG_VARS
460 if _CONFIG_VARS is None:
461 _CONFIG_VARS = {}
462 # Normalized versions of prefix and exec_prefix are handy to have;
463 # in fact, these are the standard versions used most places in the
464 # Distutils.
465 _CONFIG_VARS['prefix'] = _PREFIX
466 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
467 _CONFIG_VARS['py_version'] = _PY_VERSION
468 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
469 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
470 _CONFIG_VARS['base'] = _PREFIX
471 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadé5633a802010-01-23 09:23:15 +0000472 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
473
474 if os.name in ('nt', 'os2'):
475 _init_non_posix(_CONFIG_VARS)
476 if os.name == 'posix':
477 _init_posix(_CONFIG_VARS)
478
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +0000479 # Setting 'userbase' is done below the call to the
480 # init function to enable using 'get_config_var' in
481 # the init-function.
482 _CONFIG_VARS['userbase'] = _getuserbase()
483
Tarek Ziadé5633a802010-01-23 09:23:15 +0000484 if 'srcdir' not in _CONFIG_VARS:
485 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
486
487 # Convert srcdir into an absolute path if it appears necessary.
488 # Normally it is relative to the build directory. However, during
489 # testing, for example, we might be running a non-installed python
490 # from a different directory.
491 if _PYTHON_BUILD and os.name == "posix":
492 base = _PROJECT_BASE
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000493 try:
494 cwd = os.getcwd()
495 except OSError:
496 cwd = None
Tarek Ziadé5633a802010-01-23 09:23:15 +0000497 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000498 base != cwd):
Tarek Ziadé5633a802010-01-23 09:23:15 +0000499 # srcdir is relative and we are not in the same directory
500 # as the executable. Assume executable is in the build
501 # directory and make srcdir absolute.
502 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
503 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
504
Ned Deily18fae3f2013-01-31 01:24:55 -0800505 # OS X platforms require special customization to handle
506 # multi-architecture, multi-os-version installers
Tarek Ziadé5633a802010-01-23 09:23:15 +0000507 if sys.platform == 'darwin':
Ned Deily18fae3f2013-01-31 01:24:55 -0800508 import _osx_support
509 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000510
511 if args:
512 vals = []
513 for name in args:
514 vals.append(_CONFIG_VARS.get(name))
515 return vals
516 else:
517 return _CONFIG_VARS
518
519def get_config_var(name):
520 """Return the value of a single variable using the dictionary returned by
521 'get_config_vars()'.
522
523 Equivalent to get_config_vars().get(name)
524 """
525 return get_config_vars().get(name)
526
527def get_platform():
528 """Return a string that identifies the current platform.
529
530 This is used mainly to distinguish platform-specific build directories and
531 platform-specific built distributions. Typically includes the OS name
532 and version and the architecture (as supplied by 'os.uname()'),
533 although the exact information included depends on the OS; eg. for IRIX
534 the architecture isn't particularly important (IRIX only runs on SGI
535 hardware), but for Linux the kernel version isn't particularly
536 important.
537
538 Examples of returned values:
539 linux-i586
540 linux-alpha (?)
541 solaris-2.6-sun4u
542 irix-5.3
543 irix64-6.2
544
545 Windows will return one of:
546 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
547 win-ia64 (64bit Windows on Itanium)
548 win32 (all others - specifically, sys.platform is returned)
549
550 For other non-POSIX platforms, currently just returns 'sys.platform'.
551 """
552 import re
553 if os.name == 'nt':
554 # sniff sys.version for architecture.
555 prefix = " bit ("
556 i = sys.version.find(prefix)
557 if i == -1:
558 return sys.platform
559 j = sys.version.find(")", i)
560 look = sys.version[i+len(prefix):j].lower()
561 if look == 'amd64':
562 return 'win-amd64'
563 if look == 'itanium':
564 return 'win-ia64'
565 return sys.platform
566
doko@python.orgd65e2ba2013-01-31 23:52:03 +0100567 # Set for cross builds explicitly
568 if "_PYTHON_HOST_PLATFORM" in os.environ:
569 return os.environ["_PYTHON_HOST_PLATFORM"]
570
Tarek Ziadé5633a802010-01-23 09:23:15 +0000571 if os.name != "posix" or not hasattr(os, 'uname'):
572 # XXX what about the architecture? NT is Intel or Alpha,
573 # Mac OS is M68k or PPC, etc.
574 return sys.platform
575
576 # Try to distinguish various flavours of Unix
577 osname, host, release, version, machine = os.uname()
578
579 # Convert the OS name to lowercase, remove '/' characters
580 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
581 osname = osname.lower().replace('/', '')
582 machine = machine.replace(' ', '_')
583 machine = machine.replace('/', '-')
584
585 if osname[:5] == "linux":
586 # At least on Linux/Intel, 'machine' is the processor --
587 # i386, etc.
588 # XXX what about Alpha, SPARC, etc?
589 return "%s-%s" % (osname, machine)
590 elif osname[:5] == "sunos":
591 if release[0] >= "5": # SunOS 5 == Solaris 2
592 osname = "solaris"
593 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Ceaa8f75da2012-01-18 04:43:50 +0100594 # We can't use "platform.architecture()[0]" because a
595 # bootstrap problem. We use a dict to get an error
596 # if some suspicious happens.
597 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
598 machine += ".%s" % bitness[sys.maxint]
Tarek Ziadé5633a802010-01-23 09:23:15 +0000599 # fall through to standard osname-release-machine representation
600 elif osname[:4] == "irix": # could be "irix64"!
601 return "%s-%s" % (osname, release)
602 elif osname[:3] == "aix":
603 return "%s-%s.%s" % (osname, version, release)
604 elif osname[:6] == "cygwin":
605 osname = "cygwin"
606 rel_re = re.compile (r'[\d.]+')
607 m = rel_re.match(release)
608 if m:
609 release = m.group()
610 elif osname[:6] == "darwin":
Ned Deily18fae3f2013-01-31 01:24:55 -0800611 import _osx_support
612 osname, release, machine = _osx_support.get_platform_osx(
613 get_config_vars(),
614 osname, release, machine)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000615
616 return "%s-%s-%s" % (osname, release, machine)
617
618
619def get_python_version():
620 return _PY_VERSION_SHORT
doko@ubuntu.com6cb43432013-04-08 21:20:09 +0200621
622
623def _print_dict(title, data):
624 for index, (key, value) in enumerate(sorted(data.items())):
625 if index == 0:
626 print '%s: ' % (title)
627 print '\t%s = "%s"' % (key, value)
628
629
630def _main():
631 """Display all information sysconfig detains."""
632 if '--generate-posix-vars' in sys.argv:
633 _generate_posix_vars()
634 return
635 print 'Platform: "%s"' % get_platform()
636 print 'Python version: "%s"' % get_python_version()
637 print 'Current installation scheme: "%s"' % _get_default_scheme()
638 print
639 _print_dict('Paths', get_paths())
640 print
641 _print_dict('Variables', get_config_vars())
642
643
644if __name__ == '__main__':
645 _main()