Index: Lib/platform.py =================================================================== --- Lib/platform.py (revision 66520) +++ Lib/platform.py (working copy) @@ -109,7 +109,7 @@ __version__ = '1.0.4' -import sys,string,os,re +import subprocess,sys,string,os,re ### Platform specific APIs @@ -217,13 +217,99 @@ return distname,version,id +_distributor_id_cmdline_re = re.compile("(?:Distributor ID:)\s*(.*)", re.I) +_release_cmdline_re = re.compile("(?:Release:)\s*(.*)", re.I) +_codename_cmdline_re = re.compile("(?:Codename:)\s*(.*)", re.I) + +_distributor_id_file_re = re.compile("(?:DISTRIB_ID\s*=)\s*(.*)", re.I) +_release_file_re = re.compile("(?:DISTRIB_RELEASE\s*=)\s*(.*)", re.I) +_codename_file_re = re.compile("(?:DISTRIB_CODENAME\s*=)\s*(.*)", re.I) + +def dist(distname='',version='',id=''): + """ Tries to determine the name of the Linux OS distribution name. + + First, try to parse a file named "/etc/lsb-release". If it exists, and + contains the "DISTRIB_ID=" line and the "DISTRIB_RELEASE=" line, then return + the strings parsed from that file. The reason we try this first is because + it is faster than the official method of invoking "lsb_release" (which takes + half a second on my high-performance Athlon64 Ubuntu workstation). Also + because some distributions (at least Debian/Ubuntu) have /etc/lsb-release in + the "base-files" package (Priority: required) but /usr/bin/lsb_release in + the "lsb-release" package (Priority: important), so it is possible that + /etc/lsb-release is there even if /usr/bin/lsb_release isn't. + + If parsing /etc/lsb-release doesn't work, then try to execute "lsb_release", + as standardized in 2001: + + http://refspecs.freestandards.org/LSB_1.0.0/gLSB/lsbrelease.html + + The current version of the standard is here: + + http://refspecs.freestandards.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/lsbrelease.html + + If executing "lsb_release" raises no exception, and returns exit code 0, and + both the "distributor id" and "release" results are non-empty after being + stripped of whitespace, then return a two-tuple containing the information + that lsb_release emitted, as strings. + + If that doesn't work, then invoke _dist_try_a_little_harder() and return + whatever it returns. + + Returns a tuple (distname,version,id). Distname is what LSB calls a + "distributor id", e.g. "Ubuntu". Version is what LSB calls a "release", + e.g. "8.04". ID is what LSB calls a "codename", e.g. "hardy". + """ + _distname = None + _version = None + _id = None + + try: + etclsbrel = open("/etc/lsb-release", "rU") + for line in etclsbrel: + m = _distributor_id_file_re.search(line) + if m: + _distname = m.group(1).strip() + m = _release_file_re.search(line) + if m: + _version = m.group(1).strip() + m = _codename_file_re.search(line) + if m: + _id = m.group(1).strip() + if _distname and _version: + return (_distname, _version,_id) + except EnvironmentError: + pass + + try: + p = subprocess.Popen(["lsb_release", "--all"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + rc = p.wait() + if rc == 0: + for line in p.stdout.readlines(): + m = _distributor_id_cmdline_re.search(line) + if m: + _distname = m.group(1).strip() + m = _release_cmdline_re.search(p.stdout.read()) + if m: + _version = m.group(1).strip() + m = _codename_cmdline_re.search(p.stdout.read()) + if m: + _id = m.group(1).strip() + + if _distname and _version: + return (_distname, _version,_id) + except EnvironmentError: + pass + + return _dist_try_a_little_harder(distname, version, id) + + _release_filename = re.compile(r'(\w+)[-_](release|version)') _release_version = re.compile(r'([\d.]+)[^(]*(?:\((.+)\))?') # Note:In supported_dists below we need 'fedora' before 'redhat' as in # Fedora redhat-release is a link to fedora-release. -def dist(distname='',version='',id='', +def _dist_try_a_little_harder(distname='',version='',id='', supported_dists=('SuSE', 'debian', 'fedora', 'redhat', 'mandrake')):