Update external distro package to 1.0.1 (#2381)
This commit is contained in:
parent
1901b05b9c
commit
f351e4402c
1 changed files with 92 additions and 60 deletions
152
lib/spack/external/distro.py
vendored
152
lib/spack/external/distro.py
vendored
|
@ -31,14 +31,16 @@
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import shlex
|
||||
import logging
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
|
||||
if not sys.platform.startswith('linux'):
|
||||
raise ImportError('Unsupported platform: {0}'.format(sys.platform))
|
||||
|
||||
|
||||
_UNIXCONFDIR = '/etc'
|
||||
_OS_RELEASE_BASENAME = 'os-release'
|
||||
|
||||
|
@ -75,7 +77,6 @@
|
|||
'redhat': 'rhel', # RHEL 6.x, 7.x
|
||||
}
|
||||
|
||||
|
||||
# Pattern for content of distro release file (reversed)
|
||||
_DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile(
|
||||
r'(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)')
|
||||
|
@ -119,7 +120,7 @@ def linux_distribution(full_distribution_name=True):
|
|||
method normalizes the distro ID string to a reliable machine-readable value
|
||||
for a number of popular Linux distributions.
|
||||
"""
|
||||
return _distroi.linux_distribution(full_distribution_name)
|
||||
return _distro.linux_distribution(full_distribution_name)
|
||||
|
||||
|
||||
def id():
|
||||
|
@ -194,7 +195,7 @@ def id():
|
|||
command, with ID values that differ from what was previously determined
|
||||
from the distro release file name.
|
||||
"""
|
||||
return _distroi.id()
|
||||
return _distro.id()
|
||||
|
||||
|
||||
def name(pretty=False):
|
||||
|
@ -233,7 +234,7 @@ def name(pretty=False):
|
|||
with the value of the pretty version ("<version_id>" and "<codename>"
|
||||
fields) of the distro release file, if available.
|
||||
"""
|
||||
return _distroi.name(pretty)
|
||||
return _distro.name(pretty)
|
||||
|
||||
|
||||
def version(pretty=False, best=False):
|
||||
|
@ -277,7 +278,7 @@ def version(pretty=False, best=False):
|
|||
the lsb_release command, if it follows the format of the distro release
|
||||
files.
|
||||
"""
|
||||
return _distroi.version(pretty, best)
|
||||
return _distro.version(pretty, best)
|
||||
|
||||
|
||||
def version_parts(best=False):
|
||||
|
@ -294,7 +295,7 @@ def version_parts(best=False):
|
|||
For a description of the *best* parameter, see the :func:`distro.version`
|
||||
method.
|
||||
"""
|
||||
return _distroi.version_parts(best)
|
||||
return _distro.version_parts(best)
|
||||
|
||||
|
||||
def major_version(best=False):
|
||||
|
@ -307,7 +308,7 @@ def major_version(best=False):
|
|||
For a description of the *best* parameter, see the :func:`distro.version`
|
||||
method.
|
||||
"""
|
||||
return _distroi.major_version(best)
|
||||
return _distro.major_version(best)
|
||||
|
||||
|
||||
def minor_version(best=False):
|
||||
|
@ -320,7 +321,7 @@ def minor_version(best=False):
|
|||
For a description of the *best* parameter, see the :func:`distro.version`
|
||||
method.
|
||||
"""
|
||||
return _distroi.minor_version(best)
|
||||
return _distro.minor_version(best)
|
||||
|
||||
|
||||
def build_number(best=False):
|
||||
|
@ -333,7 +334,7 @@ def build_number(best=False):
|
|||
For a description of the *best* parameter, see the :func:`distro.version`
|
||||
method.
|
||||
"""
|
||||
return _distroi.build_number(best)
|
||||
return _distro.build_number(best)
|
||||
|
||||
|
||||
def like():
|
||||
|
@ -350,7 +351,7 @@ def like():
|
|||
`os-release man page
|
||||
<http://www.freedesktop.org/software/systemd/man/os-release.html>`_.
|
||||
"""
|
||||
return _distroi.like()
|
||||
return _distro.like()
|
||||
|
||||
|
||||
def codename():
|
||||
|
@ -374,7 +375,7 @@ def codename():
|
|||
|
||||
* the value of the "<codename>" field of the distro release file.
|
||||
"""
|
||||
return _distroi.codename()
|
||||
return _distro.codename()
|
||||
|
||||
|
||||
def info(pretty=False, best=False):
|
||||
|
@ -418,7 +419,7 @@ def info(pretty=False, best=False):
|
|||
For a description of the *pretty* and *best* parameters, see the
|
||||
:func:`distro.version` method.
|
||||
"""
|
||||
return _distroi.info(pretty, best)
|
||||
return _distro.info(pretty, best)
|
||||
|
||||
|
||||
def os_release_info():
|
||||
|
@ -428,7 +429,7 @@ def os_release_info():
|
|||
|
||||
See `os-release file`_ for details about these information items.
|
||||
"""
|
||||
return _distroi.os_release_info()
|
||||
return _distro.os_release_info()
|
||||
|
||||
|
||||
def lsb_release_info():
|
||||
|
@ -439,7 +440,7 @@ def lsb_release_info():
|
|||
See `lsb_release command output`_ for details about these information
|
||||
items.
|
||||
"""
|
||||
return _distroi.lsb_release_info()
|
||||
return _distro.lsb_release_info()
|
||||
|
||||
|
||||
def distro_release_info():
|
||||
|
@ -449,7 +450,7 @@ def distro_release_info():
|
|||
|
||||
See `distro release file`_ for details about these information items.
|
||||
"""
|
||||
return _distroi.distro_release_info()
|
||||
return _distro.distro_release_info()
|
||||
|
||||
|
||||
def os_release_attr(attribute):
|
||||
|
@ -468,7 +469,7 @@ def os_release_attr(attribute):
|
|||
|
||||
See `os-release file`_ for details about these information items.
|
||||
"""
|
||||
return _distroi.os_release_attr(attribute)
|
||||
return _distro.os_release_attr(attribute)
|
||||
|
||||
|
||||
def lsb_release_attr(attribute):
|
||||
|
@ -488,7 +489,7 @@ def lsb_release_attr(attribute):
|
|||
See `lsb_release command output`_ for details about these information
|
||||
items.
|
||||
"""
|
||||
return _distroi.lsb_release_attr(attribute)
|
||||
return _distro.lsb_release_attr(attribute)
|
||||
|
||||
|
||||
def distro_release_attr(attribute):
|
||||
|
@ -507,7 +508,7 @@ def distro_release_attr(attribute):
|
|||
|
||||
See `distro release file`_ for details about these information items.
|
||||
"""
|
||||
return _distroi.distro_release_attr(attribute)
|
||||
return _distro.distro_release_attr(attribute)
|
||||
|
||||
|
||||
class LinuxDistribution(object):
|
||||
|
@ -590,12 +591,14 @@ def __init__(self,
|
|||
self.os_release_file = os_release_file or \
|
||||
os.path.join(_UNIXCONFDIR, _OS_RELEASE_BASENAME)
|
||||
self.distro_release_file = distro_release_file or '' # updated later
|
||||
self._os_release_info = self._os_release_info()
|
||||
self._lsb_release_info = self._lsb_release_info() \
|
||||
self._os_release_info = self._get_os_release_info()
|
||||
self._lsb_release_info = self._get_lsb_release_info() \
|
||||
if include_lsb else {}
|
||||
self._distro_release_info = self._distro_release_info()
|
||||
self._distro_release_info = self._get_distro_release_info()
|
||||
|
||||
def __repr__(self):
|
||||
"""Return repr of all info
|
||||
"""
|
||||
return \
|
||||
"LinuxDistribution(" \
|
||||
"os_release_file={0!r}, " \
|
||||
|
@ -624,25 +627,25 @@ def linux_distribution(self, full_distribution_name=True):
|
|||
)
|
||||
|
||||
def id(self):
|
||||
"""
|
||||
Return the distro ID of the Linux distribution, as a string.
|
||||
"""Return the distro ID of the Linux distribution, as a string.
|
||||
|
||||
For details, see :func:`distro.id`.
|
||||
"""
|
||||
def normalize(distro_id, table):
|
||||
distro_id = distro_id.lower().replace(' ', '_')
|
||||
return table.get(distro_id, distro_id)
|
||||
|
||||
distro_id = self.os_release_attr('id')
|
||||
if distro_id:
|
||||
distro_id = distro_id.lower().replace(' ', '_')
|
||||
return NORMALIZED_OS_ID.get(distro_id, distro_id)
|
||||
return normalize(distro_id, NORMALIZED_OS_ID)
|
||||
|
||||
distro_id = self.lsb_release_attr('distributor_id')
|
||||
if distro_id:
|
||||
distro_id = distro_id.lower().replace(' ', '_')
|
||||
return NORMALIZED_LSB_ID.get(distro_id, distro_id)
|
||||
return normalize(distro_id, NORMALIZED_LSB_ID)
|
||||
|
||||
distro_id = self.distro_release_attr('id')
|
||||
if distro_id:
|
||||
distro_id = distro_id.lower().replace(' ', '_')
|
||||
return NORMALIZED_DISTRO_ID.get(distro_id, distro_id)
|
||||
return normalize(distro_id, NORMALIZED_DISTRO_ID)
|
||||
|
||||
return ''
|
||||
|
||||
|
@ -707,10 +710,10 @@ def version_parts(self, best=False):
|
|||
"""
|
||||
version_str = self.version(best=best)
|
||||
if version_str:
|
||||
g = re.compile(r'(\d+)\.?(\d+)?\.?(\d+)?')
|
||||
m = g.match(version_str)
|
||||
if m:
|
||||
major, minor, build_number = m.groups()
|
||||
version_regex = re.compile(r'(\d+)\.?(\d+)?\.?(\d+)?')
|
||||
matches = version_regex.match(version_str)
|
||||
if matches:
|
||||
major, minor, build_number = matches.groups()
|
||||
return major, minor or '', build_number or ''
|
||||
return '', '', ''
|
||||
|
||||
|
@ -832,7 +835,7 @@ def distro_release_attr(self, attribute):
|
|||
"""
|
||||
return self._distro_release_info.get(attribute, '')
|
||||
|
||||
def _os_release_info(self):
|
||||
def _get_os_release_info(self):
|
||||
"""
|
||||
Get the information items from the specified os-release file.
|
||||
|
||||
|
@ -840,8 +843,8 @@ def _os_release_info(self):
|
|||
A dictionary containing all information items.
|
||||
"""
|
||||
if os.path.isfile(self.os_release_file):
|
||||
with open(self.os_release_file, 'r') as f:
|
||||
return self._parse_os_release_content(f)
|
||||
with open(self.os_release_file) as release_file:
|
||||
return self._parse_os_release_content(release_file)
|
||||
return {}
|
||||
|
||||
@staticmethod
|
||||
|
@ -904,7 +907,7 @@ def _parse_os_release_content(lines):
|
|||
pass
|
||||
return props
|
||||
|
||||
def _lsb_release_info(self):
|
||||
def _get_lsb_release_info(self):
|
||||
"""
|
||||
Get the information items from the lsb_release command output.
|
||||
|
||||
|
@ -912,26 +915,26 @@ def _lsb_release_info(self):
|
|||
A dictionary containing all information items.
|
||||
"""
|
||||
cmd = 'lsb_release -a'
|
||||
p = subprocess.Popen(
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
out, err = p.communicate()
|
||||
out, err = out.decode('ascii'), err.decode('ascii')
|
||||
rc = p.returncode
|
||||
if rc == 0:
|
||||
content = out.splitlines()
|
||||
stdout, stderr = process.communicate()
|
||||
stdout, stderr = stdout.decode('utf-8'), stderr.decode('utf-8')
|
||||
code = process.returncode
|
||||
if code == 0:
|
||||
content = stdout.splitlines()
|
||||
return self._parse_lsb_release_content(content)
|
||||
elif rc == 127: # Command not found
|
||||
elif code == 127: # Command not found
|
||||
return {}
|
||||
else:
|
||||
if sys.version_info[:2] >= (3, 5):
|
||||
raise subprocess.CalledProcessError(rc, cmd, out, err)
|
||||
raise subprocess.CalledProcessError(code, cmd, stdout, stderr)
|
||||
elif sys.version_info[:2] >= (2, 7):
|
||||
raise subprocess.CalledProcessError(rc, cmd, out)
|
||||
raise subprocess.CalledProcessError(code, cmd, stdout)
|
||||
elif sys.version_info[:2] == (2, 6):
|
||||
raise subprocess.CalledProcessError(rc, cmd)
|
||||
raise subprocess.CalledProcessError(code, cmd)
|
||||
|
||||
@staticmethod
|
||||
def _parse_lsb_release_content(lines):
|
||||
|
@ -949,8 +952,7 @@ def _parse_lsb_release_content(lines):
|
|||
"""
|
||||
props = {}
|
||||
for line in lines:
|
||||
if isinstance(line, bytes):
|
||||
line = line.decode('utf-8')
|
||||
line = line.decode('utf-8') if isinstance(line, bytes) else line
|
||||
kv = line.strip('\n').split(':', 1)
|
||||
if len(kv) != 2:
|
||||
# Ignore lines without colon.
|
||||
|
@ -959,7 +961,7 @@ def _parse_lsb_release_content(lines):
|
|||
props.update({k.replace(' ', '_').lower(): v.strip()})
|
||||
return props
|
||||
|
||||
def _distro_release_info(self):
|
||||
def _get_distro_release_info(self):
|
||||
"""
|
||||
Get the information items from the specified distro release file.
|
||||
|
||||
|
@ -1012,7 +1014,7 @@ def _parse_distro_release_file(self, filepath):
|
|||
A dictionary containing all information items.
|
||||
"""
|
||||
if os.path.isfile(filepath):
|
||||
with open(filepath, 'r') as fp:
|
||||
with open(filepath) as fp:
|
||||
# Only parse the first line. For instance, on SLES there
|
||||
# are multiple lines. We don't want them...
|
||||
return self._parse_distro_release_content(fp.readline())
|
||||
|
@ -1032,18 +1034,48 @@ def _parse_distro_release_content(line):
|
|||
"""
|
||||
if isinstance(line, bytes):
|
||||
line = line.decode('utf-8')
|
||||
m = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match(
|
||||
matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match(
|
||||
line.strip()[::-1])
|
||||
distro_info = {}
|
||||
if m:
|
||||
distro_info['name'] = m.group(3)[::-1] # regexp ensures non-None
|
||||
if m.group(2):
|
||||
distro_info['version_id'] = m.group(2)[::-1]
|
||||
if m.group(1):
|
||||
distro_info['codename'] = m.group(1)[::-1]
|
||||
if matches:
|
||||
# regexp ensures non-None
|
||||
distro_info['name'] = matches.group(3)[::-1]
|
||||
if matches.group(2):
|
||||
distro_info['version_id'] = matches.group(2)[::-1]
|
||||
if matches.group(1):
|
||||
distro_info['codename'] = matches.group(1)[::-1]
|
||||
elif line:
|
||||
distro_info['name'] = line.strip()
|
||||
return distro_info
|
||||
|
||||
|
||||
_distroi = LinuxDistribution()
|
||||
_distro = LinuxDistribution()
|
||||
|
||||
|
||||
def main():
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||
|
||||
parser = argparse.ArgumentParser(description="Linux distro info tool")
|
||||
parser.add_argument(
|
||||
'--json',
|
||||
'-j',
|
||||
help="Output in machine readable format",
|
||||
action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.json:
|
||||
logger.info(json.dumps(info(), indent=4, sort_keys=True))
|
||||
else:
|
||||
logger.info('Name: %s', name(pretty=True))
|
||||
distribution_version = version(pretty=True)
|
||||
if distribution_version:
|
||||
logger.info('Version: %s', distribution_version)
|
||||
distribution_codename = codename()
|
||||
if distribution_codename:
|
||||
logger.info('Codename: %s', distribution_codename)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
Loading…
Reference in a new issue