blob: 137932ef784688ede8938f1ce9cf8d24945cee67 [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',
Steve Dower17be5142015-02-14 09:50:59 -080060 'scripts': '{userbase}/Python{py_version_nodot}/Scripts',
Éric Araujoec177c12012-06-24 03:27:43 -040061 '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
Steve Dower65e4cb12014-11-22 12:54:57 -0800112if (os.name == 'nt' and
113 _PROJECT_BASE.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
Victor Stinnerb103a932010-10-12 22:23:23 +0000114 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000115
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200116# set for cross builds
doko@ubuntu.com7e6c2e22012-06-30 22:35:00 +0200117if "_PYTHON_PROJECT_BASE" in os.environ:
118 _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200119
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100120def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000121 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100122 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000123 return True
124 return False
125
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100126_sys_home = getattr(sys, '_home', None)
Steve Dower65e4cb12014-11-22 12:54:57 -0800127if (_sys_home and os.name == 'nt' and
128 _sys_home.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
129 _sys_home = os.path.dirname(os.path.dirname(_sys_home))
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100130def is_python_build(check_home=False):
131 if check_home and _sys_home:
132 return _is_python_source_dir(_sys_home)
133 return _is_python_source_dir(_PROJECT_BASE)
134
135_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000136
137if _PYTHON_BUILD:
138 for scheme in ('posix_prefix', 'posix_home'):
Éric Araujoec177c12012-06-24 03:27:43 -0400139 _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
140 _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000141
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200142
Éric Araujoec177c12012-06-24 03:27:43 -0400143def _subst_vars(s, local_vars):
144 try:
145 return s.format(**local_vars)
146 except KeyError:
147 try:
148 return s.format(**os.environ)
149 except KeyError as var:
150 raise AttributeError('{%s}' % var)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000151
152def _extend_dict(target_dict, other_dict):
153 target_keys = target_dict.keys()
154 for key, value in other_dict.items():
155 if key in target_keys:
156 continue
157 target_dict[key] = value
158
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200159
Tarek Ziadéedacea32010-01-29 11:41:03 +0000160def _expand_vars(scheme, vars):
161 res = {}
162 if vars is None:
163 vars = {}
164 _extend_dict(vars, get_config_vars())
165
Éric Araujoec177c12012-06-24 03:27:43 -0400166 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000167 if os.name in ('posix', 'nt'):
168 value = os.path.expanduser(value)
169 res[key] = os.path.normpath(_subst_vars(value, vars))
170 return res
171
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200172
Tarek Ziadéedacea32010-01-29 11:41:03 +0000173def _get_default_scheme():
174 if os.name == 'posix':
175 # the default scheme for posix is posix_prefix
176 return 'posix_prefix'
177 return os.name
178
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200179
Tarek Ziadéedacea32010-01-29 11:41:03 +0000180def _getuserbase():
181 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200182
Tarek Ziadéedacea32010-01-29 11:41:03 +0000183 def joinuser(*args):
184 return os.path.expanduser(os.path.join(*args))
185
Tarek Ziadéedacea32010-01-29 11:41:03 +0000186 if os.name == "nt":
187 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200188 if env_base:
189 return env_base
190 else:
191 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000192
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000193 if sys.platform == "darwin":
194 framework = get_config_var("PYTHONFRAMEWORK")
195 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200196 if env_base:
197 return env_base
198 else:
199 return joinuser("~", "Library", framework, "%d.%d" %
200 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000201
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200202 if env_base:
203 return env_base
204 else:
205 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000206
207
208def _parse_makefile(filename, vars=None):
209 """Parse a Makefile-style file.
210
211 A dictionary containing name/value pairs is returned. If an
212 optional dictionary is passed in as the second argument, it is
213 used instead of a new dictionary.
214 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000215 # Regexes needed for parsing Makefile (and similar syntaxes,
216 # like old-style Setup files).
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200217 import re
Tarek Ziadéedacea32010-01-29 11:41:03 +0000218 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
219 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
220 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
221
222 if vars is None:
223 vars = {}
224 done = {}
225 notdone = {}
226
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000227 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000228 lines = f.readlines()
229
230 for line in lines:
231 if line.startswith('#') or line.strip() == '':
232 continue
233 m = _variable_rx.match(line)
234 if m:
235 n, v = m.group(1, 2)
236 v = v.strip()
237 # `$$' is a literal `$' in make
238 tmpv = v.replace('$$', '')
239
240 if "$" in tmpv:
241 notdone[n] = v
242 else:
243 try:
244 v = int(v)
245 except ValueError:
246 # insert literal `$'
247 done[n] = v.replace('$$', '$')
248 else:
249 done[n] = v
250
251 # do variable interpolation here
252 variables = list(notdone.keys())
253
Ronald Oussorend21886c2010-07-20 16:07:10 +0000254 # Variables with a 'PY_' prefix in the makefile. These need to
255 # be made available without that prefix through sysconfig.
256 # Special care is needed to ensure that variable expansion works, even
257 # if the expansion uses the name without a prefix.
258 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
259
Tarek Ziadéedacea32010-01-29 11:41:03 +0000260 while len(variables) > 0:
261 for name in tuple(variables):
262 value = notdone[name]
263 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
264 if m is not None:
265 n = m.group(1)
266 found = True
267 if n in done:
268 item = str(done[n])
269 elif n in notdone:
270 # get it on a subsequent round
271 found = False
272 elif n in os.environ:
273 # do it like make: fall back to environment
274 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000275
276 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200277 if (name.startswith('PY_') and
278 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000279 item = ""
280
281 elif 'PY_' + n in notdone:
282 found = False
283
284 else:
285 item = str(done['PY_' + n])
286
Tarek Ziadéedacea32010-01-29 11:41:03 +0000287 else:
288 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000289
Tarek Ziadéedacea32010-01-29 11:41:03 +0000290 if found:
291 after = value[m.end():]
292 value = value[:m.start()] + item + after
293 if "$" in after:
294 notdone[name] = value
295 else:
296 try:
297 value = int(value)
298 except ValueError:
299 done[name] = value.strip()
300 else:
301 done[name] = value
302 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000303
304 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200305 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000306
307 name = name[3:]
308 if name not in done:
309 done[name] = value
310
Tarek Ziadéedacea32010-01-29 11:41:03 +0000311 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200312 # bogus variable reference (e.g. "prefix=$/opt/python");
313 # just drop it since we can't deal
314 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000315 variables.remove(name)
316
Antoine Pitroudbec7802010-10-10 09:37:12 +0000317 # strip spurious spaces
318 for k, v in done.items():
319 if isinstance(v, str):
320 done[k] = v.strip()
321
Tarek Ziadéedacea32010-01-29 11:41:03 +0000322 # save the results in the global dictionary
323 vars.update(done)
324 return vars
325
Tarek Ziadéedacea32010-01-29 11:41:03 +0000326
Barry Warsawebbef6f2010-09-20 15:29:53 +0000327def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000328 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000329 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100330 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200331 if hasattr(sys, 'abiflags'):
332 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
333 else:
334 config_dir_name = 'config'
335 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000336
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200337def _generate_posix_vars():
338 """Generate the Python module containing build-time variables."""
339 import pprint
340 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000341 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000342 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000343 try:
344 _parse_makefile(makefile, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200345 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000346 msg = "invalid Python installation: unable to open %s" % makefile
347 if hasattr(e, "strerror"):
348 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200349 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000350 # load the installed pyconfig.h:
351 config_h = get_config_h_filename()
352 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000353 with open(config_h) as f:
354 parse_config_h(f, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200355 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000356 msg = "invalid Python installation: unable to open %s" % config_h
357 if hasattr(e, "strerror"):
358 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200359 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000360 # On AIX, there are wrong paths to the linker scripts in the Makefile
361 # -- these paths are relative to the Python source, but when installed
362 # the scripts are in another directory.
363 if _PYTHON_BUILD:
Antoine Pitrou0abb2182013-10-19 22:05:05 +0200364 vars['BLDSHARED'] = vars['LDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200365
Trent Nelsonee528cc2012-10-17 04:23:50 -0400366 # There's a chicken-and-egg situation on OS X with regards to the
367 # _sysconfigdata module after the changes introduced by #15298:
368 # get_config_vars() is called by get_platform() as part of the
369 # `make pybuilddir.txt` target -- which is a precursor to the
370 # _sysconfigdata.py module being constructed. Unfortunately,
371 # get_config_vars() eventually calls _init_posix(), which attempts
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400372 # to import _sysconfigdata, which we won't have built yet. In order
373 # for _init_posix() to work, if we're on Darwin, just mock up the
374 # _sysconfigdata module manually and populate it with the build vars.
375 # This is more than sufficient for ensuring the subsequent call to
376 # get_platform() succeeds.
377 name = '_sysconfigdata'
378 if 'darwin' in sys.platform:
Brett Cannonf15a59f2013-06-15 14:32:11 -0400379 import types
380 module = types.ModuleType(name)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400381 module.build_time_vars = vars
382 sys.modules[name] = module
Tarek Ziadéedacea32010-01-29 11:41:03 +0000383
Trent Nelsonee528cc2012-10-17 04:23:50 -0400384 pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version[:3])
385 if hasattr(sys, "gettotalrefcount"):
386 pybuilddir += '-pydebug'
387 os.makedirs(pybuilddir, exist_ok=True)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400388 destfile = os.path.join(pybuilddir, name + '.py')
Trent Nelsonee528cc2012-10-17 04:23:50 -0400389
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400390 with open(destfile, 'w', encoding='utf8') as f:
391 f.write('# system configuration generated and used by'
392 ' the sysconfig module\n')
393 f.write('build_time_vars = ')
394 pprint.pprint(vars, stream=f)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400395
Trent Nelsonc101bf32012-10-16 08:13:12 -0400396 # Create file used for sys.path fixup -- see Modules/getpath.c
397 with open('pybuilddir.txt', 'w', encoding='ascii') as f:
398 f.write(pybuilddir)
399
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')
doko@ubuntu.comd5537d02013-03-21 13:21:49 -0700412 vars['EXT_SUFFIX'] = '.pyd'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000413 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 = {}
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200431 import re
Tarek Ziadébd797682010-02-02 23:16:13 +0000432 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
433 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
434
435 while True:
436 line = fp.readline()
437 if not line:
438 break
439 m = define_rx.match(line)
440 if m:
441 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200442 try:
443 v = int(v)
444 except ValueError:
445 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000446 vars[n] = v
447 else:
448 m = undef_rx.match(line)
449 if m:
450 vars[m.group(1)] = 0
451 return vars
452
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200453
Tarek Ziadébd797682010-02-02 23:16:13 +0000454def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000455 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000456 if _PYTHON_BUILD:
457 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100458 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000459 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100460 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000461 else:
462 inc_dir = get_path('platinclude')
463 return os.path.join(inc_dir, 'pyconfig.h')
464
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200465
Tarek Ziadéedacea32010-01-29 11:41:03 +0000466def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000467 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400468 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200469
Tarek Ziadéedacea32010-01-29 11:41:03 +0000470
471def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000472 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400473 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200474
Tarek Ziadéedacea32010-01-29 11:41:03 +0000475
476def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000477 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000478
479 ``scheme`` is the install scheme name. If not provided, it will
480 return the default scheme for the current platform.
481 """
482 if expand:
483 return _expand_vars(scheme, vars)
484 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400485 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200486
Tarek Ziadéedacea32010-01-29 11:41:03 +0000487
488def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000489 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000490
491 ``scheme`` is the install scheme name.
492 """
493 return get_paths(scheme, vars, expand)[name]
494
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200495
Tarek Ziadéedacea32010-01-29 11:41:03 +0000496def get_config_vars(*args):
497 """With no arguments, return a dictionary of all configuration
498 variables relevant for the current platform.
499
500 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700501 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000502
503 With arguments, return a list of values that result from looking up
504 each argument in the configuration variable dictionary.
505 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000506 global _CONFIG_VARS
507 if _CONFIG_VARS is None:
508 _CONFIG_VARS = {}
509 # Normalized versions of prefix and exec_prefix are handy to have;
510 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400511 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000512 _CONFIG_VARS['prefix'] = _PREFIX
513 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
514 _CONFIG_VARS['py_version'] = _PY_VERSION
515 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
516 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100517 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000518 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100519 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000520 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000521 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000522 try:
523 _CONFIG_VARS['abiflags'] = sys.abiflags
524 except AttributeError:
525 # sys.abiflags may not be defined on all platforms.
526 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000527
Jesus Cea4791a242012-10-05 03:15:39 +0200528 if os.name == 'nt':
Tarek Ziadéedacea32010-01-29 11:41:03 +0000529 _init_non_posix(_CONFIG_VARS)
530 if os.name == 'posix':
531 _init_posix(_CONFIG_VARS)
Barry Warsaw87b96372013-11-22 11:08:05 -0500532 # For backward compatibility, see issue19555
533 SO = _CONFIG_VARS.get('EXT_SUFFIX')
534 if SO is not None:
535 _CONFIG_VARS['SO'] = SO
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000536 # Setting 'userbase' is done below the call to the
537 # init function to enable using 'get_config_var' in
538 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100539 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000540
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100541 # Always convert srcdir to an absolute path
542 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
543 if os.name == 'posix':
544 if _PYTHON_BUILD:
545 # If srcdir is a relative path (typically '.' or '..')
546 # then it should be interpreted relative to the directory
547 # containing Makefile.
548 base = os.path.dirname(get_makefile_filename())
549 srcdir = os.path.join(base, srcdir)
550 else:
551 # srcdir is not meaningful since the installation is
552 # spread about the filesystem. We choose the
553 # directory containing the Makefile since we know it
554 # exists.
555 srcdir = os.path.dirname(get_makefile_filename())
556 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000557
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700558 # OS X platforms require special customization to handle
559 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000560 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700561 import _osx_support
562 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000563
564 if args:
565 vals = []
566 for name in args:
567 vals.append(_CONFIG_VARS.get(name))
568 return vals
569 else:
570 return _CONFIG_VARS
571
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200572
Tarek Ziadéedacea32010-01-29 11:41:03 +0000573def get_config_var(name):
574 """Return the value of a single variable using the dictionary returned by
575 'get_config_vars()'.
576
577 Equivalent to get_config_vars().get(name)
578 """
Barry Warsaw197a7702013-11-21 18:57:14 -0500579 if name == 'SO':
580 import warnings
Serhiy Storchakaeaec3592013-11-26 17:08:24 +0200581 warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000582 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()