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