1 | """Provide access to Python's configuration information.
|
---|
2 |
|
---|
3 | """
|
---|
4 | import sys
|
---|
5 | import os
|
---|
6 | from os.path import pardir, realpath
|
---|
7 |
|
---|
8 | _INSTALL_SCHEMES = {
|
---|
9 | 'posix_prefix': {
|
---|
10 | 'stdlib': '{base}/lib/python{py_version_short}',
|
---|
11 | 'platstdlib': '{platbase}/lib/python{py_version_short}',
|
---|
12 | 'purelib': '{base}/lib/python{py_version_short}/site-packages',
|
---|
13 | 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
|
---|
14 | 'include': '{base}/include/python{py_version_short}',
|
---|
15 | 'platinclude': '{platbase}/include/python{py_version_short}',
|
---|
16 | 'scripts': '{base}/bin',
|
---|
17 | 'data': '{base}',
|
---|
18 | },
|
---|
19 | 'posix_home': {
|
---|
20 | 'stdlib': '{base}/lib/python',
|
---|
21 | 'platstdlib': '{base}/lib/python',
|
---|
22 | 'purelib': '{base}/lib/python',
|
---|
23 | 'platlib': '{base}/lib/python',
|
---|
24 | 'include': '{base}/include/python',
|
---|
25 | 'platinclude': '{base}/include/python',
|
---|
26 | 'scripts': '{base}/bin',
|
---|
27 | 'data' : '{base}',
|
---|
28 | },
|
---|
29 | 'nt': {
|
---|
30 | 'stdlib': '{base}/Lib',
|
---|
31 | 'platstdlib': '{base}/Lib',
|
---|
32 | 'purelib': '{base}/Lib/site-packages',
|
---|
33 | 'platlib': '{base}/Lib/site-packages',
|
---|
34 | 'include': '{base}/Include',
|
---|
35 | 'platinclude': '{base}/Include',
|
---|
36 | 'scripts': '{base}/Scripts',
|
---|
37 | 'data' : '{base}',
|
---|
38 | },
|
---|
39 | 'os2': {
|
---|
40 | 'stdlib': '{base}/Lib',
|
---|
41 | 'platstdlib': '{base}/Lib',
|
---|
42 | 'purelib': '{base}/Lib/site-packages',
|
---|
43 | 'platlib': '{base}/Lib/site-packages',
|
---|
44 | 'include': '{base}/Include',
|
---|
45 | 'platinclude': '{base}/Include',
|
---|
46 | 'scripts': '{base}/Scripts',
|
---|
47 | 'data' : '{base}',
|
---|
48 | },
|
---|
49 | 'os2_home': {
|
---|
50 | 'stdlib': '{userbase}/lib/python{py_version_short}',
|
---|
51 | 'platstdlib': '{userbase}/lib/python{py_version_short}',
|
---|
52 | 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
|
---|
53 | 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
|
---|
54 | 'include': '{userbase}/include/python{py_version_short}',
|
---|
55 | 'scripts': '{userbase}/bin',
|
---|
56 | 'data' : '{userbase}',
|
---|
57 | },
|
---|
58 | 'nt_user': {
|
---|
59 | 'stdlib': '{userbase}/Python{py_version_nodot}',
|
---|
60 | 'platstdlib': '{userbase}/Python{py_version_nodot}',
|
---|
61 | 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
|
---|
62 | 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
|
---|
63 | 'include': '{userbase}/Python{py_version_nodot}/Include',
|
---|
64 | 'scripts': '{userbase}/Scripts',
|
---|
65 | 'data' : '{userbase}',
|
---|
66 | },
|
---|
67 | 'posix_user': {
|
---|
68 | 'stdlib': '{userbase}/lib/python{py_version_short}',
|
---|
69 | 'platstdlib': '{userbase}/lib/python{py_version_short}',
|
---|
70 | 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
|
---|
71 | 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
|
---|
72 | 'include': '{userbase}/include/python{py_version_short}',
|
---|
73 | 'scripts': '{userbase}/bin',
|
---|
74 | 'data' : '{userbase}',
|
---|
75 | },
|
---|
76 | 'osx_framework_user': {
|
---|
77 | 'stdlib': '{userbase}/lib/python',
|
---|
78 | 'platstdlib': '{userbase}/lib/python',
|
---|
79 | 'purelib': '{userbase}/lib/python/site-packages',
|
---|
80 | 'platlib': '{userbase}/lib/python/site-packages',
|
---|
81 | 'include': '{userbase}/include',
|
---|
82 | 'scripts': '{userbase}/bin',
|
---|
83 | 'data' : '{userbase}',
|
---|
84 | },
|
---|
85 | }
|
---|
86 |
|
---|
87 | _SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
|
---|
88 | 'scripts', 'data')
|
---|
89 | _PY_VERSION = sys.version.split()[0]
|
---|
90 | _PY_VERSION_SHORT = sys.version[:3]
|
---|
91 | _PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
|
---|
92 | _PREFIX = os.path.normpath(sys.prefix)
|
---|
93 | _EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
|
---|
94 | _CONFIG_VARS = None
|
---|
95 | _USER_BASE = None
|
---|
96 |
|
---|
97 | def _safe_realpath(path):
|
---|
98 | try:
|
---|
99 | return realpath(path)
|
---|
100 | except OSError:
|
---|
101 | return path
|
---|
102 |
|
---|
103 | if sys.executable:
|
---|
104 | _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
|
---|
105 | else:
|
---|
106 | # sys.executable can be empty if argv[0] has been changed and Python is
|
---|
107 | # unable to retrieve the real program name
|
---|
108 | _PROJECT_BASE = _safe_realpath(os.getcwd())
|
---|
109 |
|
---|
110 | if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
|
---|
111 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
|
---|
112 | # PC/VS7.1
|
---|
113 | if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
|
---|
114 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
|
---|
115 | # PC/AMD64
|
---|
116 | if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
|
---|
117 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
|
---|
118 |
|
---|
119 | # set for cross builds
|
---|
120 | if "_PYTHON_PROJECT_BASE" in os.environ:
|
---|
121 | # the build directory for posix builds
|
---|
122 | _PROJECT_BASE = os.path.normpath(os.path.abspath("."))
|
---|
123 | def is_python_build():
|
---|
124 | for fn in ("Setup.dist", "Setup.local"):
|
---|
125 | if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
|
---|
126 | return True
|
---|
127 | return False
|
---|
128 |
|
---|
129 | _PYTHON_BUILD = is_python_build()
|
---|
130 |
|
---|
131 | if _PYTHON_BUILD:
|
---|
132 | for scheme in ('posix_prefix', 'posix_home'):
|
---|
133 | _INSTALL_SCHEMES[scheme]['include'] = '{projectbase}/Include'
|
---|
134 | _INSTALL_SCHEMES[scheme]['platinclude'] = '{srcdir}'
|
---|
135 |
|
---|
136 | def _subst_vars(s, local_vars):
|
---|
137 | try:
|
---|
138 | return s.format(**local_vars)
|
---|
139 | except KeyError:
|
---|
140 | try:
|
---|
141 | return s.format(**os.environ)
|
---|
142 | except KeyError, var:
|
---|
143 | raise AttributeError('{%s}' % var)
|
---|
144 |
|
---|
145 | def _extend_dict(target_dict, other_dict):
|
---|
146 | target_keys = target_dict.keys()
|
---|
147 | for key, value in other_dict.items():
|
---|
148 | if key in target_keys:
|
---|
149 | continue
|
---|
150 | target_dict[key] = value
|
---|
151 |
|
---|
152 | def _expand_vars(scheme, vars):
|
---|
153 | res = {}
|
---|
154 | if vars is None:
|
---|
155 | vars = {}
|
---|
156 | _extend_dict(vars, get_config_vars())
|
---|
157 |
|
---|
158 | for key, value in _INSTALL_SCHEMES[scheme].items():
|
---|
159 | if os.name in ('posix', 'nt'):
|
---|
160 | value = os.path.expanduser(value)
|
---|
161 | res[key] = os.path.normpath(_subst_vars(value, vars))
|
---|
162 | return res
|
---|
163 |
|
---|
164 | def _get_default_scheme():
|
---|
165 | if os.name == 'posix':
|
---|
166 | # the default scheme for posix is posix_prefix
|
---|
167 | return 'posix_prefix'
|
---|
168 | return os.name
|
---|
169 |
|
---|
170 | def _getuserbase():
|
---|
171 | env_base = os.environ.get("PYTHONUSERBASE", None)
|
---|
172 | def joinuser(*args):
|
---|
173 | return os.path.expanduser(os.path.join(*args))
|
---|
174 |
|
---|
175 | # what about 'os2emx', 'riscos' ?
|
---|
176 | if os.name == "nt":
|
---|
177 | base = os.environ.get("APPDATA") or "~"
|
---|
178 | return env_base if env_base else joinuser(base, "Python")
|
---|
179 |
|
---|
180 | if sys.platform == "darwin":
|
---|
181 | framework = get_config_var("PYTHONFRAMEWORK")
|
---|
182 | if framework:
|
---|
183 | return env_base if env_base else \
|
---|
184 | joinuser("~", "Library", framework, "%d.%d"
|
---|
185 | % (sys.version_info[:2]))
|
---|
186 |
|
---|
187 | return env_base if env_base else joinuser("~", ".local")
|
---|
188 |
|
---|
189 |
|
---|
190 | def _parse_makefile(filename, vars=None):
|
---|
191 | """Parse a Makefile-style file.
|
---|
192 |
|
---|
193 | A dictionary containing name/value pairs is returned. If an
|
---|
194 | optional dictionary is passed in as the second argument, it is
|
---|
195 | used instead of a new dictionary.
|
---|
196 | """
|
---|
197 | import re
|
---|
198 | # Regexes needed for parsing Makefile (and similar syntaxes,
|
---|
199 | # like old-style Setup files).
|
---|
200 | _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
|
---|
201 | _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
|
---|
202 | _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
|
---|
203 |
|
---|
204 | if vars is None:
|
---|
205 | vars = {}
|
---|
206 | done = {}
|
---|
207 | notdone = {}
|
---|
208 |
|
---|
209 | with open(filename) as f:
|
---|
210 | lines = f.readlines()
|
---|
211 |
|
---|
212 | for line in lines:
|
---|
213 | if line.startswith('#') or line.strip() == '':
|
---|
214 | continue
|
---|
215 | m = _variable_rx.match(line)
|
---|
216 | if m:
|
---|
217 | n, v = m.group(1, 2)
|
---|
218 | v = v.strip()
|
---|
219 | # `$$' is a literal `$' in make
|
---|
220 | tmpv = v.replace('$$', '')
|
---|
221 |
|
---|
222 | if "$" in tmpv:
|
---|
223 | notdone[n] = v
|
---|
224 | else:
|
---|
225 | try:
|
---|
226 | v = int(v)
|
---|
227 | except ValueError:
|
---|
228 | # insert literal `$'
|
---|
229 | done[n] = v.replace('$$', '$')
|
---|
230 | else:
|
---|
231 | done[n] = v
|
---|
232 |
|
---|
233 | # do variable interpolation here
|
---|
234 | while notdone:
|
---|
235 | for name in notdone.keys():
|
---|
236 | value = notdone[name]
|
---|
237 | m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
|
---|
238 | if m:
|
---|
239 | n = m.group(1)
|
---|
240 | found = True
|
---|
241 | if n in done:
|
---|
242 | item = str(done[n])
|
---|
243 | elif n in notdone:
|
---|
244 | # get it on a subsequent round
|
---|
245 | found = False
|
---|
246 | elif n in os.environ:
|
---|
247 | # do it like make: fall back to environment
|
---|
248 | item = os.environ[n]
|
---|
249 | else:
|
---|
250 | done[n] = item = ""
|
---|
251 | if found:
|
---|
252 | after = value[m.end():]
|
---|
253 | value = value[:m.start()] + item + after
|
---|
254 | if "$" in after:
|
---|
255 | notdone[name] = value
|
---|
256 | else:
|
---|
257 | try: value = int(value)
|
---|
258 | except ValueError:
|
---|
259 | done[name] = value.strip()
|
---|
260 | else:
|
---|
261 | done[name] = value
|
---|
262 | del notdone[name]
|
---|
263 | else:
|
---|
264 | # bogus variable reference; just drop it since we can't deal
|
---|
265 | del notdone[name]
|
---|
266 | # strip spurious spaces
|
---|
267 | for k, v in done.items():
|
---|
268 | if isinstance(v, str):
|
---|
269 | done[k] = v.strip()
|
---|
270 |
|
---|
271 | # save the results in the global dictionary
|
---|
272 | vars.update(done)
|
---|
273 | return vars
|
---|
274 |
|
---|
275 |
|
---|
276 | def _get_makefile_filename():
|
---|
277 | if _PYTHON_BUILD:
|
---|
278 | return os.path.join(_PROJECT_BASE, "Makefile")
|
---|
279 | return os.path.join(get_path('platstdlib'), "config", "Makefile")
|
---|
280 |
|
---|
281 | def _generate_posix_vars():
|
---|
282 | """Generate the Python module containing build-time variables."""
|
---|
283 | import pprint
|
---|
284 | vars = {}
|
---|
285 | # load the installed Makefile:
|
---|
286 | makefile = _get_makefile_filename()
|
---|
287 | try:
|
---|
288 | _parse_makefile(makefile, vars)
|
---|
289 | except IOError, e:
|
---|
290 | msg = "invalid Python installation: unable to open %s" % makefile
|
---|
291 | if hasattr(e, "strerror"):
|
---|
292 | msg = msg + " (%s)" % e.strerror
|
---|
293 | raise IOError(msg)
|
---|
294 |
|
---|
295 | # load the installed pyconfig.h:
|
---|
296 | config_h = get_config_h_filename()
|
---|
297 | try:
|
---|
298 | with open(config_h) as f:
|
---|
299 | parse_config_h(f, vars)
|
---|
300 | except IOError, e:
|
---|
301 | msg = "invalid Python installation: unable to open %s" % config_h
|
---|
302 | if hasattr(e, "strerror"):
|
---|
303 | msg = msg + " (%s)" % e.strerror
|
---|
304 | raise IOError(msg)
|
---|
305 |
|
---|
306 | # On AIX, there are wrong paths to the linker scripts in the Makefile
|
---|
307 | # -- these paths are relative to the Python source, but when installed
|
---|
308 | # the scripts are in another directory.
|
---|
309 | if _PYTHON_BUILD:
|
---|
310 | vars['LDSHARED'] = vars['BLDSHARED']
|
---|
311 |
|
---|
312 | # There's a chicken-and-egg situation on OS X with regards to the
|
---|
313 | # _sysconfigdata module after the changes introduced by #15298:
|
---|
314 | # get_config_vars() is called by get_platform() as part of the
|
---|
315 | # `make pybuilddir.txt` target -- which is a precursor to the
|
---|
316 | # _sysconfigdata.py module being constructed. Unfortunately,
|
---|
317 | # get_config_vars() eventually calls _init_posix(), which attempts
|
---|
318 | # to import _sysconfigdata, which we won't have built yet. In order
|
---|
319 | # for _init_posix() to work, if we're on Darwin, just mock up the
|
---|
320 | # _sysconfigdata module manually and populate it with the build vars.
|
---|
321 | # This is more than sufficient for ensuring the subsequent call to
|
---|
322 | # get_platform() succeeds.
|
---|
323 | name = '_sysconfigdata'
|
---|
324 | if 'darwin' in sys.platform:
|
---|
325 | import imp
|
---|
326 | module = imp.new_module(name)
|
---|
327 | module.build_time_vars = vars
|
---|
328 | sys.modules[name] = module
|
---|
329 |
|
---|
330 | pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version[:3])
|
---|
331 | if hasattr(sys, "gettotalrefcount"):
|
---|
332 | pybuilddir += '-pydebug'
|
---|
333 | try:
|
---|
334 | os.makedirs(pybuilddir)
|
---|
335 | except OSError:
|
---|
336 | pass
|
---|
337 | destfile = os.path.join(pybuilddir, name + '.py')
|
---|
338 |
|
---|
339 | with open(destfile, 'wb') as f:
|
---|
340 | f.write('# system configuration generated and used by'
|
---|
341 | ' the sysconfig module\n')
|
---|
342 | f.write('build_time_vars = ')
|
---|
343 | pprint.pprint(vars, stream=f)
|
---|
344 |
|
---|
345 | # Create file used for sys.path fixup -- see Modules/getpath.c
|
---|
346 | with open('pybuilddir.txt', 'w') as f:
|
---|
347 | f.write(pybuilddir)
|
---|
348 |
|
---|
349 | def _init_posix(vars):
|
---|
350 | """Initialize the module as appropriate for POSIX systems."""
|
---|
351 | # _sysconfigdata is generated at build time, see _generate_posix_vars()
|
---|
352 | from _sysconfigdata import build_time_vars
|
---|
353 | vars.update(build_time_vars)
|
---|
354 |
|
---|
355 | def _init_non_posix(vars):
|
---|
356 | """Initialize the module as appropriate for NT"""
|
---|
357 | # set basic install directories
|
---|
358 | vars['LIBDEST'] = get_path('stdlib')
|
---|
359 | vars['BINLIBDEST'] = get_path('platstdlib')
|
---|
360 | vars['INCLUDEPY'] = get_path('include')
|
---|
361 | vars['SO'] = '.pyd'
|
---|
362 | vars['EXE'] = '.exe'
|
---|
363 | vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
|
---|
364 | vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
|
---|
365 |
|
---|
366 | #
|
---|
367 | # public APIs
|
---|
368 | #
|
---|
369 |
|
---|
370 |
|
---|
371 | def parse_config_h(fp, vars=None):
|
---|
372 | """Parse a config.h-style file.
|
---|
373 |
|
---|
374 | A dictionary containing name/value pairs is returned. If an
|
---|
375 | optional dictionary is passed in as the second argument, it is
|
---|
376 | used instead of a new dictionary.
|
---|
377 | """
|
---|
378 | import re
|
---|
379 | if vars is None:
|
---|
380 | vars = {}
|
---|
381 | define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
|
---|
382 | undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
|
---|
383 |
|
---|
384 | while True:
|
---|
385 | line = fp.readline()
|
---|
386 | if not line:
|
---|
387 | break
|
---|
388 | m = define_rx.match(line)
|
---|
389 | if m:
|
---|
390 | n, v = m.group(1, 2)
|
---|
391 | try: v = int(v)
|
---|
392 | except ValueError: pass
|
---|
393 | vars[n] = v
|
---|
394 | else:
|
---|
395 | m = undef_rx.match(line)
|
---|
396 | if m:
|
---|
397 | vars[m.group(1)] = 0
|
---|
398 | return vars
|
---|
399 |
|
---|
400 | def get_config_h_filename():
|
---|
401 | """Returns the path of pyconfig.h."""
|
---|
402 | if _PYTHON_BUILD:
|
---|
403 | if os.name == "nt":
|
---|
404 | inc_dir = os.path.join(_PROJECT_BASE, "PC")
|
---|
405 | else:
|
---|
406 | inc_dir = _PROJECT_BASE
|
---|
407 | else:
|
---|
408 | inc_dir = get_path('platinclude')
|
---|
409 | return os.path.join(inc_dir, 'pyconfig.h')
|
---|
410 |
|
---|
411 | def get_scheme_names():
|
---|
412 | """Returns a tuple containing the schemes names."""
|
---|
413 | schemes = _INSTALL_SCHEMES.keys()
|
---|
414 | schemes.sort()
|
---|
415 | return tuple(schemes)
|
---|
416 |
|
---|
417 | def get_path_names():
|
---|
418 | """Returns a tuple containing the paths names."""
|
---|
419 | return _SCHEME_KEYS
|
---|
420 |
|
---|
421 | def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
|
---|
422 | """Returns a mapping containing an install scheme.
|
---|
423 |
|
---|
424 | ``scheme`` is the install scheme name. If not provided, it will
|
---|
425 | return the default scheme for the current platform.
|
---|
426 | """
|
---|
427 | if expand:
|
---|
428 | return _expand_vars(scheme, vars)
|
---|
429 | else:
|
---|
430 | return _INSTALL_SCHEMES[scheme]
|
---|
431 |
|
---|
432 | def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
|
---|
433 | """Returns a path corresponding to the scheme.
|
---|
434 |
|
---|
435 | ``scheme`` is the install scheme name.
|
---|
436 | """
|
---|
437 | return get_paths(scheme, vars, expand)[name]
|
---|
438 |
|
---|
439 | def get_config_vars(*args):
|
---|
440 | """With no arguments, return a dictionary of all configuration
|
---|
441 | variables relevant for the current platform.
|
---|
442 |
|
---|
443 | On Unix, this means every variable defined in Python's installed Makefile;
|
---|
444 | On Windows and Mac OS it's a much smaller set.
|
---|
445 |
|
---|
446 | With arguments, return a list of values that result from looking up
|
---|
447 | each argument in the configuration variable dictionary.
|
---|
448 | """
|
---|
449 | import re
|
---|
450 | global _CONFIG_VARS
|
---|
451 | if _CONFIG_VARS is None:
|
---|
452 | _CONFIG_VARS = {}
|
---|
453 | # Normalized versions of prefix and exec_prefix are handy to have;
|
---|
454 | # in fact, these are the standard versions used most places in the
|
---|
455 | # Distutils.
|
---|
456 | _CONFIG_VARS['prefix'] = _PREFIX
|
---|
457 | _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
|
---|
458 | _CONFIG_VARS['py_version'] = _PY_VERSION
|
---|
459 | _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
|
---|
460 | _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
|
---|
461 | _CONFIG_VARS['base'] = _PREFIX
|
---|
462 | _CONFIG_VARS['platbase'] = _EXEC_PREFIX
|
---|
463 | _CONFIG_VARS['projectbase'] = _PROJECT_BASE
|
---|
464 |
|
---|
465 | if os.name in ('nt', 'os2'):
|
---|
466 | _init_non_posix(_CONFIG_VARS)
|
---|
467 | if os.name == 'posix':
|
---|
468 | _init_posix(_CONFIG_VARS)
|
---|
469 |
|
---|
470 | # Setting 'userbase' is done below the call to the
|
---|
471 | # init function to enable using 'get_config_var' in
|
---|
472 | # the init-function.
|
---|
473 | _CONFIG_VARS['userbase'] = _getuserbase()
|
---|
474 |
|
---|
475 | if 'srcdir' not in _CONFIG_VARS:
|
---|
476 | _CONFIG_VARS['srcdir'] = _PROJECT_BASE
|
---|
477 |
|
---|
478 | # Convert srcdir into an absolute path if it appears necessary.
|
---|
479 | # Normally it is relative to the build directory. However, during
|
---|
480 | # testing, for example, we might be running a non-installed python
|
---|
481 | # from a different directory.
|
---|
482 | if _PYTHON_BUILD and os.name == "posix":
|
---|
483 | base = _PROJECT_BASE
|
---|
484 | try:
|
---|
485 | cwd = os.getcwd()
|
---|
486 | except OSError:
|
---|
487 | cwd = None
|
---|
488 | if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
|
---|
489 | base != cwd):
|
---|
490 | # srcdir is relative and we are not in the same directory
|
---|
491 | # as the executable. Assume executable is in the build
|
---|
492 | # directory and make srcdir absolute.
|
---|
493 | srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
|
---|
494 | _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
|
---|
495 |
|
---|
496 | # OS X platforms require special customization to handle
|
---|
497 | # multi-architecture, multi-os-version installers
|
---|
498 | if sys.platform == 'darwin':
|
---|
499 | import _osx_support
|
---|
500 | _osx_support.customize_config_vars(_CONFIG_VARS)
|
---|
501 |
|
---|
502 | if args:
|
---|
503 | vals = []
|
---|
504 | for name in args:
|
---|
505 | vals.append(_CONFIG_VARS.get(name))
|
---|
506 | return vals
|
---|
507 | else:
|
---|
508 | return _CONFIG_VARS
|
---|
509 |
|
---|
510 | def get_config_var(name):
|
---|
511 | """Return the value of a single variable using the dictionary returned by
|
---|
512 | 'get_config_vars()'.
|
---|
513 |
|
---|
514 | Equivalent to get_config_vars().get(name)
|
---|
515 | """
|
---|
516 | return get_config_vars().get(name)
|
---|
517 |
|
---|
518 | def get_platform():
|
---|
519 | """Return a string that identifies the current platform.
|
---|
520 |
|
---|
521 | This is used mainly to distinguish platform-specific build directories and
|
---|
522 | platform-specific built distributions. Typically includes the OS name
|
---|
523 | and version and the architecture (as supplied by 'os.uname()'),
|
---|
524 | although the exact information included depends on the OS; eg. for IRIX
|
---|
525 | the architecture isn't particularly important (IRIX only runs on SGI
|
---|
526 | hardware), but for Linux the kernel version isn't particularly
|
---|
527 | important.
|
---|
528 |
|
---|
529 | Examples of returned values:
|
---|
530 | linux-i586
|
---|
531 | linux-alpha (?)
|
---|
532 | solaris-2.6-sun4u
|
---|
533 | irix-5.3
|
---|
534 | irix64-6.2
|
---|
535 |
|
---|
536 | Windows will return one of:
|
---|
537 | win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
|
---|
538 | win-ia64 (64bit Windows on Itanium)
|
---|
539 | win32 (all others - specifically, sys.platform is returned)
|
---|
540 |
|
---|
541 | For other non-POSIX platforms, currently just returns 'sys.platform'.
|
---|
542 | """
|
---|
543 | import re
|
---|
544 | if os.name == 'nt':
|
---|
545 | # sniff sys.version for architecture.
|
---|
546 | prefix = " bit ("
|
---|
547 | i = sys.version.find(prefix)
|
---|
548 | if i == -1:
|
---|
549 | return sys.platform
|
---|
550 | j = sys.version.find(")", i)
|
---|
551 | look = sys.version[i+len(prefix):j].lower()
|
---|
552 | if look == 'amd64':
|
---|
553 | return 'win-amd64'
|
---|
554 | if look == 'itanium':
|
---|
555 | return 'win-ia64'
|
---|
556 | return sys.platform
|
---|
557 |
|
---|
558 | # Set for cross builds explicitly
|
---|
559 | if "_PYTHON_HOST_PLATFORM" in os.environ:
|
---|
560 | return os.environ["_PYTHON_HOST_PLATFORM"]
|
---|
561 |
|
---|
562 | if os.name != "posix" or not hasattr(os, 'uname'):
|
---|
563 | # XXX what about the architecture? NT is Intel or Alpha,
|
---|
564 | # Mac OS is M68k or PPC, etc.
|
---|
565 | return sys.platform
|
---|
566 |
|
---|
567 | # Try to distinguish various flavours of Unix
|
---|
568 | osname, host, release, version, machine = os.uname()
|
---|
569 |
|
---|
570 | # Convert the OS name to lowercase, remove '/' characters
|
---|
571 | # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
|
---|
572 | osname = osname.lower().replace('/', '')
|
---|
573 | machine = machine.replace(' ', '_')
|
---|
574 | machine = machine.replace('/', '-')
|
---|
575 |
|
---|
576 | if osname[:5] == "linux":
|
---|
577 | # At least on Linux/Intel, 'machine' is the processor --
|
---|
578 | # i386, etc.
|
---|
579 | # XXX what about Alpha, SPARC, etc?
|
---|
580 | return "%s-%s" % (osname, machine)
|
---|
581 | elif osname[:5] == "sunos":
|
---|
582 | if release[0] >= "5": # SunOS 5 == Solaris 2
|
---|
583 | osname = "solaris"
|
---|
584 | release = "%d.%s" % (int(release[0]) - 3, release[2:])
|
---|
585 | # We can't use "platform.architecture()[0]" because a
|
---|
586 | # bootstrap problem. We use a dict to get an error
|
---|
587 | # if some suspicious happens.
|
---|
588 | bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
|
---|
589 | machine += ".%s" % bitness[sys.maxint]
|
---|
590 | # fall through to standard osname-release-machine representation
|
---|
591 | elif osname[:4] == "irix": # could be "irix64"!
|
---|
592 | return "%s-%s" % (osname, release)
|
---|
593 | elif osname[:3] == "aix":
|
---|
594 | return "%s-%s.%s" % (osname, version, release)
|
---|
595 | elif osname[:6] == "cygwin":
|
---|
596 | osname = "cygwin"
|
---|
597 | rel_re = re.compile (r'[\d.]+')
|
---|
598 | m = rel_re.match(release)
|
---|
599 | if m:
|
---|
600 | release = m.group()
|
---|
601 | elif osname[:6] == "darwin":
|
---|
602 | import _osx_support
|
---|
603 | osname, release, machine = _osx_support.get_platform_osx(
|
---|
604 | get_config_vars(),
|
---|
605 | osname, release, machine)
|
---|
606 |
|
---|
607 | return "%s-%s-%s" % (osname, release, machine)
|
---|
608 |
|
---|
609 |
|
---|
610 | def get_python_version():
|
---|
611 | return _PY_VERSION_SHORT
|
---|
612 |
|
---|
613 |
|
---|
614 | def _print_dict(title, data):
|
---|
615 | for index, (key, value) in enumerate(sorted(data.items())):
|
---|
616 | if index == 0:
|
---|
617 | print '%s: ' % (title)
|
---|
618 | print '\t%s = "%s"' % (key, value)
|
---|
619 |
|
---|
620 |
|
---|
621 | def _main():
|
---|
622 | """Display all information sysconfig detains."""
|
---|
623 | if '--generate-posix-vars' in sys.argv:
|
---|
624 | _generate_posix_vars()
|
---|
625 | return
|
---|
626 | print 'Platform: "%s"' % get_platform()
|
---|
627 | print 'Python version: "%s"' % get_python_version()
|
---|
628 | print 'Current installation scheme: "%s"' % _get_default_scheme()
|
---|
629 | print
|
---|
630 | _print_dict('Paths', get_paths())
|
---|
631 | print
|
---|
632 | _print_dict('Variables', get_config_vars())
|
---|
633 |
|
---|
634 |
|
---|
635 | if __name__ == '__main__':
|
---|
636 | _main()
|
---|