blob: ba4024fe8898045ce02cfd83193ea83c2712004a [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 },
55 'os2': {
56 'stdlib': '{installed_base}/Lib',
57 'platstdlib': '{base}/Lib',
58 'purelib': '{base}/Lib/site-packages',
59 'platlib': '{base}/Lib/site-packages',
60 'include': '{installed_base}/Include',
61 'platinclude': '{installed_base}/Include',
62 'scripts': '{base}/Scripts',
63 'data': '{base}',
64 },
65 'os2_home': {
66 'stdlib': '{userbase}/lib/python{py_version_short}',
67 'platstdlib': '{userbase}/lib/python{py_version_short}',
68 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
69 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
70 'include': '{userbase}/include/python{py_version_short}',
71 'scripts': '{userbase}/bin',
72 'data': '{userbase}',
73 },
74 'nt_user': {
75 'stdlib': '{userbase}/Python{py_version_nodot}',
76 'platstdlib': '{userbase}/Python{py_version_nodot}',
77 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
78 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
79 'include': '{userbase}/Python{py_version_nodot}/Include',
80 'scripts': '{userbase}/Scripts',
81 'data': '{userbase}',
82 },
83 'posix_user': {
84 'stdlib': '{userbase}/lib/python{py_version_short}',
85 'platstdlib': '{userbase}/lib/python{py_version_short}',
86 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
87 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
88 'include': '{userbase}/include/python{py_version_short}',
89 'scripts': '{userbase}/bin',
90 'data': '{userbase}',
91 },
92 'osx_framework_user': {
93 'stdlib': '{userbase}/lib/python',
94 'platstdlib': '{userbase}/lib/python',
95 'purelib': '{userbase}/lib/python/site-packages',
96 'platlib': '{userbase}/lib/python/site-packages',
97 'include': '{userbase}/include',
98 'scripts': '{userbase}/bin',
99 'data': '{userbase}',
100 },
101 }
Tarek Ziadéedacea32010-01-29 11:41:03 +0000102
Éric Araujoec177c12012-06-24 03:27:43 -0400103_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
104 'scripts', 'data')
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200105
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100106 # FIXME don't rely on sys.version here, its format is an implementation detail
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200107 # of CPython, use sys.version_info or sys.hexversion
Tarek Ziadéedacea32010-01-29 11:41:03 +0000108_PY_VERSION = sys.version.split()[0]
109_PY_VERSION_SHORT = sys.version[:3]
110_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
111_PREFIX = os.path.normpath(sys.prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100112_BASE_PREFIX = os.path.normpath(sys.base_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000113_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100114_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000115_CONFIG_VARS = None
116_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +0000117
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200118
Victor Stinnerb103a932010-10-12 22:23:23 +0000119def _safe_realpath(path):
120 try:
121 return realpath(path)
122 except OSError:
123 return path
124
Victor Stinner171ba052010-03-12 14:20:59 +0000125if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +0000126 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +0000127else:
128 # sys.executable can be empty if argv[0] has been changed and Python is
129 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +0000130 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +0000131
132if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000133 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000134# PC/VS7.1
135if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000136 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000137# PC/AMD64
138if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000139 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000140
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200141# set for cross builds
doko@ubuntu.com7e6c2e22012-06-30 22:35:00 +0200142if "_PYTHON_PROJECT_BASE" in os.environ:
143 _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200144
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100145def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000146 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100147 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000148 return True
149 return False
150
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100151_sys_home = getattr(sys, '_home', None)
Vinay Sajip42211422012-05-26 20:36:12 +0100152if _sys_home and os.name == 'nt' and \
153 _sys_home.lower().endswith(('pcbuild', 'pcbuild\\amd64')):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100154 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7e203492012-05-27 17:30:09 +0100155 if _sys_home.endswith('pcbuild'): # must be amd64
156 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100157def is_python_build(check_home=False):
158 if check_home and _sys_home:
159 return _is_python_source_dir(_sys_home)
160 return _is_python_source_dir(_PROJECT_BASE)
161
162_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000163
164if _PYTHON_BUILD:
165 for scheme in ('posix_prefix', 'posix_home'):
Éric Araujoec177c12012-06-24 03:27:43 -0400166 _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
167 _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000168
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200169
Éric Araujoec177c12012-06-24 03:27:43 -0400170def _subst_vars(s, local_vars):
171 try:
172 return s.format(**local_vars)
173 except KeyError:
174 try:
175 return s.format(**os.environ)
176 except KeyError as var:
177 raise AttributeError('{%s}' % var)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000178
179def _extend_dict(target_dict, other_dict):
180 target_keys = target_dict.keys()
181 for key, value in other_dict.items():
182 if key in target_keys:
183 continue
184 target_dict[key] = value
185
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200186
Tarek Ziadéedacea32010-01-29 11:41:03 +0000187def _expand_vars(scheme, vars):
188 res = {}
189 if vars is None:
190 vars = {}
191 _extend_dict(vars, get_config_vars())
192
Éric Araujoec177c12012-06-24 03:27:43 -0400193 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000194 if os.name in ('posix', 'nt'):
195 value = os.path.expanduser(value)
196 res[key] = os.path.normpath(_subst_vars(value, vars))
197 return res
198
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200199
Tarek Ziadéedacea32010-01-29 11:41:03 +0000200def _get_default_scheme():
201 if os.name == 'posix':
202 # the default scheme for posix is posix_prefix
203 return 'posix_prefix'
204 return os.name
205
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200206
Tarek Ziadéedacea32010-01-29 11:41:03 +0000207def _getuserbase():
208 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200209
Tarek Ziadéedacea32010-01-29 11:41:03 +0000210 def joinuser(*args):
211 return os.path.expanduser(os.path.join(*args))
212
213 # what about 'os2emx', 'riscos' ?
214 if os.name == "nt":
215 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200216 if env_base:
217 return env_base
218 else:
219 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000220
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000221 if sys.platform == "darwin":
222 framework = get_config_var("PYTHONFRAMEWORK")
223 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200224 if env_base:
225 return env_base
226 else:
227 return joinuser("~", "Library", framework, "%d.%d" %
228 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000229
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200230 if env_base:
231 return env_base
232 else:
233 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000234
235
236def _parse_makefile(filename, vars=None):
237 """Parse a Makefile-style file.
238
239 A dictionary containing name/value pairs is returned. If an
240 optional dictionary is passed in as the second argument, it is
241 used instead of a new dictionary.
242 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000243 # Regexes needed for parsing Makefile (and similar syntaxes,
244 # like old-style Setup files).
245 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
246 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
247 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
248
249 if vars is None:
250 vars = {}
251 done = {}
252 notdone = {}
253
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000254 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000255 lines = f.readlines()
256
257 for line in lines:
258 if line.startswith('#') or line.strip() == '':
259 continue
260 m = _variable_rx.match(line)
261 if m:
262 n, v = m.group(1, 2)
263 v = v.strip()
264 # `$$' is a literal `$' in make
265 tmpv = v.replace('$$', '')
266
267 if "$" in tmpv:
268 notdone[n] = v
269 else:
270 try:
271 v = int(v)
272 except ValueError:
273 # insert literal `$'
274 done[n] = v.replace('$$', '$')
275 else:
276 done[n] = v
277
278 # do variable interpolation here
279 variables = list(notdone.keys())
280
Ronald Oussorend21886c2010-07-20 16:07:10 +0000281 # Variables with a 'PY_' prefix in the makefile. These need to
282 # be made available without that prefix through sysconfig.
283 # Special care is needed to ensure that variable expansion works, even
284 # if the expansion uses the name without a prefix.
285 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
286
Tarek Ziadéedacea32010-01-29 11:41:03 +0000287 while len(variables) > 0:
288 for name in tuple(variables):
289 value = notdone[name]
290 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
291 if m is not None:
292 n = m.group(1)
293 found = True
294 if n in done:
295 item = str(done[n])
296 elif n in notdone:
297 # get it on a subsequent round
298 found = False
299 elif n in os.environ:
300 # do it like make: fall back to environment
301 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000302
303 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200304 if (name.startswith('PY_') and
305 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000306 item = ""
307
308 elif 'PY_' + n in notdone:
309 found = False
310
311 else:
312 item = str(done['PY_' + n])
313
Tarek Ziadéedacea32010-01-29 11:41:03 +0000314 else:
315 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000316
Tarek Ziadéedacea32010-01-29 11:41:03 +0000317 if found:
318 after = value[m.end():]
319 value = value[:m.start()] + item + after
320 if "$" in after:
321 notdone[name] = value
322 else:
323 try:
324 value = int(value)
325 except ValueError:
326 done[name] = value.strip()
327 else:
328 done[name] = value
329 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000330
331 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200332 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000333
334 name = name[3:]
335 if name not in done:
336 done[name] = value
337
Tarek Ziadéedacea32010-01-29 11:41:03 +0000338 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200339 # bogus variable reference (e.g. "prefix=$/opt/python");
340 # just drop it since we can't deal
341 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000342 variables.remove(name)
343
Antoine Pitroudbec7802010-10-10 09:37:12 +0000344 # strip spurious spaces
345 for k, v in done.items():
346 if isinstance(v, str):
347 done[k] = v.strip()
348
Tarek Ziadéedacea32010-01-29 11:41:03 +0000349 # save the results in the global dictionary
350 vars.update(done)
351 return vars
352
Tarek Ziadéedacea32010-01-29 11:41:03 +0000353
Barry Warsawebbef6f2010-09-20 15:29:53 +0000354def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000355 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000356 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100357 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200358 if hasattr(sys, 'abiflags'):
359 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
360 else:
361 config_dir_name = 'config'
362 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000363
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200364def _generate_posix_vars():
365 """Generate the Python module containing build-time variables."""
366 import pprint
367 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000368 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000369 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000370 try:
371 _parse_makefile(makefile, vars)
372 except IOError as e:
373 msg = "invalid Python installation: unable to open %s" % makefile
374 if hasattr(e, "strerror"):
375 msg = msg + " (%s)" % e.strerror
376 raise IOError(msg)
377 # load the installed pyconfig.h:
378 config_h = get_config_h_filename()
379 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000380 with open(config_h) as f:
381 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000382 except IOError as e:
383 msg = "invalid Python installation: unable to open %s" % config_h
384 if hasattr(e, "strerror"):
385 msg = msg + " (%s)" % e.strerror
386 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000387 # On AIX, there are wrong paths to the linker scripts in the Makefile
388 # -- these paths are relative to the Python source, but when installed
389 # the scripts are in another directory.
390 if _PYTHON_BUILD:
391 vars['LDSHARED'] = vars['BLDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200392
393 destfile = os.path.join(os.path.dirname(__file__), '_sysconfigdata.py')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200394 with open(destfile, 'w', encoding='utf8') as f:
Victor Stinner65651ea2011-10-20 00:41:21 +0200395 f.write('# system configuration generated and used by'
396 ' the sysconfig module\n')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200397 f.write('build_time_vars = ')
398 pprint.pprint(vars, stream=f)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000399
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200400def _init_posix(vars):
401 """Initialize the module as appropriate for POSIX systems."""
402 # _sysconfigdata is generated at build time, see _generate_posix_vars()
403 from _sysconfigdata import build_time_vars
404 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200405
Tarek Ziadéedacea32010-01-29 11:41:03 +0000406def _init_non_posix(vars):
407 """Initialize the module as appropriate for NT"""
408 # set basic install directories
409 vars['LIBDEST'] = get_path('stdlib')
410 vars['BINLIBDEST'] = get_path('platstdlib')
411 vars['INCLUDEPY'] = get_path('include')
412 vars['SO'] = '.pyd'
413 vars['EXE'] = '.exe'
414 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000415 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000416
417#
418# public APIs
419#
420
Tarek Ziadébd797682010-02-02 23:16:13 +0000421
422def parse_config_h(fp, vars=None):
423 """Parse a config.h-style file.
424
425 A dictionary containing name/value pairs is returned. If an
426 optional dictionary is passed in as the second argument, it is
427 used instead of a new dictionary.
428 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000429 if vars is None:
430 vars = {}
431 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
432 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
433
434 while True:
435 line = fp.readline()
436 if not line:
437 break
438 m = define_rx.match(line)
439 if m:
440 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200441 try:
442 v = int(v)
443 except ValueError:
444 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000445 vars[n] = v
446 else:
447 m = undef_rx.match(line)
448 if m:
449 vars[m.group(1)] = 0
450 return vars
451
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200452
Tarek Ziadébd797682010-02-02 23:16:13 +0000453def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000454 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000455 if _PYTHON_BUILD:
456 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100457 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000458 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100459 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000460 else:
461 inc_dir = get_path('platinclude')
462 return os.path.join(inc_dir, 'pyconfig.h')
463
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200464
Tarek Ziadéedacea32010-01-29 11:41:03 +0000465def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000466 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400467 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200468
Tarek Ziadéedacea32010-01-29 11:41:03 +0000469
470def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000471 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400472 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200473
Tarek Ziadéedacea32010-01-29 11:41:03 +0000474
475def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000476 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000477
478 ``scheme`` is the install scheme name. If not provided, it will
479 return the default scheme for the current platform.
480 """
481 if expand:
482 return _expand_vars(scheme, vars)
483 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400484 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200485
Tarek Ziadéedacea32010-01-29 11:41:03 +0000486
487def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000488 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000489
490 ``scheme`` is the install scheme name.
491 """
492 return get_paths(scheme, vars, expand)[name]
493
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200494
Tarek Ziadéedacea32010-01-29 11:41:03 +0000495def get_config_vars(*args):
496 """With no arguments, return a dictionary of all configuration
497 variables relevant for the current platform.
498
499 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700500 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000501
502 With arguments, return a list of values that result from looking up
503 each argument in the configuration variable dictionary.
504 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000505 global _CONFIG_VARS
506 if _CONFIG_VARS is None:
507 _CONFIG_VARS = {}
508 # Normalized versions of prefix and exec_prefix are handy to have;
509 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400510 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000511 _CONFIG_VARS['prefix'] = _PREFIX
512 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
513 _CONFIG_VARS['py_version'] = _PY_VERSION
514 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
515 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100516 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000517 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100518 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000519 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000520 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000521 try:
522 _CONFIG_VARS['abiflags'] = sys.abiflags
523 except AttributeError:
524 # sys.abiflags may not be defined on all platforms.
525 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000526
527 if os.name in ('nt', 'os2'):
528 _init_non_posix(_CONFIG_VARS)
529 if os.name == 'posix':
530 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000531 # Setting 'userbase' is done below the call to the
532 # init function to enable using 'get_config_var' in
533 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100534 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000535
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100536 # Always convert srcdir to an absolute path
537 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
538 if os.name == 'posix':
539 if _PYTHON_BUILD:
540 # If srcdir is a relative path (typically '.' or '..')
541 # then it should be interpreted relative to the directory
542 # containing Makefile.
543 base = os.path.dirname(get_makefile_filename())
544 srcdir = os.path.join(base, srcdir)
545 else:
546 # srcdir is not meaningful since the installation is
547 # spread about the filesystem. We choose the
548 # directory containing the Makefile since we know it
549 # exists.
550 srcdir = os.path.dirname(get_makefile_filename())
551 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000552
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700553 # OS X platforms require special customization to handle
554 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000555 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700556 import _osx_support
557 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000558
559 if args:
560 vals = []
561 for name in args:
562 vals.append(_CONFIG_VARS.get(name))
563 return vals
564 else:
565 return _CONFIG_VARS
566
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200567
Tarek Ziadéedacea32010-01-29 11:41:03 +0000568def get_config_var(name):
569 """Return the value of a single variable using the dictionary returned by
570 'get_config_vars()'.
571
572 Equivalent to get_config_vars().get(name)
573 """
574 return get_config_vars().get(name)
575
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200576
Tarek Ziadéedacea32010-01-29 11:41:03 +0000577def get_platform():
578 """Return a string that identifies the current platform.
579
580 This is used mainly to distinguish platform-specific build directories and
581 platform-specific built distributions. Typically includes the OS name
582 and version and the architecture (as supplied by 'os.uname()'),
583 although the exact information included depends on the OS; eg. for IRIX
584 the architecture isn't particularly important (IRIX only runs on SGI
585 hardware), but for Linux the kernel version isn't particularly
586 important.
587
588 Examples of returned values:
589 linux-i586
590 linux-alpha (?)
591 solaris-2.6-sun4u
592 irix-5.3
593 irix64-6.2
594
595 Windows will return one of:
596 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
597 win-ia64 (64bit Windows on Itanium)
598 win32 (all others - specifically, sys.platform is returned)
599
600 For other non-POSIX platforms, currently just returns 'sys.platform'.
601 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000602 if os.name == 'nt':
603 # sniff sys.version for architecture.
604 prefix = " bit ("
605 i = sys.version.find(prefix)
606 if i == -1:
607 return sys.platform
608 j = sys.version.find(")", i)
609 look = sys.version[i+len(prefix):j].lower()
610 if look == 'amd64':
611 return 'win-amd64'
612 if look == 'itanium':
613 return 'win-ia64'
614 return sys.platform
615
616 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700617 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000618 return sys.platform
619
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200620 # Set for cross builds explicitly
621 if "_PYTHON_HOST_PLATFORM" in os.environ:
622 return os.environ["_PYTHON_HOST_PLATFORM"]
623
Tarek Ziadéedacea32010-01-29 11:41:03 +0000624 # Try to distinguish various flavours of Unix
625 osname, host, release, version, machine = os.uname()
626
627 # Convert the OS name to lowercase, remove '/' characters
628 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
629 osname = osname.lower().replace('/', '')
630 machine = machine.replace(' ', '_')
631 machine = machine.replace('/', '-')
632
633 if osname[:5] == "linux":
634 # At least on Linux/Intel, 'machine' is the processor --
635 # i386, etc.
636 # XXX what about Alpha, SPARC, etc?
637 return "%s-%s" % (osname, machine)
638 elif osname[:5] == "sunos":
639 if release[0] >= "5": # SunOS 5 == Solaris 2
640 osname = "solaris"
641 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100642 # We can't use "platform.architecture()[0]" because a
643 # bootstrap problem. We use a dict to get an error
644 # if some suspicious happens.
645 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100646 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000647 # fall through to standard osname-release-machine representation
648 elif osname[:4] == "irix": # could be "irix64"!
649 return "%s-%s" % (osname, release)
650 elif osname[:3] == "aix":
651 return "%s-%s.%s" % (osname, version, release)
652 elif osname[:6] == "cygwin":
653 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200654 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000655 m = rel_re.match(release)
656 if m:
657 release = m.group()
658 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700659 import _osx_support
660 osname, release, machine = _osx_support.get_platform_osx(
661 get_config_vars(),
662 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000663
664 return "%s-%s-%s" % (osname, release, machine)
665
666
667def get_python_version():
668 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000669
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200670
Tarek Ziadéa7514992010-05-25 09:44:36 +0000671def _print_dict(title, data):
672 for index, (key, value) in enumerate(sorted(data.items())):
673 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200674 print('%s: ' % (title))
675 print('\t%s = "%s"' % (key, value))
676
Tarek Ziadéa7514992010-05-25 09:44:36 +0000677
678def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000679 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200680 if '--generate-posix-vars' in sys.argv:
681 _generate_posix_vars()
682 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200683 print('Platform: "%s"' % get_platform())
684 print('Python version: "%s"' % get_python_version())
685 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200686 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000687 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200688 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000689 _print_dict('Variables', get_config_vars())
690
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200691
Tarek Ziadéa7514992010-05-25 09:44:36 +0000692if __name__ == '__main__':
693 _main()