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