blob: d74ca391c6446bac7576a50ed30f6992c3d2cbd7 [file] [log] [blame]
Tarek Ziadé5633a802010-01-23 09:23:15 +00001"""Provide access to Python's configuration information.
2
3"""
4import sys
5import os
Florent Xicluna85677612010-03-10 23:58:42 +00006from os.path import pardir, realpath
Tarek Ziadé5633a802010-01-23 09:23:15 +00007
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': {
Tarek Ziadé8f692272010-05-19 22:20:14 +000050 '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',
Tarek Ziadé5633a802010-01-23 09:23:15 +000054 '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': {
Tarek Ziadé8f692272010-05-19 22:20:14 +000068 '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',
Tarek Ziadé5633a802010-01-23 09:23:15 +000072 'include': '{userbase}/include/python{py_version_short}',
73 'scripts': '{userbase}/bin',
74 'data' : '{userbase}',
75 },
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +000076 '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 },
Tarek Ziadé5633a802010-01-23 09:23:15 +000085 }
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
Victor Stinnerd2f6ae62010-10-12 22:53:51 +000096
97def _safe_realpath(path):
98 try:
99 return realpath(path)
100 except OSError:
101 return path
102
Victor Stinner4a7e0c852010-03-11 12:34:39 +0000103if sys.executable:
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000104 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner4a7e0c852010-03-11 12:34:39 +0000105else:
106 # sys.executable can be empty if argv[0] has been changed and Python is
107 # unable to retrieve the real program name
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000108 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadé5633a802010-01-23 09:23:15 +0000109
110if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000111 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000112# PC/VS7.1
113if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000114 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000115# PC/AMD64
116if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000117 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000118
doko@python.orgd65e2ba2013-01-31 23:52:03 +0100119# 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("."))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000123def 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
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +0000180 if sys.platform == "darwin":
181 framework = get_config_var("PYTHONFRAMEWORK")
182 if framework:
Ned Deily2c8bf042012-02-06 00:55:50 +0100183 return env_base if env_base else \
184 joinuser("~", "Library", framework, "%d.%d"
185 % (sys.version_info[:2]))
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +0000186
Tarek Ziadé5633a802010-01-23 09:23:15 +0000187 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]
Antoine Pitrou58dab672010-10-10 09:54:59 +0000266 # strip spurious spaces
267 for k, v in done.items():
268 if isinstance(v, str):
269 done[k] = v.strip()
270
Tarek Ziadé5633a802010-01-23 09:23:15 +0000271 # save the results in the global dictionary
272 vars.update(done)
273 return vars
274
Tarek Ziadé5633a802010-01-23 09:23:15 +0000275
276def _get_makefile_filename():
277 if _PYTHON_BUILD:
278 return os.path.join(_PROJECT_BASE, "Makefile")
Barry Warsaw42bb7ca2011-02-14 20:04:00 +0000279 return os.path.join(get_path('platstdlib'), "config", "Makefile")
Tarek Ziadé5633a802010-01-23 09:23:15 +0000280
Tarek Ziadé5633a802010-01-23 09:23:15 +0000281
282def _init_posix(vars):
283 """Initialize the module as appropriate for POSIX systems."""
284 # load the installed Makefile:
285 makefile = _get_makefile_filename()
286 try:
287 _parse_makefile(makefile, vars)
288 except IOError, e:
289 msg = "invalid Python installation: unable to open %s" % makefile
290 if hasattr(e, "strerror"):
291 msg = msg + " (%s)" % e.strerror
292 raise IOError(msg)
293
294 # load the installed pyconfig.h:
295 config_h = get_config_h_filename()
296 try:
Antoine Pitrouf7c24452010-10-14 21:22:52 +0000297 with open(config_h) as f:
298 parse_config_h(f, vars)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000299 except IOError, e:
300 msg = "invalid Python installation: unable to open %s" % config_h
301 if hasattr(e, "strerror"):
302 msg = msg + " (%s)" % e.strerror
303 raise IOError(msg)
304
Tarek Ziadé5633a802010-01-23 09:23:15 +0000305 # On AIX, there are wrong paths to the linker scripts in the Makefile
306 # -- these paths are relative to the Python source, but when installed
307 # the scripts are in another directory.
308 if _PYTHON_BUILD:
309 vars['LDSHARED'] = vars['BLDSHARED']
310
311def _init_non_posix(vars):
312 """Initialize the module as appropriate for NT"""
313 # set basic install directories
314 vars['LIBDEST'] = get_path('stdlib')
315 vars['BINLIBDEST'] = get_path('platstdlib')
316 vars['INCLUDEPY'] = get_path('include')
317 vars['SO'] = '.pyd'
318 vars['EXE'] = '.exe'
319 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000320 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000321
322#
323# public APIs
324#
325
Tarek Ziadécc118172010-02-02 22:50:23 +0000326
327def parse_config_h(fp, vars=None):
328 """Parse a config.h-style file.
329
330 A dictionary containing name/value pairs is returned. If an
331 optional dictionary is passed in as the second argument, it is
332 used instead of a new dictionary.
333 """
334 import re
335 if vars is None:
336 vars = {}
337 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
338 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
339
340 while True:
341 line = fp.readline()
342 if not line:
343 break
344 m = define_rx.match(line)
345 if m:
346 n, v = m.group(1, 2)
347 try: v = int(v)
348 except ValueError: pass
349 vars[n] = v
350 else:
351 m = undef_rx.match(line)
352 if m:
353 vars[m.group(1)] = 0
354 return vars
355
356def get_config_h_filename():
357 """Returns the path of pyconfig.h."""
358 if _PYTHON_BUILD:
359 if os.name == "nt":
360 inc_dir = os.path.join(_PROJECT_BASE, "PC")
361 else:
362 inc_dir = _PROJECT_BASE
363 else:
364 inc_dir = get_path('platinclude')
365 return os.path.join(inc_dir, 'pyconfig.h')
366
Tarek Ziadé5633a802010-01-23 09:23:15 +0000367def get_scheme_names():
Tarek Ziadécc118172010-02-02 22:50:23 +0000368 """Returns a tuple containing the schemes names."""
Tarek Ziadée81b0282010-02-02 22:54:28 +0000369 schemes = _INSTALL_SCHEMES.keys()
370 schemes.sort()
371 return tuple(schemes)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000372
373def get_path_names():
Tarek Ziadécc118172010-02-02 22:50:23 +0000374 """Returns a tuple containing the paths names."""
Tarek Ziadé5633a802010-01-23 09:23:15 +0000375 return _SCHEME_KEYS
376
377def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
378 """Returns a mapping containing an install scheme.
379
380 ``scheme`` is the install scheme name. If not provided, it will
381 return the default scheme for the current platform.
382 """
383 if expand:
384 return _expand_vars(scheme, vars)
385 else:
386 return _INSTALL_SCHEMES[scheme]
387
388def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
389 """Returns a path corresponding to the scheme.
390
391 ``scheme`` is the install scheme name.
392 """
393 return get_paths(scheme, vars, expand)[name]
394
395def get_config_vars(*args):
396 """With no arguments, return a dictionary of all configuration
397 variables relevant for the current platform.
398
399 On Unix, this means every variable defined in Python's installed Makefile;
400 On Windows and Mac OS it's a much smaller set.
401
402 With arguments, return a list of values that result from looking up
403 each argument in the configuration variable dictionary.
404 """
405 import re
406 global _CONFIG_VARS
407 if _CONFIG_VARS is None:
408 _CONFIG_VARS = {}
409 # Normalized versions of prefix and exec_prefix are handy to have;
410 # in fact, these are the standard versions used most places in the
411 # Distutils.
412 _CONFIG_VARS['prefix'] = _PREFIX
413 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
414 _CONFIG_VARS['py_version'] = _PY_VERSION
415 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
416 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
417 _CONFIG_VARS['base'] = _PREFIX
418 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadé5633a802010-01-23 09:23:15 +0000419 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
420
421 if os.name in ('nt', 'os2'):
422 _init_non_posix(_CONFIG_VARS)
423 if os.name == 'posix':
424 _init_posix(_CONFIG_VARS)
425
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +0000426 # Setting 'userbase' is done below the call to the
427 # init function to enable using 'get_config_var' in
428 # the init-function.
429 _CONFIG_VARS['userbase'] = _getuserbase()
430
Tarek Ziadé5633a802010-01-23 09:23:15 +0000431 if 'srcdir' not in _CONFIG_VARS:
432 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
433
434 # Convert srcdir into an absolute path if it appears necessary.
435 # Normally it is relative to the build directory. However, during
436 # testing, for example, we might be running a non-installed python
437 # from a different directory.
438 if _PYTHON_BUILD and os.name == "posix":
439 base = _PROJECT_BASE
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000440 try:
441 cwd = os.getcwd()
442 except OSError:
443 cwd = None
Tarek Ziadé5633a802010-01-23 09:23:15 +0000444 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000445 base != cwd):
Tarek Ziadé5633a802010-01-23 09:23:15 +0000446 # srcdir is relative and we are not in the same directory
447 # as the executable. Assume executable is in the build
448 # directory and make srcdir absolute.
449 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
450 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
451
Ned Deily18fae3f2013-01-31 01:24:55 -0800452 # OS X platforms require special customization to handle
453 # multi-architecture, multi-os-version installers
Tarek Ziadé5633a802010-01-23 09:23:15 +0000454 if sys.platform == 'darwin':
Ned Deily18fae3f2013-01-31 01:24:55 -0800455 import _osx_support
456 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000457
458 if args:
459 vals = []
460 for name in args:
461 vals.append(_CONFIG_VARS.get(name))
462 return vals
463 else:
464 return _CONFIG_VARS
465
466def get_config_var(name):
467 """Return the value of a single variable using the dictionary returned by
468 'get_config_vars()'.
469
470 Equivalent to get_config_vars().get(name)
471 """
472 return get_config_vars().get(name)
473
474def get_platform():
475 """Return a string that identifies the current platform.
476
477 This is used mainly to distinguish platform-specific build directories and
478 platform-specific built distributions. Typically includes the OS name
479 and version and the architecture (as supplied by 'os.uname()'),
480 although the exact information included depends on the OS; eg. for IRIX
481 the architecture isn't particularly important (IRIX only runs on SGI
482 hardware), but for Linux the kernel version isn't particularly
483 important.
484
485 Examples of returned values:
486 linux-i586
487 linux-alpha (?)
488 solaris-2.6-sun4u
489 irix-5.3
490 irix64-6.2
491
492 Windows will return one of:
493 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
494 win-ia64 (64bit Windows on Itanium)
495 win32 (all others - specifically, sys.platform is returned)
496
497 For other non-POSIX platforms, currently just returns 'sys.platform'.
498 """
499 import re
500 if os.name == 'nt':
501 # sniff sys.version for architecture.
502 prefix = " bit ("
503 i = sys.version.find(prefix)
504 if i == -1:
505 return sys.platform
506 j = sys.version.find(")", i)
507 look = sys.version[i+len(prefix):j].lower()
508 if look == 'amd64':
509 return 'win-amd64'
510 if look == 'itanium':
511 return 'win-ia64'
512 return sys.platform
513
doko@python.orgd65e2ba2013-01-31 23:52:03 +0100514 # Set for cross builds explicitly
515 if "_PYTHON_HOST_PLATFORM" in os.environ:
516 return os.environ["_PYTHON_HOST_PLATFORM"]
517
Tarek Ziadé5633a802010-01-23 09:23:15 +0000518 if os.name != "posix" or not hasattr(os, 'uname'):
519 # XXX what about the architecture? NT is Intel or Alpha,
520 # Mac OS is M68k or PPC, etc.
521 return sys.platform
522
523 # Try to distinguish various flavours of Unix
524 osname, host, release, version, machine = os.uname()
525
526 # Convert the OS name to lowercase, remove '/' characters
527 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
528 osname = osname.lower().replace('/', '')
529 machine = machine.replace(' ', '_')
530 machine = machine.replace('/', '-')
531
532 if osname[:5] == "linux":
533 # At least on Linux/Intel, 'machine' is the processor --
534 # i386, etc.
535 # XXX what about Alpha, SPARC, etc?
536 return "%s-%s" % (osname, machine)
537 elif osname[:5] == "sunos":
538 if release[0] >= "5": # SunOS 5 == Solaris 2
539 osname = "solaris"
540 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Ceaa8f75da2012-01-18 04:43:50 +0100541 # We can't use "platform.architecture()[0]" because a
542 # bootstrap problem. We use a dict to get an error
543 # if some suspicious happens.
544 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
545 machine += ".%s" % bitness[sys.maxint]
Tarek Ziadé5633a802010-01-23 09:23:15 +0000546 # fall through to standard osname-release-machine representation
547 elif osname[:4] == "irix": # could be "irix64"!
548 return "%s-%s" % (osname, release)
549 elif osname[:3] == "aix":
550 return "%s-%s.%s" % (osname, version, release)
551 elif osname[:6] == "cygwin":
552 osname = "cygwin"
553 rel_re = re.compile (r'[\d.]+')
554 m = rel_re.match(release)
555 if m:
556 release = m.group()
557 elif osname[:6] == "darwin":
Ned Deily18fae3f2013-01-31 01:24:55 -0800558 import _osx_support
559 osname, release, machine = _osx_support.get_platform_osx(
560 get_config_vars(),
561 osname, release, machine)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000562
563 return "%s-%s-%s" % (osname, release, machine)
564
565
566def get_python_version():
567 return _PY_VERSION_SHORT