source: python/vendor/Python-2.7.6/Lib/sysconfig.py

Last change on this file was 388, checked in by dmik, 11 years ago

python: Update vendor to 2.7.6.

  • Property svn:eol-style set to native
File size: 21.9 KB
Line 
1"""Provide access to Python's configuration information.
2
3"""
4import sys
5import os
6from 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
97def _safe_realpath(path):
98 try:
99 return realpath(path)
100 except OSError:
101 return path
102
103if sys.executable:
104 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
105else:
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
110if 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
113if 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
116if 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
120if "_PYTHON_PROJECT_BASE" in os.environ:
121 # the build directory for posix builds
122 _PROJECT_BASE = os.path.normpath(os.path.abspath("."))
123def 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
131if _PYTHON_BUILD:
132 for scheme in ('posix_prefix', 'posix_home'):
133 _INSTALL_SCHEMES[scheme]['include'] = '{projectbase}/Include'
134 _INSTALL_SCHEMES[scheme]['platinclude'] = '{srcdir}'
135
136def _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
145def _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
152def _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
164def _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
170def _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
190def _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
276def _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
281def _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
349def _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
355def _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
371def 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
400def 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
411def get_scheme_names():
412 """Returns a tuple containing the schemes names."""
413 schemes = _INSTALL_SCHEMES.keys()
414 schemes.sort()
415 return tuple(schemes)
416
417def get_path_names():
418 """Returns a tuple containing the paths names."""
419 return _SCHEME_KEYS
420
421def 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
432def 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
439def 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
510def 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
518def 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
610def get_python_version():
611 return _PY_VERSION_SHORT
612
613
614def _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
621def _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
635if __name__ == '__main__':
636 _main()
Note: See TracBrowser for help on using the repository browser.