blob: c4f7cab174300c46818946154d87d6f006f22cbd [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 sys
Florent Xiclunaa4707382010-03-11 00:05:17 +00005from os.path import pardir, realpath
Tarek Ziadéedacea32010-01-29 11:41:03 +00006
Barry Warsawebbef6f2010-09-20 15:29:53 +00007__all__ = [
8 'get_config_h_filename',
9 'get_config_var',
10 'get_config_vars',
11 'get_makefile_filename',
12 'get_path',
13 'get_path_names',
14 'get_paths',
15 'get_platform',
16 'get_python_version',
17 'get_scheme_names',
18 'parse_config_h',
Tarek Ziade1231a4e2011-05-19 13:07:25 +020019]
Tarek Ziadé16ed6cb2010-05-25 09:47:06 +000020
Éric Araujoec177c12012-06-24 03:27:43 -040021_INSTALL_SCHEMES = {
22 'posix_prefix': {
23 'stdlib': '{installed_base}/lib/python{py_version_short}',
24 'platstdlib': '{platbase}/lib/python{py_version_short}',
25 'purelib': '{base}/lib/python{py_version_short}/site-packages',
26 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
27 'include':
28 '{installed_base}/include/python{py_version_short}{abiflags}',
29 'platinclude':
30 '{installed_platbase}/include/python{py_version_short}{abiflags}',
31 'scripts': '{base}/bin',
32 'data': '{base}',
33 },
34 'posix_home': {
35 'stdlib': '{installed_base}/lib/python',
36 'platstdlib': '{base}/lib/python',
37 'purelib': '{base}/lib/python',
38 'platlib': '{base}/lib/python',
39 'include': '{installed_base}/include/python',
40 'platinclude': '{installed_base}/include/python',
41 'scripts': '{base}/bin',
42 'data': '{base}',
43 },
44 'nt': {
45 'stdlib': '{installed_base}/Lib',
46 'platstdlib': '{base}/Lib',
47 'purelib': '{base}/Lib/site-packages',
48 'platlib': '{base}/Lib/site-packages',
49 'include': '{installed_base}/Include',
50 'platinclude': '{installed_base}/Include',
51 'scripts': '{base}/Scripts',
52 'data': '{base}',
53 },
Éric Araujoec177c12012-06-24 03:27:43 -040054 'nt_user': {
55 'stdlib': '{userbase}/Python{py_version_nodot}',
56 'platstdlib': '{userbase}/Python{py_version_nodot}',
57 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
58 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
59 'include': '{userbase}/Python{py_version_nodot}/Include',
60 'scripts': '{userbase}/Scripts',
61 'data': '{userbase}',
62 },
63 'posix_user': {
64 'stdlib': '{userbase}/lib/python{py_version_short}',
65 'platstdlib': '{userbase}/lib/python{py_version_short}',
66 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
67 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
68 'include': '{userbase}/include/python{py_version_short}',
69 'scripts': '{userbase}/bin',
70 'data': '{userbase}',
71 },
72 'osx_framework_user': {
73 'stdlib': '{userbase}/lib/python',
74 'platstdlib': '{userbase}/lib/python',
75 'purelib': '{userbase}/lib/python/site-packages',
76 'platlib': '{userbase}/lib/python/site-packages',
77 'include': '{userbase}/include',
78 'scripts': '{userbase}/bin',
79 'data': '{userbase}',
80 },
81 }
Tarek Ziadéedacea32010-01-29 11:41:03 +000082
Éric Araujoec177c12012-06-24 03:27:43 -040083_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
84 'scripts', 'data')
Tarek Ziade1231a4e2011-05-19 13:07:25 +020085
Vinay Sajip7ded1f02012-05-26 03:45:29 +010086 # FIXME don't rely on sys.version here, its format is an implementation detail
Tarek Ziade1231a4e2011-05-19 13:07:25 +020087 # of CPython, use sys.version_info or sys.hexversion
Tarek Ziadéedacea32010-01-29 11:41:03 +000088_PY_VERSION = sys.version.split()[0]
89_PY_VERSION_SHORT = sys.version[:3]
90_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
91_PREFIX = os.path.normpath(sys.prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010092_BASE_PREFIX = os.path.normpath(sys.base_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000093_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010094_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000095_CONFIG_VARS = None
96_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +000097
Tarek Ziade1231a4e2011-05-19 13:07:25 +020098
Victor Stinnerb103a932010-10-12 22:23:23 +000099def _safe_realpath(path):
100 try:
101 return realpath(path)
102 except OSError:
103 return path
104
Victor Stinner171ba052010-03-12 14:20:59 +0000105if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +0000106 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +0000107else:
108 # sys.executable can be empty if argv[0] has been changed and Python is
109 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +0000110 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +0000111
112if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000113 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000114# PC/VS7.1
115if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000116 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000117# PC/AMD64
118if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000119 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000120
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200121# set for cross builds
doko@ubuntu.com7e6c2e22012-06-30 22:35:00 +0200122if "_PYTHON_PROJECT_BASE" in os.environ:
123 _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200124
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100125def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000126 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100127 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000128 return True
129 return False
130
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100131_sys_home = getattr(sys, '_home', None)
Vinay Sajip42211422012-05-26 20:36:12 +0100132if _sys_home and os.name == 'nt' and \
133 _sys_home.lower().endswith(('pcbuild', 'pcbuild\\amd64')):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100134 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7e203492012-05-27 17:30:09 +0100135 if _sys_home.endswith('pcbuild'): # must be amd64
136 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100137def is_python_build(check_home=False):
138 if check_home and _sys_home:
139 return _is_python_source_dir(_sys_home)
140 return _is_python_source_dir(_PROJECT_BASE)
141
142_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000143
144if _PYTHON_BUILD:
145 for scheme in ('posix_prefix', 'posix_home'):
Éric Araujoec177c12012-06-24 03:27:43 -0400146 _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
147 _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000148
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200149
Éric Araujoec177c12012-06-24 03:27:43 -0400150def _subst_vars(s, local_vars):
151 try:
152 return s.format(**local_vars)
153 except KeyError:
154 try:
155 return s.format(**os.environ)
156 except KeyError as var:
157 raise AttributeError('{%s}' % var)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000158
159def _extend_dict(target_dict, other_dict):
160 target_keys = target_dict.keys()
161 for key, value in other_dict.items():
162 if key in target_keys:
163 continue
164 target_dict[key] = value
165
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200166
Tarek Ziadéedacea32010-01-29 11:41:03 +0000167def _expand_vars(scheme, vars):
168 res = {}
169 if vars is None:
170 vars = {}
171 _extend_dict(vars, get_config_vars())
172
Éric Araujoec177c12012-06-24 03:27:43 -0400173 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000174 if os.name in ('posix', 'nt'):
175 value = os.path.expanduser(value)
176 res[key] = os.path.normpath(_subst_vars(value, vars))
177 return res
178
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200179
Tarek Ziadéedacea32010-01-29 11:41:03 +0000180def _get_default_scheme():
181 if os.name == 'posix':
182 # the default scheme for posix is posix_prefix
183 return 'posix_prefix'
184 return os.name
185
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200186
Tarek Ziadéedacea32010-01-29 11:41:03 +0000187def _getuserbase():
188 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200189
Tarek Ziadéedacea32010-01-29 11:41:03 +0000190 def joinuser(*args):
191 return os.path.expanduser(os.path.join(*args))
192
Tarek Ziadéedacea32010-01-29 11:41:03 +0000193 if os.name == "nt":
194 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200195 if env_base:
196 return env_base
197 else:
198 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000199
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000200 if sys.platform == "darwin":
201 framework = get_config_var("PYTHONFRAMEWORK")
202 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200203 if env_base:
204 return env_base
205 else:
206 return joinuser("~", "Library", framework, "%d.%d" %
207 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000208
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200209 if env_base:
210 return env_base
211 else:
212 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000213
214
215def _parse_makefile(filename, vars=None):
216 """Parse a Makefile-style file.
217
218 A dictionary containing name/value pairs is returned. If an
219 optional dictionary is passed in as the second argument, it is
220 used instead of a new dictionary.
221 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000222 # Regexes needed for parsing Makefile (and similar syntaxes,
223 # like old-style Setup files).
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200224 import re
Tarek Ziadéedacea32010-01-29 11:41:03 +0000225 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
226 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
227 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
228
229 if vars is None:
230 vars = {}
231 done = {}
232 notdone = {}
233
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000234 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000235 lines = f.readlines()
236
237 for line in lines:
238 if line.startswith('#') or line.strip() == '':
239 continue
240 m = _variable_rx.match(line)
241 if m:
242 n, v = m.group(1, 2)
243 v = v.strip()
244 # `$$' is a literal `$' in make
245 tmpv = v.replace('$$', '')
246
247 if "$" in tmpv:
248 notdone[n] = v
249 else:
250 try:
251 v = int(v)
252 except ValueError:
253 # insert literal `$'
254 done[n] = v.replace('$$', '$')
255 else:
256 done[n] = v
257
258 # do variable interpolation here
259 variables = list(notdone.keys())
260
Ronald Oussorend21886c2010-07-20 16:07:10 +0000261 # Variables with a 'PY_' prefix in the makefile. These need to
262 # be made available without that prefix through sysconfig.
263 # Special care is needed to ensure that variable expansion works, even
264 # if the expansion uses the name without a prefix.
265 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
266
Tarek Ziadéedacea32010-01-29 11:41:03 +0000267 while len(variables) > 0:
268 for name in tuple(variables):
269 value = notdone[name]
270 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
271 if m is not None:
272 n = m.group(1)
273 found = True
274 if n in done:
275 item = str(done[n])
276 elif n in notdone:
277 # get it on a subsequent round
278 found = False
279 elif n in os.environ:
280 # do it like make: fall back to environment
281 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000282
283 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200284 if (name.startswith('PY_') and
285 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000286 item = ""
287
288 elif 'PY_' + n in notdone:
289 found = False
290
291 else:
292 item = str(done['PY_' + n])
293
Tarek Ziadéedacea32010-01-29 11:41:03 +0000294 else:
295 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000296
Tarek Ziadéedacea32010-01-29 11:41:03 +0000297 if found:
298 after = value[m.end():]
299 value = value[:m.start()] + item + after
300 if "$" in after:
301 notdone[name] = value
302 else:
303 try:
304 value = int(value)
305 except ValueError:
306 done[name] = value.strip()
307 else:
308 done[name] = value
309 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000310
311 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200312 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000313
314 name = name[3:]
315 if name not in done:
316 done[name] = value
317
Tarek Ziadéedacea32010-01-29 11:41:03 +0000318 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200319 # bogus variable reference (e.g. "prefix=$/opt/python");
320 # just drop it since we can't deal
321 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000322 variables.remove(name)
323
Antoine Pitroudbec7802010-10-10 09:37:12 +0000324 # strip spurious spaces
325 for k, v in done.items():
326 if isinstance(v, str):
327 done[k] = v.strip()
328
Tarek Ziadéedacea32010-01-29 11:41:03 +0000329 # save the results in the global dictionary
330 vars.update(done)
331 return vars
332
Tarek Ziadéedacea32010-01-29 11:41:03 +0000333
Barry Warsawebbef6f2010-09-20 15:29:53 +0000334def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000335 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000336 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100337 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200338 if hasattr(sys, 'abiflags'):
339 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
340 else:
341 config_dir_name = 'config'
342 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000343
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200344def _generate_posix_vars():
345 """Generate the Python module containing build-time variables."""
346 import pprint
347 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000348 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000349 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000350 try:
351 _parse_makefile(makefile, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200352 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000353 msg = "invalid Python installation: unable to open %s" % makefile
354 if hasattr(e, "strerror"):
355 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200356 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000357 # load the installed pyconfig.h:
358 config_h = get_config_h_filename()
359 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000360 with open(config_h) as f:
361 parse_config_h(f, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200362 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000363 msg = "invalid Python installation: unable to open %s" % config_h
364 if hasattr(e, "strerror"):
365 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200366 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000367 # On AIX, there are wrong paths to the linker scripts in the Makefile
368 # -- these paths are relative to the Python source, but when installed
369 # the scripts are in another directory.
370 if _PYTHON_BUILD:
Antoine Pitrou0abb2182013-10-19 22:05:05 +0200371 vars['BLDSHARED'] = vars['LDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200372
Trent Nelsonee528cc2012-10-17 04:23:50 -0400373 # There's a chicken-and-egg situation on OS X with regards to the
374 # _sysconfigdata module after the changes introduced by #15298:
375 # get_config_vars() is called by get_platform() as part of the
376 # `make pybuilddir.txt` target -- which is a precursor to the
377 # _sysconfigdata.py module being constructed. Unfortunately,
378 # get_config_vars() eventually calls _init_posix(), which attempts
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400379 # to import _sysconfigdata, which we won't have built yet. In order
380 # for _init_posix() to work, if we're on Darwin, just mock up the
381 # _sysconfigdata module manually and populate it with the build vars.
382 # This is more than sufficient for ensuring the subsequent call to
383 # get_platform() succeeds.
384 name = '_sysconfigdata'
385 if 'darwin' in sys.platform:
Brett Cannonf15a59f2013-06-15 14:32:11 -0400386 import types
387 module = types.ModuleType(name)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400388 module.build_time_vars = vars
389 sys.modules[name] = module
Tarek Ziadéedacea32010-01-29 11:41:03 +0000390
Trent Nelsonee528cc2012-10-17 04:23:50 -0400391 pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version[:3])
392 if hasattr(sys, "gettotalrefcount"):
393 pybuilddir += '-pydebug'
394 os.makedirs(pybuilddir, exist_ok=True)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400395 destfile = os.path.join(pybuilddir, name + '.py')
Trent Nelsonee528cc2012-10-17 04:23:50 -0400396
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400397 with open(destfile, 'w', encoding='utf8') as f:
398 f.write('# system configuration generated and used by'
399 ' the sysconfig module\n')
400 f.write('build_time_vars = ')
401 pprint.pprint(vars, stream=f)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400402
Trent Nelsonc101bf32012-10-16 08:13:12 -0400403 # Create file used for sys.path fixup -- see Modules/getpath.c
404 with open('pybuilddir.txt', 'w', encoding='ascii') as f:
405 f.write(pybuilddir)
406
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200407def _init_posix(vars):
408 """Initialize the module as appropriate for POSIX systems."""
409 # _sysconfigdata is generated at build time, see _generate_posix_vars()
410 from _sysconfigdata import build_time_vars
411 vars.update(build_time_vars)
Barry Warsaw197a7702013-11-21 18:57:14 -0500412 # For backward compatibility, see issue19555
413 SO = build_time_vars.get('EXT_SUFFIX')
414 if SO is not None:
415 vars['SO'] = SO
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200416
Tarek Ziadéedacea32010-01-29 11:41:03 +0000417def _init_non_posix(vars):
418 """Initialize the module as appropriate for NT"""
419 # set basic install directories
420 vars['LIBDEST'] = get_path('stdlib')
421 vars['BINLIBDEST'] = get_path('platstdlib')
422 vars['INCLUDEPY'] = get_path('include')
doko@ubuntu.comd5537d02013-03-21 13:21:49 -0700423 vars['EXT_SUFFIX'] = '.pyd'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000424 vars['EXE'] = '.exe'
425 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000426 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000427
428#
429# public APIs
430#
431
Tarek Ziadébd797682010-02-02 23:16:13 +0000432
433def parse_config_h(fp, vars=None):
434 """Parse a config.h-style file.
435
436 A dictionary containing name/value pairs is returned. If an
437 optional dictionary is passed in as the second argument, it is
438 used instead of a new dictionary.
439 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000440 if vars is None:
441 vars = {}
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200442 import re
Tarek Ziadébd797682010-02-02 23:16:13 +0000443 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
444 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
445
446 while True:
447 line = fp.readline()
448 if not line:
449 break
450 m = define_rx.match(line)
451 if m:
452 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200453 try:
454 v = int(v)
455 except ValueError:
456 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000457 vars[n] = v
458 else:
459 m = undef_rx.match(line)
460 if m:
461 vars[m.group(1)] = 0
462 return vars
463
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200464
Tarek Ziadébd797682010-02-02 23:16:13 +0000465def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000466 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000467 if _PYTHON_BUILD:
468 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100469 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000470 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100471 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000472 else:
473 inc_dir = get_path('platinclude')
474 return os.path.join(inc_dir, 'pyconfig.h')
475
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200476
Tarek Ziadéedacea32010-01-29 11:41:03 +0000477def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000478 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400479 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200480
Tarek Ziadéedacea32010-01-29 11:41:03 +0000481
482def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000483 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400484 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200485
Tarek Ziadéedacea32010-01-29 11:41:03 +0000486
487def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000488 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000489
490 ``scheme`` is the install scheme name. If not provided, it will
491 return the default scheme for the current platform.
492 """
493 if expand:
494 return _expand_vars(scheme, vars)
495 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400496 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200497
Tarek Ziadéedacea32010-01-29 11:41:03 +0000498
499def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000500 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000501
502 ``scheme`` is the install scheme name.
503 """
504 return get_paths(scheme, vars, expand)[name]
505
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200506
Tarek Ziadéedacea32010-01-29 11:41:03 +0000507def get_config_vars(*args):
508 """With no arguments, return a dictionary of all configuration
509 variables relevant for the current platform.
510
511 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700512 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000513
514 With arguments, return a list of values that result from looking up
515 each argument in the configuration variable dictionary.
516 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000517 global _CONFIG_VARS
518 if _CONFIG_VARS is None:
519 _CONFIG_VARS = {}
520 # Normalized versions of prefix and exec_prefix are handy to have;
521 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400522 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000523 _CONFIG_VARS['prefix'] = _PREFIX
524 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
525 _CONFIG_VARS['py_version'] = _PY_VERSION
526 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
527 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100528 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000529 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100530 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000531 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000532 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000533 try:
534 _CONFIG_VARS['abiflags'] = sys.abiflags
535 except AttributeError:
536 # sys.abiflags may not be defined on all platforms.
537 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000538
Jesus Cea4791a242012-10-05 03:15:39 +0200539 if os.name == 'nt':
Tarek Ziadéedacea32010-01-29 11:41:03 +0000540 _init_non_posix(_CONFIG_VARS)
541 if os.name == 'posix':
542 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000543 # Setting 'userbase' is done below the call to the
544 # init function to enable using 'get_config_var' in
545 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100546 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000547
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100548 # Always convert srcdir to an absolute path
549 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
550 if os.name == 'posix':
551 if _PYTHON_BUILD:
552 # If srcdir is a relative path (typically '.' or '..')
553 # then it should be interpreted relative to the directory
554 # containing Makefile.
555 base = os.path.dirname(get_makefile_filename())
556 srcdir = os.path.join(base, srcdir)
557 else:
558 # srcdir is not meaningful since the installation is
559 # spread about the filesystem. We choose the
560 # directory containing the Makefile since we know it
561 # exists.
562 srcdir = os.path.dirname(get_makefile_filename())
563 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000564
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700565 # OS X platforms require special customization to handle
566 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000567 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700568 import _osx_support
569 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000570
571 if args:
572 vals = []
573 for name in args:
574 vals.append(_CONFIG_VARS.get(name))
575 return vals
576 else:
577 return _CONFIG_VARS
578
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200579
Tarek Ziadéedacea32010-01-29 11:41:03 +0000580def get_config_var(name):
581 """Return the value of a single variable using the dictionary returned by
582 'get_config_vars()'.
583
584 Equivalent to get_config_vars().get(name)
585 """
Barry Warsaw197a7702013-11-21 18:57:14 -0500586 if name == 'SO':
587 import warnings
588 warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000589 return get_config_vars().get(name)
590
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200591
Tarek Ziadéedacea32010-01-29 11:41:03 +0000592def get_platform():
593 """Return a string that identifies the current platform.
594
595 This is used mainly to distinguish platform-specific build directories and
596 platform-specific built distributions. Typically includes the OS name
597 and version and the architecture (as supplied by 'os.uname()'),
598 although the exact information included depends on the OS; eg. for IRIX
599 the architecture isn't particularly important (IRIX only runs on SGI
600 hardware), but for Linux the kernel version isn't particularly
601 important.
602
603 Examples of returned values:
604 linux-i586
605 linux-alpha (?)
606 solaris-2.6-sun4u
607 irix-5.3
608 irix64-6.2
609
610 Windows will return one of:
611 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
612 win-ia64 (64bit Windows on Itanium)
613 win32 (all others - specifically, sys.platform is returned)
614
615 For other non-POSIX platforms, currently just returns 'sys.platform'.
616 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000617 if os.name == 'nt':
618 # sniff sys.version for architecture.
619 prefix = " bit ("
620 i = sys.version.find(prefix)
621 if i == -1:
622 return sys.platform
623 j = sys.version.find(")", i)
624 look = sys.version[i+len(prefix):j].lower()
625 if look == 'amd64':
626 return 'win-amd64'
627 if look == 'itanium':
628 return 'win-ia64'
629 return sys.platform
630
631 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700632 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000633 return sys.platform
634
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200635 # Set for cross builds explicitly
636 if "_PYTHON_HOST_PLATFORM" in os.environ:
637 return os.environ["_PYTHON_HOST_PLATFORM"]
638
Tarek Ziadéedacea32010-01-29 11:41:03 +0000639 # Try to distinguish various flavours of Unix
640 osname, host, release, version, machine = os.uname()
641
642 # Convert the OS name to lowercase, remove '/' characters
643 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
644 osname = osname.lower().replace('/', '')
645 machine = machine.replace(' ', '_')
646 machine = machine.replace('/', '-')
647
648 if osname[:5] == "linux":
649 # At least on Linux/Intel, 'machine' is the processor --
650 # i386, etc.
651 # XXX what about Alpha, SPARC, etc?
652 return "%s-%s" % (osname, machine)
653 elif osname[:5] == "sunos":
654 if release[0] >= "5": # SunOS 5 == Solaris 2
655 osname = "solaris"
656 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100657 # We can't use "platform.architecture()[0]" because a
658 # bootstrap problem. We use a dict to get an error
659 # if some suspicious happens.
660 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100661 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000662 # fall through to standard osname-release-machine representation
663 elif osname[:4] == "irix": # could be "irix64"!
664 return "%s-%s" % (osname, release)
665 elif osname[:3] == "aix":
666 return "%s-%s.%s" % (osname, version, release)
667 elif osname[:6] == "cygwin":
668 osname = "cygwin"
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200669 import re
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200670 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000671 m = rel_re.match(release)
672 if m:
673 release = m.group()
674 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700675 import _osx_support
676 osname, release, machine = _osx_support.get_platform_osx(
677 get_config_vars(),
678 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000679
680 return "%s-%s-%s" % (osname, release, machine)
681
682
683def get_python_version():
684 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000685
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200686
Tarek Ziadéa7514992010-05-25 09:44:36 +0000687def _print_dict(title, data):
688 for index, (key, value) in enumerate(sorted(data.items())):
689 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200690 print('%s: ' % (title))
691 print('\t%s = "%s"' % (key, value))
692
Tarek Ziadéa7514992010-05-25 09:44:36 +0000693
694def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000695 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200696 if '--generate-posix-vars' in sys.argv:
697 _generate_posix_vars()
698 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200699 print('Platform: "%s"' % get_platform())
700 print('Python version: "%s"' % get_python_version())
701 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200702 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000703 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200704 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000705 _print_dict('Variables', get_config_vars())
706
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200707
Tarek Ziadéa7514992010-05-25 09:44:36 +0000708if __name__ == '__main__':
709 _main()