blob: 776b2f640459ae17c853e22c61112fc138b2a1bc [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)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200412
Tarek Ziadéedacea32010-01-29 11:41:03 +0000413def _init_non_posix(vars):
414 """Initialize the module as appropriate for NT"""
415 # set basic install directories
416 vars['LIBDEST'] = get_path('stdlib')
417 vars['BINLIBDEST'] = get_path('platstdlib')
418 vars['INCLUDEPY'] = get_path('include')
doko@ubuntu.comd5537d02013-03-21 13:21:49 -0700419 vars['EXT_SUFFIX'] = '.pyd'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000420 vars['EXE'] = '.exe'
421 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000422 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000423
424#
425# public APIs
426#
427
Tarek Ziadébd797682010-02-02 23:16:13 +0000428
429def parse_config_h(fp, vars=None):
430 """Parse a config.h-style file.
431
432 A dictionary containing name/value pairs is returned. If an
433 optional dictionary is passed in as the second argument, it is
434 used instead of a new dictionary.
435 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000436 if vars is None:
437 vars = {}
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200438 import re
Tarek Ziadébd797682010-02-02 23:16:13 +0000439 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
440 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
441
442 while True:
443 line = fp.readline()
444 if not line:
445 break
446 m = define_rx.match(line)
447 if m:
448 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200449 try:
450 v = int(v)
451 except ValueError:
452 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000453 vars[n] = v
454 else:
455 m = undef_rx.match(line)
456 if m:
457 vars[m.group(1)] = 0
458 return vars
459
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200460
Tarek Ziadébd797682010-02-02 23:16:13 +0000461def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000462 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000463 if _PYTHON_BUILD:
464 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100465 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000466 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100467 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000468 else:
469 inc_dir = get_path('platinclude')
470 return os.path.join(inc_dir, 'pyconfig.h')
471
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200472
Tarek Ziadéedacea32010-01-29 11:41:03 +0000473def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000474 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400475 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200476
Tarek Ziadéedacea32010-01-29 11:41:03 +0000477
478def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000479 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400480 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200481
Tarek Ziadéedacea32010-01-29 11:41:03 +0000482
483def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000484 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000485
486 ``scheme`` is the install scheme name. If not provided, it will
487 return the default scheme for the current platform.
488 """
489 if expand:
490 return _expand_vars(scheme, vars)
491 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400492 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200493
Tarek Ziadéedacea32010-01-29 11:41:03 +0000494
495def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000496 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000497
498 ``scheme`` is the install scheme name.
499 """
500 return get_paths(scheme, vars, expand)[name]
501
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200502
Tarek Ziadéedacea32010-01-29 11:41:03 +0000503def get_config_vars(*args):
504 """With no arguments, return a dictionary of all configuration
505 variables relevant for the current platform.
506
507 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700508 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000509
510 With arguments, return a list of values that result from looking up
511 each argument in the configuration variable dictionary.
512 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000513 global _CONFIG_VARS
514 if _CONFIG_VARS is None:
515 _CONFIG_VARS = {}
516 # Normalized versions of prefix and exec_prefix are handy to have;
517 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400518 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000519 _CONFIG_VARS['prefix'] = _PREFIX
520 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
521 _CONFIG_VARS['py_version'] = _PY_VERSION
522 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
523 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100524 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000525 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100526 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000527 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000528 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000529 try:
530 _CONFIG_VARS['abiflags'] = sys.abiflags
531 except AttributeError:
532 # sys.abiflags may not be defined on all platforms.
533 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000534
Jesus Cea4791a242012-10-05 03:15:39 +0200535 if os.name == 'nt':
Tarek Ziadéedacea32010-01-29 11:41:03 +0000536 _init_non_posix(_CONFIG_VARS)
537 if os.name == 'posix':
538 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000539 # Setting 'userbase' is done below the call to the
540 # init function to enable using 'get_config_var' in
541 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100542 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000543
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100544 # Always convert srcdir to an absolute path
545 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
546 if os.name == 'posix':
547 if _PYTHON_BUILD:
548 # If srcdir is a relative path (typically '.' or '..')
549 # then it should be interpreted relative to the directory
550 # containing Makefile.
551 base = os.path.dirname(get_makefile_filename())
552 srcdir = os.path.join(base, srcdir)
553 else:
554 # srcdir is not meaningful since the installation is
555 # spread about the filesystem. We choose the
556 # directory containing the Makefile since we know it
557 # exists.
558 srcdir = os.path.dirname(get_makefile_filename())
559 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000560
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700561 # OS X platforms require special customization to handle
562 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000563 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700564 import _osx_support
565 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000566
567 if args:
568 vals = []
569 for name in args:
570 vals.append(_CONFIG_VARS.get(name))
571 return vals
572 else:
573 return _CONFIG_VARS
574
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200575
Tarek Ziadéedacea32010-01-29 11:41:03 +0000576def get_config_var(name):
577 """Return the value of a single variable using the dictionary returned by
578 'get_config_vars()'.
579
580 Equivalent to get_config_vars().get(name)
581 """
582 return get_config_vars().get(name)
583
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200584
Tarek Ziadéedacea32010-01-29 11:41:03 +0000585def get_platform():
586 """Return a string that identifies the current platform.
587
588 This is used mainly to distinguish platform-specific build directories and
589 platform-specific built distributions. Typically includes the OS name
590 and version and the architecture (as supplied by 'os.uname()'),
591 although the exact information included depends on the OS; eg. for IRIX
592 the architecture isn't particularly important (IRIX only runs on SGI
593 hardware), but for Linux the kernel version isn't particularly
594 important.
595
596 Examples of returned values:
597 linux-i586
598 linux-alpha (?)
599 solaris-2.6-sun4u
600 irix-5.3
601 irix64-6.2
602
603 Windows will return one of:
604 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
605 win-ia64 (64bit Windows on Itanium)
606 win32 (all others - specifically, sys.platform is returned)
607
608 For other non-POSIX platforms, currently just returns 'sys.platform'.
609 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000610 if os.name == 'nt':
611 # sniff sys.version for architecture.
612 prefix = " bit ("
613 i = sys.version.find(prefix)
614 if i == -1:
615 return sys.platform
616 j = sys.version.find(")", i)
617 look = sys.version[i+len(prefix):j].lower()
618 if look == 'amd64':
619 return 'win-amd64'
620 if look == 'itanium':
621 return 'win-ia64'
622 return sys.platform
623
624 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700625 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000626 return sys.platform
627
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200628 # Set for cross builds explicitly
629 if "_PYTHON_HOST_PLATFORM" in os.environ:
630 return os.environ["_PYTHON_HOST_PLATFORM"]
631
Tarek Ziadéedacea32010-01-29 11:41:03 +0000632 # Try to distinguish various flavours of Unix
633 osname, host, release, version, machine = os.uname()
634
635 # Convert the OS name to lowercase, remove '/' characters
636 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
637 osname = osname.lower().replace('/', '')
638 machine = machine.replace(' ', '_')
639 machine = machine.replace('/', '-')
640
641 if osname[:5] == "linux":
642 # At least on Linux/Intel, 'machine' is the processor --
643 # i386, etc.
644 # XXX what about Alpha, SPARC, etc?
645 return "%s-%s" % (osname, machine)
646 elif osname[:5] == "sunos":
647 if release[0] >= "5": # SunOS 5 == Solaris 2
648 osname = "solaris"
649 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100650 # We can't use "platform.architecture()[0]" because a
651 # bootstrap problem. We use a dict to get an error
652 # if some suspicious happens.
653 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100654 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000655 # fall through to standard osname-release-machine representation
656 elif osname[:4] == "irix": # could be "irix64"!
657 return "%s-%s" % (osname, release)
658 elif osname[:3] == "aix":
659 return "%s-%s.%s" % (osname, version, release)
660 elif osname[:6] == "cygwin":
661 osname = "cygwin"
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200662 import re
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200663 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000664 m = rel_re.match(release)
665 if m:
666 release = m.group()
667 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700668 import _osx_support
669 osname, release, machine = _osx_support.get_platform_osx(
670 get_config_vars(),
671 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000672
673 return "%s-%s-%s" % (osname, release, machine)
674
675
676def get_python_version():
677 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000678
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200679
Tarek Ziadéa7514992010-05-25 09:44:36 +0000680def _print_dict(title, data):
681 for index, (key, value) in enumerate(sorted(data.items())):
682 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200683 print('%s: ' % (title))
684 print('\t%s = "%s"' % (key, value))
685
Tarek Ziadéa7514992010-05-25 09:44:36 +0000686
687def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000688 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200689 if '--generate-posix-vars' in sys.argv:
690 _generate_posix_vars()
691 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200692 print('Platform: "%s"' % get_platform())
693 print('Python version: "%s"' % get_python_version())
694 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200695 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000696 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200697 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000698 _print_dict('Variables', get_config_vars())
699
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200700
Tarek Ziadéa7514992010-05-25 09:44:36 +0000701if __name__ == '__main__':
702 _main()