blob: 9314e71a2f82b759a197d45ab6133fcd555930bd [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]
Serhiy Storchaka885bdc42016-02-11 13:10:36 +020089_PY_VERSION_SHORT = '%d.%d' % sys.version_info[:2]
90_PY_VERSION_SHORT_NO_DOT = '%d%d' % sys.version_info[:2]
Tarek Ziadéedacea32010-01-29 11:41:03 +000091_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
R David Murray44b548d2016-09-08 13:59:53 -0400218 _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000219 _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]
doko@ubuntu.comb2b12172016-01-11 21:41:40 +0100263 m1 = _findvar1_rx.search(value)
264 m2 = _findvar2_rx.search(value)
265 if m1 and m2:
266 m = m1 if m1.start() < m2.start() else m2
267 else:
268 m = m1 if m1 else m2
Tarek Ziadéedacea32010-01-29 11:41:03 +0000269 if m is not None:
270 n = m.group(1)
271 found = True
272 if n in done:
273 item = str(done[n])
274 elif n in notdone:
275 # get it on a subsequent round
276 found = False
277 elif n in os.environ:
278 # do it like make: fall back to environment
279 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000280
281 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200282 if (name.startswith('PY_') and
283 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000284 item = ""
285
286 elif 'PY_' + n in notdone:
287 found = False
288
289 else:
290 item = str(done['PY_' + n])
291
Tarek Ziadéedacea32010-01-29 11:41:03 +0000292 else:
293 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000294
Tarek Ziadéedacea32010-01-29 11:41:03 +0000295 if found:
296 after = value[m.end():]
297 value = value[:m.start()] + item + after
298 if "$" in after:
299 notdone[name] = value
300 else:
301 try:
302 value = int(value)
303 except ValueError:
304 done[name] = value.strip()
305 else:
306 done[name] = value
307 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000308
309 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200310 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000311
312 name = name[3:]
313 if name not in done:
314 done[name] = value
315
Tarek Ziadéedacea32010-01-29 11:41:03 +0000316 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200317 # bogus variable reference (e.g. "prefix=$/opt/python");
318 # just drop it since we can't deal
319 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000320 variables.remove(name)
321
Antoine Pitroudbec7802010-10-10 09:37:12 +0000322 # strip spurious spaces
323 for k, v in done.items():
324 if isinstance(v, str):
325 done[k] = v.strip()
326
Tarek Ziadéedacea32010-01-29 11:41:03 +0000327 # save the results in the global dictionary
328 vars.update(done)
329 return vars
330
Tarek Ziadéedacea32010-01-29 11:41:03 +0000331
Barry Warsawebbef6f2010-09-20 15:29:53 +0000332def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000333 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000334 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100335 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200336 if hasattr(sys, 'abiflags'):
337 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
338 else:
339 config_dir_name = 'config'
doko@ubuntu.com55532312016-06-14 08:55:19 +0200340 if hasattr(sys.implementation, '_multiarch'):
341 config_dir_name += '-%s' % sys.implementation._multiarch
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200342 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000343
Zachary Warec4b53af2016-09-09 17:59:49 -0700344
Xavier de Gaye92dec542016-09-11 22:22:24 +0200345def _get_sysconfigdata_name():
346 return os.environ.get('_PYTHON_SYSCONFIGDATA_NAME',
347 '_sysconfigdata_{abi}_{platform}_{multiarch}'.format(
348 abi=sys.abiflags,
349 platform=sys.platform,
350 multiarch=getattr(sys.implementation, '_multiarch', ''),
351 ))
Zachary Warec4b53af2016-09-09 17:59:49 -0700352
353
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200354def _generate_posix_vars():
355 """Generate the Python module containing build-time variables."""
356 import pprint
357 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000358 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000359 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000360 try:
361 _parse_makefile(makefile, 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" % makefile
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 # load the installed pyconfig.h:
368 config_h = get_config_h_filename()
369 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000370 with open(config_h) as f:
371 parse_config_h(f, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200372 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000373 msg = "invalid Python installation: unable to open %s" % config_h
374 if hasattr(e, "strerror"):
375 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200376 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000377 # On AIX, there are wrong paths to the linker scripts in the Makefile
378 # -- these paths are relative to the Python source, but when installed
379 # the scripts are in another directory.
380 if _PYTHON_BUILD:
Antoine Pitrou0abb2182013-10-19 22:05:05 +0200381 vars['BLDSHARED'] = vars['LDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200382
Trent Nelsonee528cc2012-10-17 04:23:50 -0400383 # There's a chicken-and-egg situation on OS X with regards to the
384 # _sysconfigdata module after the changes introduced by #15298:
385 # get_config_vars() is called by get_platform() as part of the
386 # `make pybuilddir.txt` target -- which is a precursor to the
387 # _sysconfigdata.py module being constructed. Unfortunately,
388 # get_config_vars() eventually calls _init_posix(), which attempts
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400389 # to import _sysconfigdata, which we won't have built yet. In order
390 # for _init_posix() to work, if we're on Darwin, just mock up the
391 # _sysconfigdata module manually and populate it with the build vars.
392 # This is more than sufficient for ensuring the subsequent call to
393 # get_platform() succeeds.
Xavier de Gaye92dec542016-09-11 22:22:24 +0200394 name = _get_sysconfigdata_name()
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400395 if 'darwin' in sys.platform:
Brett Cannonf15a59f2013-06-15 14:32:11 -0400396 import types
397 module = types.ModuleType(name)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400398 module.build_time_vars = vars
399 sys.modules[name] = module
Tarek Ziadéedacea32010-01-29 11:41:03 +0000400
Serhiy Storchaka885bdc42016-02-11 13:10:36 +0200401 pybuilddir = 'build/lib.%s-%s' % (get_platform(), _PY_VERSION_SHORT)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400402 if hasattr(sys, "gettotalrefcount"):
403 pybuilddir += '-pydebug'
404 os.makedirs(pybuilddir, exist_ok=True)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400405 destfile = os.path.join(pybuilddir, name + '.py')
Trent Nelsonee528cc2012-10-17 04:23:50 -0400406
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400407 with open(destfile, 'w', encoding='utf8') as f:
408 f.write('# system configuration generated and used by'
409 ' the sysconfig module\n')
410 f.write('build_time_vars = ')
411 pprint.pprint(vars, stream=f)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400412
Trent Nelsonc101bf32012-10-16 08:13:12 -0400413 # Create file used for sys.path fixup -- see Modules/getpath.c
414 with open('pybuilddir.txt', 'w', encoding='ascii') as f:
415 f.write(pybuilddir)
416
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200417def _init_posix(vars):
418 """Initialize the module as appropriate for POSIX systems."""
419 # _sysconfigdata is generated at build time, see _generate_posix_vars()
Zachary Warec4b53af2016-09-09 17:59:49 -0700420 name = _get_sysconfigdata_name()
doko@ubuntu.com55532312016-06-14 08:55:19 +0200421 _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
422 build_time_vars = _temp.build_time_vars
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200423 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200424
Tarek Ziadéedacea32010-01-29 11:41:03 +0000425def _init_non_posix(vars):
426 """Initialize the module as appropriate for NT"""
427 # set basic install directories
428 vars['LIBDEST'] = get_path('stdlib')
429 vars['BINLIBDEST'] = get_path('platstdlib')
430 vars['INCLUDEPY'] = get_path('include')
doko@ubuntu.comd5537d02013-03-21 13:21:49 -0700431 vars['EXT_SUFFIX'] = '.pyd'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000432 vars['EXE'] = '.exe'
433 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000434 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000435
436#
437# public APIs
438#
439
Tarek Ziadébd797682010-02-02 23:16:13 +0000440
441def parse_config_h(fp, vars=None):
442 """Parse a config.h-style file.
443
444 A dictionary containing name/value pairs is returned. If an
445 optional dictionary is passed in as the second argument, it is
446 used instead of a new dictionary.
447 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000448 if vars is None:
449 vars = {}
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200450 import re
Tarek Ziadébd797682010-02-02 23:16:13 +0000451 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
452 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
453
454 while True:
455 line = fp.readline()
456 if not line:
457 break
458 m = define_rx.match(line)
459 if m:
460 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200461 try:
462 v = int(v)
463 except ValueError:
464 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000465 vars[n] = v
466 else:
467 m = undef_rx.match(line)
468 if m:
469 vars[m.group(1)] = 0
470 return vars
471
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200472
Tarek Ziadébd797682010-02-02 23:16:13 +0000473def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000474 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000475 if _PYTHON_BUILD:
476 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100477 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000478 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100479 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000480 else:
481 inc_dir = get_path('platinclude')
482 return os.path.join(inc_dir, 'pyconfig.h')
483
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200484
Tarek Ziadéedacea32010-01-29 11:41:03 +0000485def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000486 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400487 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200488
Tarek Ziadéedacea32010-01-29 11:41:03 +0000489
490def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000491 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400492 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200493
Tarek Ziadéedacea32010-01-29 11:41:03 +0000494
495def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000496 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000497
498 ``scheme`` is the install scheme name. If not provided, it will
499 return the default scheme for the current platform.
500 """
501 if expand:
502 return _expand_vars(scheme, vars)
503 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400504 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200505
Tarek Ziadéedacea32010-01-29 11:41:03 +0000506
507def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000508 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000509
510 ``scheme`` is the install scheme name.
511 """
512 return get_paths(scheme, vars, expand)[name]
513
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200514
Tarek Ziadéedacea32010-01-29 11:41:03 +0000515def get_config_vars(*args):
516 """With no arguments, return a dictionary of all configuration
517 variables relevant for the current platform.
518
519 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700520 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000521
522 With arguments, return a list of values that result from looking up
523 each argument in the configuration variable dictionary.
524 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000525 global _CONFIG_VARS
526 if _CONFIG_VARS is None:
527 _CONFIG_VARS = {}
528 # Normalized versions of prefix and exec_prefix are handy to have;
529 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400530 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000531 _CONFIG_VARS['prefix'] = _PREFIX
532 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
533 _CONFIG_VARS['py_version'] = _PY_VERSION
534 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
Serhiy Storchaka885bdc42016-02-11 13:10:36 +0200535 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100536 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000537 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100538 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000539 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000540 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000541 try:
542 _CONFIG_VARS['abiflags'] = sys.abiflags
543 except AttributeError:
544 # sys.abiflags may not be defined on all platforms.
545 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000546
Jesus Cea4791a242012-10-05 03:15:39 +0200547 if os.name == 'nt':
Tarek Ziadéedacea32010-01-29 11:41:03 +0000548 _init_non_posix(_CONFIG_VARS)
549 if os.name == 'posix':
550 _init_posix(_CONFIG_VARS)
Barry Warsaw87b96372013-11-22 11:08:05 -0500551 # For backward compatibility, see issue19555
552 SO = _CONFIG_VARS.get('EXT_SUFFIX')
553 if SO is not None:
554 _CONFIG_VARS['SO'] = SO
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000555 # Setting 'userbase' is done below the call to the
556 # init function to enable using 'get_config_var' in
557 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100558 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000559
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100560 # Always convert srcdir to an absolute path
561 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
562 if os.name == 'posix':
563 if _PYTHON_BUILD:
564 # If srcdir is a relative path (typically '.' or '..')
565 # then it should be interpreted relative to the directory
566 # containing Makefile.
567 base = os.path.dirname(get_makefile_filename())
568 srcdir = os.path.join(base, srcdir)
569 else:
570 # srcdir is not meaningful since the installation is
571 # spread about the filesystem. We choose the
572 # directory containing the Makefile since we know it
573 # exists.
574 srcdir = os.path.dirname(get_makefile_filename())
575 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000576
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700577 # OS X platforms require special customization to handle
578 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000579 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700580 import _osx_support
581 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000582
583 if args:
584 vals = []
585 for name in args:
586 vals.append(_CONFIG_VARS.get(name))
587 return vals
588 else:
589 return _CONFIG_VARS
590
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200591
Tarek Ziadéedacea32010-01-29 11:41:03 +0000592def get_config_var(name):
593 """Return the value of a single variable using the dictionary returned by
594 'get_config_vars()'.
595
596 Equivalent to get_config_vars().get(name)
597 """
Barry Warsaw197a7702013-11-21 18:57:14 -0500598 if name == 'SO':
599 import warnings
Serhiy Storchakaeaec3592013-11-26 17:08:24 +0200600 warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000601 return get_config_vars().get(name)
602
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200603
Tarek Ziadéedacea32010-01-29 11:41:03 +0000604def get_platform():
605 """Return a string that identifies the current platform.
606
607 This is used mainly to distinguish platform-specific build directories and
608 platform-specific built distributions. Typically includes the OS name
609 and version and the architecture (as supplied by 'os.uname()'),
610 although the exact information included depends on the OS; eg. for IRIX
611 the architecture isn't particularly important (IRIX only runs on SGI
612 hardware), but for Linux the kernel version isn't particularly
613 important.
614
615 Examples of returned values:
616 linux-i586
617 linux-alpha (?)
618 solaris-2.6-sun4u
619 irix-5.3
620 irix64-6.2
621
622 Windows will return one of:
623 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
624 win-ia64 (64bit Windows on Itanium)
625 win32 (all others - specifically, sys.platform is returned)
626
627 For other non-POSIX platforms, currently just returns 'sys.platform'.
628 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000629 if os.name == 'nt':
630 # sniff sys.version for architecture.
631 prefix = " bit ("
632 i = sys.version.find(prefix)
633 if i == -1:
634 return sys.platform
635 j = sys.version.find(")", i)
636 look = sys.version[i+len(prefix):j].lower()
637 if look == 'amd64':
638 return 'win-amd64'
639 if look == 'itanium':
640 return 'win-ia64'
641 return sys.platform
642
643 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700644 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000645 return sys.platform
646
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200647 # Set for cross builds explicitly
648 if "_PYTHON_HOST_PLATFORM" in os.environ:
649 return os.environ["_PYTHON_HOST_PLATFORM"]
650
Tarek Ziadéedacea32010-01-29 11:41:03 +0000651 # Try to distinguish various flavours of Unix
652 osname, host, release, version, machine = os.uname()
653
654 # Convert the OS name to lowercase, remove '/' characters
655 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
656 osname = osname.lower().replace('/', '')
657 machine = machine.replace(' ', '_')
658 machine = machine.replace('/', '-')
659
660 if osname[:5] == "linux":
661 # At least on Linux/Intel, 'machine' is the processor --
662 # i386, etc.
663 # XXX what about Alpha, SPARC, etc?
664 return "%s-%s" % (osname, machine)
665 elif osname[:5] == "sunos":
666 if release[0] >= "5": # SunOS 5 == Solaris 2
667 osname = "solaris"
668 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100669 # We can't use "platform.architecture()[0]" because a
670 # bootstrap problem. We use a dict to get an error
671 # if some suspicious happens.
672 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100673 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000674 # fall through to standard osname-release-machine representation
675 elif osname[:4] == "irix": # could be "irix64"!
676 return "%s-%s" % (osname, release)
677 elif osname[:3] == "aix":
678 return "%s-%s.%s" % (osname, version, release)
679 elif osname[:6] == "cygwin":
680 osname = "cygwin"
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200681 import re
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200682 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000683 m = rel_re.match(release)
684 if m:
685 release = m.group()
686 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700687 import _osx_support
688 osname, release, machine = _osx_support.get_platform_osx(
689 get_config_vars(),
690 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000691
692 return "%s-%s-%s" % (osname, release, machine)
693
694
695def get_python_version():
696 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000697
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200698
Tarek Ziadéa7514992010-05-25 09:44:36 +0000699def _print_dict(title, data):
700 for index, (key, value) in enumerate(sorted(data.items())):
701 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200702 print('%s: ' % (title))
703 print('\t%s = "%s"' % (key, value))
704
Tarek Ziadéa7514992010-05-25 09:44:36 +0000705
706def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000707 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200708 if '--generate-posix-vars' in sys.argv:
709 _generate_posix_vars()
710 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200711 print('Platform: "%s"' % get_platform())
712 print('Python version: "%s"' % get_python_version())
713 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200714 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000715 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200716 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000717 _print_dict('Variables', get_config_vars())
718
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200719
Tarek Ziadéa7514992010-05-25 09:44:36 +0000720if __name__ == '__main__':
721 _main()