blob: d1b5824073327b39b78965ebd2369604d0532e8e [file] [log] [blame]
Tarek Ziade1231a4e2011-05-19 13:07:25 +02001"""Access to Python's configuration information."""
Tarek Ziadéedacea32010-01-29 11:41:03 +00002
Tarek Ziadéedacea32010-01-29 11:41:03 +00003import os
Tarek Ziade1231a4e2011-05-19 13:07:25 +02004import re
5import sys
Florent Xiclunaa4707382010-03-11 00:05:17 +00006from os.path import pardir, realpath
Tarek Ziadéedacea32010-01-29 11:41:03 +00007
Barry Warsawebbef6f2010-09-20 15:29:53 +00008__all__ = [
9 'get_config_h_filename',
10 'get_config_var',
11 'get_config_vars',
12 'get_makefile_filename',
13 'get_path',
14 'get_path_names',
15 'get_paths',
16 'get_platform',
17 'get_python_version',
18 'get_scheme_names',
19 'parse_config_h',
Tarek Ziade1231a4e2011-05-19 13:07:25 +020020]
Tarek Ziadé16ed6cb2010-05-25 09:47:06 +000021
Éric Araujoec177c12012-06-24 03:27:43 -040022_INSTALL_SCHEMES = {
23 'posix_prefix': {
24 'stdlib': '{installed_base}/lib/python{py_version_short}',
25 'platstdlib': '{platbase}/lib/python{py_version_short}',
26 'purelib': '{base}/lib/python{py_version_short}/site-packages',
27 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
28 'include':
29 '{installed_base}/include/python{py_version_short}{abiflags}',
30 'platinclude':
31 '{installed_platbase}/include/python{py_version_short}{abiflags}',
32 'scripts': '{base}/bin',
33 'data': '{base}',
34 },
35 'posix_home': {
36 'stdlib': '{installed_base}/lib/python',
37 'platstdlib': '{base}/lib/python',
38 'purelib': '{base}/lib/python',
39 'platlib': '{base}/lib/python',
40 'include': '{installed_base}/include/python',
41 'platinclude': '{installed_base}/include/python',
42 'scripts': '{base}/bin',
43 'data': '{base}',
44 },
45 'nt': {
46 'stdlib': '{installed_base}/Lib',
47 'platstdlib': '{base}/Lib',
48 'purelib': '{base}/Lib/site-packages',
49 'platlib': '{base}/Lib/site-packages',
50 'include': '{installed_base}/Include',
51 'platinclude': '{installed_base}/Include',
52 'scripts': '{base}/Scripts',
53 'data': '{base}',
54 },
Éric Araujoec177c12012-06-24 03:27:43 -040055 'nt_user': {
56 'stdlib': '{userbase}/Python{py_version_nodot}',
57 'platstdlib': '{userbase}/Python{py_version_nodot}',
58 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
59 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
60 'include': '{userbase}/Python{py_version_nodot}/Include',
61 'scripts': '{userbase}/Scripts',
62 'data': '{userbase}',
63 },
64 'posix_user': {
65 'stdlib': '{userbase}/lib/python{py_version_short}',
66 'platstdlib': '{userbase}/lib/python{py_version_short}',
67 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
68 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
69 'include': '{userbase}/include/python{py_version_short}',
70 'scripts': '{userbase}/bin',
71 'data': '{userbase}',
72 },
73 'osx_framework_user': {
74 'stdlib': '{userbase}/lib/python',
75 'platstdlib': '{userbase}/lib/python',
76 'purelib': '{userbase}/lib/python/site-packages',
77 'platlib': '{userbase}/lib/python/site-packages',
78 'include': '{userbase}/include',
79 'scripts': '{userbase}/bin',
80 'data': '{userbase}',
81 },
82 }
Tarek Ziadéedacea32010-01-29 11:41:03 +000083
Éric Araujoec177c12012-06-24 03:27:43 -040084_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
85 'scripts', 'data')
Tarek Ziade1231a4e2011-05-19 13:07:25 +020086
Vinay Sajip7ded1f02012-05-26 03:45:29 +010087 # FIXME don't rely on sys.version here, its format is an implementation detail
Tarek Ziade1231a4e2011-05-19 13:07:25 +020088 # of CPython, use sys.version_info or sys.hexversion
Tarek Ziadéedacea32010-01-29 11:41:03 +000089_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)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010093_BASE_PREFIX = os.path.normpath(sys.base_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000094_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010095_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000096_CONFIG_VARS = None
97_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +000098
Tarek Ziade1231a4e2011-05-19 13:07:25 +020099
Victor Stinnerb103a932010-10-12 22:23:23 +0000100def _safe_realpath(path):
101 try:
102 return realpath(path)
103 except OSError:
104 return path
105
Victor Stinner171ba052010-03-12 14:20:59 +0000106if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +0000107 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +0000108else:
109 # sys.executable can be empty if argv[0] has been changed and Python is
110 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +0000111 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +0000112
113if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000114 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000115# PC/VS7.1
116if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000117 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000118# PC/AMD64
119if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000120 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000121
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200122# set for cross builds
doko@ubuntu.com7e6c2e22012-06-30 22:35:00 +0200123if "_PYTHON_PROJECT_BASE" in os.environ:
124 _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200125
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100126def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000127 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100128 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000129 return True
130 return False
131
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100132_sys_home = getattr(sys, '_home', None)
Vinay Sajip42211422012-05-26 20:36:12 +0100133if _sys_home and os.name == 'nt' and \
134 _sys_home.lower().endswith(('pcbuild', 'pcbuild\\amd64')):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100135 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7e203492012-05-27 17:30:09 +0100136 if _sys_home.endswith('pcbuild'): # must be amd64
137 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100138def is_python_build(check_home=False):
139 if check_home and _sys_home:
140 return _is_python_source_dir(_sys_home)
141 return _is_python_source_dir(_PROJECT_BASE)
142
143_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000144
145if _PYTHON_BUILD:
146 for scheme in ('posix_prefix', 'posix_home'):
Éric Araujoec177c12012-06-24 03:27:43 -0400147 _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
148 _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000149
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200150
Éric Araujoec177c12012-06-24 03:27:43 -0400151def _subst_vars(s, local_vars):
152 try:
153 return s.format(**local_vars)
154 except KeyError:
155 try:
156 return s.format(**os.environ)
157 except KeyError as var:
158 raise AttributeError('{%s}' % var)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000159
160def _extend_dict(target_dict, other_dict):
161 target_keys = target_dict.keys()
162 for key, value in other_dict.items():
163 if key in target_keys:
164 continue
165 target_dict[key] = value
166
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200167
Tarek Ziadéedacea32010-01-29 11:41:03 +0000168def _expand_vars(scheme, vars):
169 res = {}
170 if vars is None:
171 vars = {}
172 _extend_dict(vars, get_config_vars())
173
Éric Araujoec177c12012-06-24 03:27:43 -0400174 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000175 if os.name in ('posix', 'nt'):
176 value = os.path.expanduser(value)
177 res[key] = os.path.normpath(_subst_vars(value, vars))
178 return res
179
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200180
Tarek Ziadéedacea32010-01-29 11:41:03 +0000181def _get_default_scheme():
182 if os.name == 'posix':
183 # the default scheme for posix is posix_prefix
184 return 'posix_prefix'
185 return os.name
186
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200187
Tarek Ziadéedacea32010-01-29 11:41:03 +0000188def _getuserbase():
189 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200190
Tarek Ziadéedacea32010-01-29 11:41:03 +0000191 def joinuser(*args):
192 return os.path.expanduser(os.path.join(*args))
193
Jesus Cea4791a242012-10-05 03:15:39 +0200194 # what about 'riscos' ?
Tarek Ziadéedacea32010-01-29 11:41:03 +0000195 if os.name == "nt":
196 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200197 if env_base:
198 return env_base
199 else:
200 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000201
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000202 if sys.platform == "darwin":
203 framework = get_config_var("PYTHONFRAMEWORK")
204 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200205 if env_base:
206 return env_base
207 else:
208 return joinuser("~", "Library", framework, "%d.%d" %
209 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000210
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200211 if env_base:
212 return env_base
213 else:
214 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000215
216
217def _parse_makefile(filename, vars=None):
218 """Parse a Makefile-style file.
219
220 A dictionary containing name/value pairs is returned. If an
221 optional dictionary is passed in as the second argument, it is
222 used instead of a new dictionary.
223 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000224 # Regexes needed for parsing Makefile (and similar syntaxes,
225 # like old-style Setup files).
226 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
227 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
228 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
229
230 if vars is None:
231 vars = {}
232 done = {}
233 notdone = {}
234
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000235 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000236 lines = f.readlines()
237
238 for line in lines:
239 if line.startswith('#') or line.strip() == '':
240 continue
241 m = _variable_rx.match(line)
242 if m:
243 n, v = m.group(1, 2)
244 v = v.strip()
245 # `$$' is a literal `$' in make
246 tmpv = v.replace('$$', '')
247
248 if "$" in tmpv:
249 notdone[n] = v
250 else:
251 try:
252 v = int(v)
253 except ValueError:
254 # insert literal `$'
255 done[n] = v.replace('$$', '$')
256 else:
257 done[n] = v
258
259 # do variable interpolation here
260 variables = list(notdone.keys())
261
Ronald Oussorend21886c2010-07-20 16:07:10 +0000262 # Variables with a 'PY_' prefix in the makefile. These need to
263 # be made available without that prefix through sysconfig.
264 # Special care is needed to ensure that variable expansion works, even
265 # if the expansion uses the name without a prefix.
266 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
267
Tarek Ziadéedacea32010-01-29 11:41:03 +0000268 while len(variables) > 0:
269 for name in tuple(variables):
270 value = notdone[name]
271 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
272 if m is not None:
273 n = m.group(1)
274 found = True
275 if n in done:
276 item = str(done[n])
277 elif n in notdone:
278 # get it on a subsequent round
279 found = False
280 elif n in os.environ:
281 # do it like make: fall back to environment
282 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000283
284 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200285 if (name.startswith('PY_') and
286 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000287 item = ""
288
289 elif 'PY_' + n in notdone:
290 found = False
291
292 else:
293 item = str(done['PY_' + n])
294
Tarek Ziadéedacea32010-01-29 11:41:03 +0000295 else:
296 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000297
Tarek Ziadéedacea32010-01-29 11:41:03 +0000298 if found:
299 after = value[m.end():]
300 value = value[:m.start()] + item + after
301 if "$" in after:
302 notdone[name] = value
303 else:
304 try:
305 value = int(value)
306 except ValueError:
307 done[name] = value.strip()
308 else:
309 done[name] = value
310 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000311
312 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200313 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000314
315 name = name[3:]
316 if name not in done:
317 done[name] = value
318
Tarek Ziadéedacea32010-01-29 11:41:03 +0000319 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200320 # bogus variable reference (e.g. "prefix=$/opt/python");
321 # just drop it since we can't deal
322 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000323 variables.remove(name)
324
Antoine Pitroudbec7802010-10-10 09:37:12 +0000325 # strip spurious spaces
326 for k, v in done.items():
327 if isinstance(v, str):
328 done[k] = v.strip()
329
Tarek Ziadéedacea32010-01-29 11:41:03 +0000330 # save the results in the global dictionary
331 vars.update(done)
332 return vars
333
Tarek Ziadéedacea32010-01-29 11:41:03 +0000334
Barry Warsawebbef6f2010-09-20 15:29:53 +0000335def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000336 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000337 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100338 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200339 if hasattr(sys, 'abiflags'):
340 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
341 else:
342 config_dir_name = 'config'
343 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000344
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200345def _generate_posix_vars():
346 """Generate the Python module containing build-time variables."""
347 import pprint
348 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000349 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000350 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000351 try:
352 _parse_makefile(makefile, vars)
353 except IOError as e:
354 msg = "invalid Python installation: unable to open %s" % makefile
355 if hasattr(e, "strerror"):
356 msg = msg + " (%s)" % e.strerror
357 raise IOError(msg)
358 # load the installed pyconfig.h:
359 config_h = get_config_h_filename()
360 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000361 with open(config_h) as f:
362 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000363 except IOError as e:
364 msg = "invalid Python installation: unable to open %s" % config_h
365 if hasattr(e, "strerror"):
366 msg = msg + " (%s)" % e.strerror
367 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000368 # On AIX, there are wrong paths to the linker scripts in the Makefile
369 # -- these paths are relative to the Python source, but when installed
370 # the scripts are in another directory.
371 if _PYTHON_BUILD:
372 vars['LDSHARED'] = vars['BLDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200373
374 destfile = os.path.join(os.path.dirname(__file__), '_sysconfigdata.py')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200375 with open(destfile, 'w', encoding='utf8') as f:
Victor Stinner65651ea2011-10-20 00:41:21 +0200376 f.write('# system configuration generated and used by'
377 ' the sysconfig module\n')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200378 f.write('build_time_vars = ')
379 pprint.pprint(vars, stream=f)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000380
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200381def _init_posix(vars):
382 """Initialize the module as appropriate for POSIX systems."""
383 # _sysconfigdata is generated at build time, see _generate_posix_vars()
384 from _sysconfigdata import build_time_vars
385 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200386
Tarek Ziadéedacea32010-01-29 11:41:03 +0000387def _init_non_posix(vars):
388 """Initialize the module as appropriate for NT"""
389 # set basic install directories
390 vars['LIBDEST'] = get_path('stdlib')
391 vars['BINLIBDEST'] = get_path('platstdlib')
392 vars['INCLUDEPY'] = get_path('include')
393 vars['SO'] = '.pyd'
394 vars['EXE'] = '.exe'
395 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000396 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000397
398#
399# public APIs
400#
401
Tarek Ziadébd797682010-02-02 23:16:13 +0000402
403def parse_config_h(fp, vars=None):
404 """Parse a config.h-style file.
405
406 A dictionary containing name/value pairs is returned. If an
407 optional dictionary is passed in as the second argument, it is
408 used instead of a new dictionary.
409 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000410 if vars is None:
411 vars = {}
412 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
413 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
414
415 while True:
416 line = fp.readline()
417 if not line:
418 break
419 m = define_rx.match(line)
420 if m:
421 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200422 try:
423 v = int(v)
424 except ValueError:
425 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000426 vars[n] = v
427 else:
428 m = undef_rx.match(line)
429 if m:
430 vars[m.group(1)] = 0
431 return vars
432
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200433
Tarek Ziadébd797682010-02-02 23:16:13 +0000434def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000435 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000436 if _PYTHON_BUILD:
437 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100438 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000439 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100440 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000441 else:
442 inc_dir = get_path('platinclude')
443 return os.path.join(inc_dir, 'pyconfig.h')
444
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200445
Tarek Ziadéedacea32010-01-29 11:41:03 +0000446def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000447 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400448 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200449
Tarek Ziadéedacea32010-01-29 11:41:03 +0000450
451def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000452 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400453 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200454
Tarek Ziadéedacea32010-01-29 11:41:03 +0000455
456def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000457 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000458
459 ``scheme`` is the install scheme name. If not provided, it will
460 return the default scheme for the current platform.
461 """
462 if expand:
463 return _expand_vars(scheme, vars)
464 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400465 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200466
Tarek Ziadéedacea32010-01-29 11:41:03 +0000467
468def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000469 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000470
471 ``scheme`` is the install scheme name.
472 """
473 return get_paths(scheme, vars, expand)[name]
474
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200475
Tarek Ziadéedacea32010-01-29 11:41:03 +0000476def get_config_vars(*args):
477 """With no arguments, return a dictionary of all configuration
478 variables relevant for the current platform.
479
480 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700481 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000482
483 With arguments, return a list of values that result from looking up
484 each argument in the configuration variable dictionary.
485 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000486 global _CONFIG_VARS
487 if _CONFIG_VARS is None:
488 _CONFIG_VARS = {}
489 # Normalized versions of prefix and exec_prefix are handy to have;
490 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400491 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000492 _CONFIG_VARS['prefix'] = _PREFIX
493 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
494 _CONFIG_VARS['py_version'] = _PY_VERSION
495 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
496 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100497 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000498 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100499 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000500 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000501 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000502 try:
503 _CONFIG_VARS['abiflags'] = sys.abiflags
504 except AttributeError:
505 # sys.abiflags may not be defined on all platforms.
506 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000507
Jesus Cea4791a242012-10-05 03:15:39 +0200508 if os.name == 'nt':
Tarek Ziadéedacea32010-01-29 11:41:03 +0000509 _init_non_posix(_CONFIG_VARS)
510 if os.name == 'posix':
511 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000512 # Setting 'userbase' is done below the call to the
513 # init function to enable using 'get_config_var' in
514 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100515 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000516
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100517 # Always convert srcdir to an absolute path
518 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
519 if os.name == 'posix':
520 if _PYTHON_BUILD:
521 # If srcdir is a relative path (typically '.' or '..')
522 # then it should be interpreted relative to the directory
523 # containing Makefile.
524 base = os.path.dirname(get_makefile_filename())
525 srcdir = os.path.join(base, srcdir)
526 else:
527 # srcdir is not meaningful since the installation is
528 # spread about the filesystem. We choose the
529 # directory containing the Makefile since we know it
530 # exists.
531 srcdir = os.path.dirname(get_makefile_filename())
532 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000533
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700534 # OS X platforms require special customization to handle
535 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000536 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700537 import _osx_support
538 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000539
540 if args:
541 vals = []
542 for name in args:
543 vals.append(_CONFIG_VARS.get(name))
544 return vals
545 else:
546 return _CONFIG_VARS
547
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200548
Tarek Ziadéedacea32010-01-29 11:41:03 +0000549def get_config_var(name):
550 """Return the value of a single variable using the dictionary returned by
551 'get_config_vars()'.
552
553 Equivalent to get_config_vars().get(name)
554 """
555 return get_config_vars().get(name)
556
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200557
Tarek Ziadéedacea32010-01-29 11:41:03 +0000558def get_platform():
559 """Return a string that identifies the current platform.
560
561 This is used mainly to distinguish platform-specific build directories and
562 platform-specific built distributions. Typically includes the OS name
563 and version and the architecture (as supplied by 'os.uname()'),
564 although the exact information included depends on the OS; eg. for IRIX
565 the architecture isn't particularly important (IRIX only runs on SGI
566 hardware), but for Linux the kernel version isn't particularly
567 important.
568
569 Examples of returned values:
570 linux-i586
571 linux-alpha (?)
572 solaris-2.6-sun4u
573 irix-5.3
574 irix64-6.2
575
576 Windows will return one of:
577 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
578 win-ia64 (64bit Windows on Itanium)
579 win32 (all others - specifically, sys.platform is returned)
580
581 For other non-POSIX platforms, currently just returns 'sys.platform'.
582 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000583 if os.name == 'nt':
584 # sniff sys.version for architecture.
585 prefix = " bit ("
586 i = sys.version.find(prefix)
587 if i == -1:
588 return sys.platform
589 j = sys.version.find(")", i)
590 look = sys.version[i+len(prefix):j].lower()
591 if look == 'amd64':
592 return 'win-amd64'
593 if look == 'itanium':
594 return 'win-ia64'
595 return sys.platform
596
597 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700598 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000599 return sys.platform
600
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200601 # Set for cross builds explicitly
602 if "_PYTHON_HOST_PLATFORM" in os.environ:
603 return os.environ["_PYTHON_HOST_PLATFORM"]
604
Tarek Ziadéedacea32010-01-29 11:41:03 +0000605 # Try to distinguish various flavours of Unix
606 osname, host, release, version, machine = os.uname()
607
608 # Convert the OS name to lowercase, remove '/' characters
609 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
610 osname = osname.lower().replace('/', '')
611 machine = machine.replace(' ', '_')
612 machine = machine.replace('/', '-')
613
614 if osname[:5] == "linux":
615 # At least on Linux/Intel, 'machine' is the processor --
616 # i386, etc.
617 # XXX what about Alpha, SPARC, etc?
618 return "%s-%s" % (osname, machine)
619 elif osname[:5] == "sunos":
620 if release[0] >= "5": # SunOS 5 == Solaris 2
621 osname = "solaris"
622 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100623 # We can't use "platform.architecture()[0]" because a
624 # bootstrap problem. We use a dict to get an error
625 # if some suspicious happens.
626 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100627 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000628 # fall through to standard osname-release-machine representation
629 elif osname[:4] == "irix": # could be "irix64"!
630 return "%s-%s" % (osname, release)
631 elif osname[:3] == "aix":
632 return "%s-%s.%s" % (osname, version, release)
633 elif osname[:6] == "cygwin":
634 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200635 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000636 m = rel_re.match(release)
637 if m:
638 release = m.group()
639 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700640 import _osx_support
641 osname, release, machine = _osx_support.get_platform_osx(
642 get_config_vars(),
643 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000644
645 return "%s-%s-%s" % (osname, release, machine)
646
647
648def get_python_version():
649 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000650
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200651
Tarek Ziadéa7514992010-05-25 09:44:36 +0000652def _print_dict(title, data):
653 for index, (key, value) in enumerate(sorted(data.items())):
654 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200655 print('%s: ' % (title))
656 print('\t%s = "%s"' % (key, value))
657
Tarek Ziadéa7514992010-05-25 09:44:36 +0000658
659def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000660 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200661 if '--generate-posix-vars' in sys.argv:
662 _generate_posix_vars()
663 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200664 print('Platform: "%s"' % get_platform())
665 print('Python version: "%s"' % get_python_version())
666 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200667 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000668 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200669 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000670 _print_dict('Variables', get_config_vars())
671
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200672
Tarek Ziadéa7514992010-05-25 09:44:36 +0000673if __name__ == '__main__':
674 _main()