You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					1387 lines
				
				47 KiB
			
		
		
			
		
	
	
					1387 lines
				
				47 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								# Copyright 2015,2016,2017 Nir Cohen
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# Licensed under the Apache License, Version 2.0 (the "License");
							 | 
						||
| 
								 | 
							
								# you may not use this file except in compliance with the License.
							 | 
						||
| 
								 | 
							
								# You may obtain a copy of the License at
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# http://www.apache.org/licenses/LICENSE-2.0
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# Unless required by applicable law or agreed to in writing, software
							 | 
						||
| 
								 | 
							
								# distributed under the License is distributed on an "AS IS" BASIS,
							 | 
						||
| 
								 | 
							
								# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
							 | 
						||
| 
								 | 
							
								# See the License for the specific language governing permissions and
							 | 
						||
| 
								 | 
							
								# limitations under the License.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								The ``distro`` package (``distro`` stands for Linux Distribution) provides
							 | 
						||
| 
								 | 
							
								information about the Linux distribution it runs on, such as a reliable
							 | 
						||
| 
								 | 
							
								machine-readable distro ID, or version information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								It is the recommended replacement for Python's original
							 | 
						||
| 
								 | 
							
								:py:func:`platform.linux_distribution` function, but it provides much more
							 | 
						||
| 
								 | 
							
								functionality. An alternative implementation became necessary because Python
							 | 
						||
| 
								 | 
							
								3.5 deprecated this function, and Python 3.8 removed it altogether. Its
							 | 
						||
| 
								 | 
							
								predecessor function :py:func:`platform.dist` was already deprecated since
							 | 
						||
| 
								 | 
							
								Python 2.6 and removed in Python 3.8. Still, there are many cases in which
							 | 
						||
| 
								 | 
							
								access to OS distribution information is needed. See `Python issue 1322
							 | 
						||
| 
								 | 
							
								<https://bugs.python.org/issue1322>`_ for more information.
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import argparse
							 | 
						||
| 
								 | 
							
								import json
							 | 
						||
| 
								 | 
							
								import logging
							 | 
						||
| 
								 | 
							
								import os
							 | 
						||
| 
								 | 
							
								import re
							 | 
						||
| 
								 | 
							
								import shlex
							 | 
						||
| 
								 | 
							
								import subprocess
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								import warnings
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								__version__ = "1.6.0"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Use `if False` to avoid an ImportError on Python 2. After dropping Python 2
							 | 
						||
| 
								 | 
							
								# support, can use typing.TYPE_CHECKING instead. See:
							 | 
						||
| 
								 | 
							
								# https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING
							 | 
						||
| 
								 | 
							
								if False:  # pragma: nocover
							 | 
						||
| 
								 | 
							
								    from typing import (
							 | 
						||
| 
								 | 
							
								        Any,
							 | 
						||
| 
								 | 
							
								        Callable,
							 | 
						||
| 
								 | 
							
								        Dict,
							 | 
						||
| 
								 | 
							
								        Iterable,
							 | 
						||
| 
								 | 
							
								        Optional,
							 | 
						||
| 
								 | 
							
								        Sequence,
							 | 
						||
| 
								 | 
							
								        TextIO,
							 | 
						||
| 
								 | 
							
								        Tuple,
							 | 
						||
| 
								 | 
							
								        Type,
							 | 
						||
| 
								 | 
							
								        TypedDict,
							 | 
						||
| 
								 | 
							
								        Union,
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    VersionDict = TypedDict(
							 | 
						||
| 
								 | 
							
								        "VersionDict", {"major": str, "minor": str, "build_number": str}
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								    InfoDict = TypedDict(
							 | 
						||
| 
								 | 
							
								        "InfoDict",
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            "id": str,
							 | 
						||
| 
								 | 
							
								            "version": str,
							 | 
						||
| 
								 | 
							
								            "version_parts": VersionDict,
							 | 
						||
| 
								 | 
							
								            "like": str,
							 | 
						||
| 
								 | 
							
								            "codename": str,
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								_UNIXCONFDIR = os.environ.get("UNIXCONFDIR", "/etc")
							 | 
						||
| 
								 | 
							
								_UNIXUSRLIBDIR = os.environ.get("UNIXUSRLIBDIR", "/usr/lib")
							 | 
						||
| 
								 | 
							
								_OS_RELEASE_BASENAME = "os-release"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#: Translation table for normalizing the "ID" attribute defined in os-release
							 | 
						||
| 
								 | 
							
								#: files, for use by the :func:`distro.id` method.
							 | 
						||
| 
								 | 
							
								#:
							 | 
						||
| 
								 | 
							
								#: * Key: Value as defined in the os-release file, translated to lower case,
							 | 
						||
| 
								 | 
							
								#:   with blanks translated to underscores.
							 | 
						||
| 
								 | 
							
								#:
							 | 
						||
| 
								 | 
							
								#: * Value: Normalized value.
							 | 
						||
| 
								 | 
							
								NORMALIZED_OS_ID = {
							 | 
						||
| 
								 | 
							
								    "ol": "oracle",  # Oracle Linux
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#: Translation table for normalizing the "Distributor ID" attribute returned by
							 | 
						||
| 
								 | 
							
								#: the lsb_release command, for use by the :func:`distro.id` method.
							 | 
						||
| 
								 | 
							
								#:
							 | 
						||
| 
								 | 
							
								#: * Key: Value as returned by the lsb_release command, translated to lower
							 | 
						||
| 
								 | 
							
								#:   case, with blanks translated to underscores.
							 | 
						||
| 
								 | 
							
								#:
							 | 
						||
| 
								 | 
							
								#: * Value: Normalized value.
							 | 
						||
| 
								 | 
							
								NORMALIZED_LSB_ID = {
							 | 
						||
| 
								 | 
							
								    "enterpriseenterpriseas": "oracle",  # Oracle Enterprise Linux 4
							 | 
						||
| 
								 | 
							
								    "enterpriseenterpriseserver": "oracle",  # Oracle Linux 5
							 | 
						||
| 
								 | 
							
								    "redhatenterpriseworkstation": "rhel",  # RHEL 6, 7 Workstation
							 | 
						||
| 
								 | 
							
								    "redhatenterpriseserver": "rhel",  # RHEL 6, 7 Server
							 | 
						||
| 
								 | 
							
								    "redhatenterprisecomputenode": "rhel",  # RHEL 6 ComputeNode
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#: Translation table for normalizing the distro ID derived from the file name
							 | 
						||
| 
								 | 
							
								#: of distro release files, for use by the :func:`distro.id` method.
							 | 
						||
| 
								 | 
							
								#:
							 | 
						||
| 
								 | 
							
								#: * Key: Value as derived from the file name of a distro release file,
							 | 
						||
| 
								 | 
							
								#:   translated to lower case, with blanks translated to underscores.
							 | 
						||
| 
								 | 
							
								#:
							 | 
						||
| 
								 | 
							
								#: * Value: Normalized value.
							 | 
						||
| 
								 | 
							
								NORMALIZED_DISTRO_ID = {
							 | 
						||
| 
								 | 
							
								    "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 *)?(.+)"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Pattern for base file name of distro release file
							 | 
						||
| 
								 | 
							
								_DISTRO_RELEASE_BASENAME_PATTERN = re.compile(r"(\w+)[-_](release|version)$")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Base file names to be ignored when searching for distro release file
							 | 
						||
| 
								 | 
							
								_DISTRO_RELEASE_IGNORE_BASENAMES = (
							 | 
						||
| 
								 | 
							
								    "debian_version",
							 | 
						||
| 
								 | 
							
								    "lsb-release",
							 | 
						||
| 
								 | 
							
								    "oem-release",
							 | 
						||
| 
								 | 
							
								    _OS_RELEASE_BASENAME,
							 | 
						||
| 
								 | 
							
								    "system-release",
							 | 
						||
| 
								 | 
							
								    "plesk-release",
							 | 
						||
| 
								 | 
							
								    "iredmail-release",
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def linux_distribution(full_distribution_name=True):
							 | 
						||
| 
								 | 
							
								    # type: (bool) -> Tuple[str, str, str]
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    .. deprecated:: 1.6.0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        :func:`distro.linux_distribution()` is deprecated. It should only be
							 | 
						||
| 
								 | 
							
								        used as a compatibility shim with Python's
							 | 
						||
| 
								 | 
							
								        :py:func:`platform.linux_distribution()`. Please use :func:`distro.id`,
							 | 
						||
| 
								 | 
							
								        :func:`distro.version` and :func:`distro.name` instead.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Return information about the current OS distribution as a tuple
							 | 
						||
| 
								 | 
							
								    ``(id_name, version, codename)`` with items as follows:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``id_name``:  If *full_distribution_name* is false, the result of
							 | 
						||
| 
								 | 
							
								      :func:`distro.id`. Otherwise, the result of :func:`distro.name`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``version``:  The result of :func:`distro.version`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``codename``:  The result of :func:`distro.codename`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The interface of this function is compatible with the original
							 | 
						||
| 
								 | 
							
								    :py:func:`platform.linux_distribution` function, supporting a subset of
							 | 
						||
| 
								 | 
							
								    its parameters.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The data it returns may not exactly be the same, because it uses more data
							 | 
						||
| 
								 | 
							
								    sources than the original function, and that may lead to different data if
							 | 
						||
| 
								 | 
							
								    the OS distribution is not consistent across multiple data sources it
							 | 
						||
| 
								 | 
							
								    provides (there are indeed such distributions ...).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Another reason for differences is the fact that the :func:`distro.id`
							 | 
						||
| 
								 | 
							
								    method normalizes the distro ID string to a reliable machine-readable value
							 | 
						||
| 
								 | 
							
								    for a number of popular OS distributions.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    warnings.warn(
							 | 
						||
| 
								 | 
							
								        "distro.linux_distribution() is deprecated. It should only be used as a "
							 | 
						||
| 
								 | 
							
								        "compatibility shim with Python's platform.linux_distribution(). Please use "
							 | 
						||
| 
								 | 
							
								        "distro.id(), distro.version() and distro.name() instead.",
							 | 
						||
| 
								 | 
							
								        DeprecationWarning,
							 | 
						||
| 
								 | 
							
								        stacklevel=2,
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								    return _distro.linux_distribution(full_distribution_name)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def id():
							 | 
						||
| 
								 | 
							
								    # type: () -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return the distro ID of the current distribution, as a
							 | 
						||
| 
								 | 
							
								    machine-readable string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    For a number of OS distributions, the returned distro ID value is
							 | 
						||
| 
								 | 
							
								    *reliable*, in the sense that it is documented and that it does not change
							 | 
						||
| 
								 | 
							
								    across releases of the distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This package maintains the following reliable distro ID values:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ==============  =========================================
							 | 
						||
| 
								 | 
							
								    Distro ID       Distribution
							 | 
						||
| 
								 | 
							
								    ==============  =========================================
							 | 
						||
| 
								 | 
							
								    "ubuntu"        Ubuntu
							 | 
						||
| 
								 | 
							
								    "debian"        Debian
							 | 
						||
| 
								 | 
							
								    "rhel"          RedHat Enterprise Linux
							 | 
						||
| 
								 | 
							
								    "centos"        CentOS
							 | 
						||
| 
								 | 
							
								    "fedora"        Fedora
							 | 
						||
| 
								 | 
							
								    "sles"          SUSE Linux Enterprise Server
							 | 
						||
| 
								 | 
							
								    "opensuse"      openSUSE
							 | 
						||
| 
								 | 
							
								    "amazon"        Amazon Linux
							 | 
						||
| 
								 | 
							
								    "arch"          Arch Linux
							 | 
						||
| 
								 | 
							
								    "cloudlinux"    CloudLinux OS
							 | 
						||
| 
								 | 
							
								    "exherbo"       Exherbo Linux
							 | 
						||
| 
								 | 
							
								    "gentoo"        GenToo Linux
							 | 
						||
| 
								 | 
							
								    "ibm_powerkvm"  IBM PowerKVM
							 | 
						||
| 
								 | 
							
								    "kvmibm"        KVM for IBM z Systems
							 | 
						||
| 
								 | 
							
								    "linuxmint"     Linux Mint
							 | 
						||
| 
								 | 
							
								    "mageia"        Mageia
							 | 
						||
| 
								 | 
							
								    "mandriva"      Mandriva Linux
							 | 
						||
| 
								 | 
							
								    "parallels"     Parallels
							 | 
						||
| 
								 | 
							
								    "pidora"        Pidora
							 | 
						||
| 
								 | 
							
								    "raspbian"      Raspbian
							 | 
						||
| 
								 | 
							
								    "oracle"        Oracle Linux (and Oracle Enterprise Linux)
							 | 
						||
| 
								 | 
							
								    "scientific"    Scientific Linux
							 | 
						||
| 
								 | 
							
								    "slackware"     Slackware
							 | 
						||
| 
								 | 
							
								    "xenserver"     XenServer
							 | 
						||
| 
								 | 
							
								    "openbsd"       OpenBSD
							 | 
						||
| 
								 | 
							
								    "netbsd"        NetBSD
							 | 
						||
| 
								 | 
							
								    "freebsd"       FreeBSD
							 | 
						||
| 
								 | 
							
								    "midnightbsd"   MidnightBSD
							 | 
						||
| 
								 | 
							
								    ==============  =========================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If you have a need to get distros for reliable IDs added into this set,
							 | 
						||
| 
								 | 
							
								    or if you find that the :func:`distro.id` function returns a different
							 | 
						||
| 
								 | 
							
								    distro ID for one of the listed distros, please create an issue in the
							 | 
						||
| 
								 | 
							
								    `distro issue tracker`_.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    **Lookup hierarchy and transformations:**
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    First, the ID is obtained from the following sources, in the specified
							 | 
						||
| 
								 | 
							
								    order. The first available and non-empty value is used:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * the value of the "ID" attribute of the os-release file,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * the value of the "Distributor ID" attribute returned by the lsb_release
							 | 
						||
| 
								 | 
							
								      command,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * the first part of the file name of the distro release file,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The so determined ID value then passes the following transformations,
							 | 
						||
| 
								 | 
							
								    before it is returned by this method:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * it is translated to lower case,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * blanks (which should not be there anyway) are translated to underscores,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * a normalization of the ID is performed, based upon
							 | 
						||
| 
								 | 
							
								      `normalization tables`_. The purpose of this normalization is to ensure
							 | 
						||
| 
								 | 
							
								      that the ID is as reliable as possible, even across incompatible changes
							 | 
						||
| 
								 | 
							
								      in the OS distributions. A common reason for an incompatible change is
							 | 
						||
| 
								 | 
							
								      the addition of an os-release file, or the addition of the lsb_release
							 | 
						||
| 
								 | 
							
								      command, with ID values that differ from what was previously determined
							 | 
						||
| 
								 | 
							
								      from the distro release file name.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.id()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def name(pretty=False):
							 | 
						||
| 
								 | 
							
								    # type: (bool) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return the name of the current OS distribution, as a human-readable
							 | 
						||
| 
								 | 
							
								    string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If *pretty* is false, the name is returned without version or codename.
							 | 
						||
| 
								 | 
							
								    (e.g. "CentOS Linux")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If *pretty* is true, the version and codename are appended.
							 | 
						||
| 
								 | 
							
								    (e.g. "CentOS Linux 7.1.1503 (Core)")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    **Lookup hierarchy:**
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The name is obtained from the following sources, in the specified order.
							 | 
						||
| 
								 | 
							
								    The first available and non-empty value is used:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * If *pretty* is false:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - the value of the "NAME" attribute of the os-release file,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - the value of the "Distributor ID" attribute returned by the lsb_release
							 | 
						||
| 
								 | 
							
								        command,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - the value of the "<name>" field of the distro release file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * If *pretty* is true:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - the value of the "PRETTY_NAME" attribute of the os-release file,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - the value of the "Description" attribute returned by the lsb_release
							 | 
						||
| 
								 | 
							
								        command,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      - the value of the "<name>" field of the distro release file, appended
							 | 
						||
| 
								 | 
							
								        with the value of the pretty version ("<version_id>" and "<codename>"
							 | 
						||
| 
								 | 
							
								        fields) of the distro release file, if available.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.name(pretty)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def version(pretty=False, best=False):
							 | 
						||
| 
								 | 
							
								    # type: (bool, bool) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return the version of the current OS distribution, as a human-readable
							 | 
						||
| 
								 | 
							
								    string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If *pretty* is false, the version is returned without codename (e.g.
							 | 
						||
| 
								 | 
							
								    "7.0").
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If *pretty* is true, the codename in parenthesis is appended, if the
							 | 
						||
| 
								 | 
							
								    codename is non-empty (e.g. "7.0 (Maipo)").
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Some distributions provide version numbers with different precisions in
							 | 
						||
| 
								 | 
							
								    the different sources of distribution information. Examining the different
							 | 
						||
| 
								 | 
							
								    sources in a fixed priority order does not always yield the most precise
							 | 
						||
| 
								 | 
							
								    version (e.g. for Debian 8.2, or CentOS 7.1).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The *best* parameter can be used to control the approach for the returned
							 | 
						||
| 
								 | 
							
								    version:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If *best* is false, the first non-empty version number in priority order of
							 | 
						||
| 
								 | 
							
								    the examined sources is returned.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If *best* is true, the most precise version number out of all examined
							 | 
						||
| 
								 | 
							
								    sources is returned.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    **Lookup hierarchy:**
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    In all cases, the version number is obtained from the following sources.
							 | 
						||
| 
								 | 
							
								    If *best* is false, this order represents the priority order:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * the value of the "VERSION_ID" attribute of the os-release file,
							 | 
						||
| 
								 | 
							
								    * the value of the "Release" attribute returned by the lsb_release
							 | 
						||
| 
								 | 
							
								      command,
							 | 
						||
| 
								 | 
							
								    * the version number parsed from the "<version_id>" field of the first line
							 | 
						||
| 
								 | 
							
								      of the distro release file,
							 | 
						||
| 
								 | 
							
								    * the version number parsed from the "PRETTY_NAME" attribute of the
							 | 
						||
| 
								 | 
							
								      os-release file, if it follows the format of the distro release files.
							 | 
						||
| 
								 | 
							
								    * the version number parsed from the "Description" attribute returned by
							 | 
						||
| 
								 | 
							
								      the lsb_release command, if it follows the format of the distro release
							 | 
						||
| 
								 | 
							
								      files.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.version(pretty, best)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def version_parts(best=False):
							 | 
						||
| 
								 | 
							
								    # type: (bool) -> Tuple[str, str, str]
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return the version of the current OS distribution as a tuple
							 | 
						||
| 
								 | 
							
								    ``(major, minor, build_number)`` with items as follows:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``major``:  The result of :func:`distro.major_version`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``minor``:  The result of :func:`distro.minor_version`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``build_number``:  The result of :func:`distro.build_number`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    For a description of the *best* parameter, see the :func:`distro.version`
							 | 
						||
| 
								 | 
							
								    method.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.version_parts(best)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def major_version(best=False):
							 | 
						||
| 
								 | 
							
								    # type: (bool) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return the major version of the current OS distribution, as a string,
							 | 
						||
| 
								 | 
							
								    if provided.
							 | 
						||
| 
								 | 
							
								    Otherwise, the empty string is returned. The major version is the first
							 | 
						||
| 
								 | 
							
								    part of the dot-separated version string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    For a description of the *best* parameter, see the :func:`distro.version`
							 | 
						||
| 
								 | 
							
								    method.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.major_version(best)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def minor_version(best=False):
							 | 
						||
| 
								 | 
							
								    # type: (bool) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return the minor version of the current OS distribution, as a string,
							 | 
						||
| 
								 | 
							
								    if provided.
							 | 
						||
| 
								 | 
							
								    Otherwise, the empty string is returned. The minor version is the second
							 | 
						||
| 
								 | 
							
								    part of the dot-separated version string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    For a description of the *best* parameter, see the :func:`distro.version`
							 | 
						||
| 
								 | 
							
								    method.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.minor_version(best)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def build_number(best=False):
							 | 
						||
| 
								 | 
							
								    # type: (bool) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return the build number of the current OS distribution, as a string,
							 | 
						||
| 
								 | 
							
								    if provided.
							 | 
						||
| 
								 | 
							
								    Otherwise, the empty string is returned. The build number is the third part
							 | 
						||
| 
								 | 
							
								    of the dot-separated version string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    For a description of the *best* parameter, see the :func:`distro.version`
							 | 
						||
| 
								 | 
							
								    method.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.build_number(best)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def like():
							 | 
						||
| 
								 | 
							
								    # type: () -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a space-separated list of distro IDs of distributions that are
							 | 
						||
| 
								 | 
							
								    closely related to the current OS distribution in regards to packaging
							 | 
						||
| 
								 | 
							
								    and programming interfaces, for example distributions the current
							 | 
						||
| 
								 | 
							
								    distribution is a derivative from.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    **Lookup hierarchy:**
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This information item is only provided by the os-release file.
							 | 
						||
| 
								 | 
							
								    For details, see the description of the "ID_LIKE" attribute in the
							 | 
						||
| 
								 | 
							
								    `os-release man page
							 | 
						||
| 
								 | 
							
								    <http://www.freedesktop.org/software/systemd/man/os-release.html>`_.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.like()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def codename():
							 | 
						||
| 
								 | 
							
								    # type: () -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return the codename for the release of the current OS distribution,
							 | 
						||
| 
								 | 
							
								    as a string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If the distribution does not have a codename, an empty string is returned.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Note that the returned codename is not always really a codename. For
							 | 
						||
| 
								 | 
							
								    example, openSUSE returns "x86_64". This function does not handle such
							 | 
						||
| 
								 | 
							
								    cases in any special way and just returns the string it finds, if any.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    **Lookup hierarchy:**
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * the codename within the "VERSION" attribute of the os-release file, if
							 | 
						||
| 
								 | 
							
								      provided,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * the value of the "Codename" attribute returned by the lsb_release
							 | 
						||
| 
								 | 
							
								      command,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * the value of the "<codename>" field of the distro release file.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.codename()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def info(pretty=False, best=False):
							 | 
						||
| 
								 | 
							
								    # type: (bool, bool) -> InfoDict
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return certain machine-readable information items about the current OS
							 | 
						||
| 
								 | 
							
								    distribution in a dictionary, as shown in the following example:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .. sourcecode:: python
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            'id': 'rhel',
							 | 
						||
| 
								 | 
							
								            'version': '7.0',
							 | 
						||
| 
								 | 
							
								            'version_parts': {
							 | 
						||
| 
								 | 
							
								                'major': '7',
							 | 
						||
| 
								 | 
							
								                'minor': '0',
							 | 
						||
| 
								 | 
							
								                'build_number': ''
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            'like': 'fedora',
							 | 
						||
| 
								 | 
							
								            'codename': 'Maipo'
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The dictionary structure and keys are always the same, regardless of which
							 | 
						||
| 
								 | 
							
								    information items are available in the underlying data sources. The values
							 | 
						||
| 
								 | 
							
								    for the various keys are as follows:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``id``:  The result of :func:`distro.id`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``version``:  The result of :func:`distro.version`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``version_parts -> major``:  The result of :func:`distro.major_version`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``version_parts -> minor``:  The result of :func:`distro.minor_version`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``version_parts -> build_number``:  The result of
							 | 
						||
| 
								 | 
							
								      :func:`distro.build_number`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``like``:  The result of :func:`distro.like`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``codename``:  The result of :func:`distro.codename`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    For a description of the *pretty* and *best* parameters, see the
							 | 
						||
| 
								 | 
							
								    :func:`distro.version` method.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.info(pretty, best)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def os_release_info():
							 | 
						||
| 
								 | 
							
								    # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a dictionary containing key-value pairs for the information items
							 | 
						||
| 
								 | 
							
								    from the os-release file data source of the current OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See `os-release file`_ for details about these information items.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.os_release_info()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def lsb_release_info():
							 | 
						||
| 
								 | 
							
								    # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a dictionary containing key-value pairs for the information items
							 | 
						||
| 
								 | 
							
								    from the lsb_release command data source of the current OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See `lsb_release command output`_ for details about these information
							 | 
						||
| 
								 | 
							
								    items.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.lsb_release_info()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def distro_release_info():
							 | 
						||
| 
								 | 
							
								    # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a dictionary containing key-value pairs for the information items
							 | 
						||
| 
								 | 
							
								    from the distro release file data source of the current OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See `distro release file`_ for details about these information items.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.distro_release_info()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def uname_info():
							 | 
						||
| 
								 | 
							
								    # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a dictionary containing key-value pairs for the information items
							 | 
						||
| 
								 | 
							
								    from the distro release file data source of the current OS distribution.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.uname_info()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def os_release_attr(attribute):
							 | 
						||
| 
								 | 
							
								    # type: (str) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a single named information item from the os-release file data source
							 | 
						||
| 
								 | 
							
								    of the current OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``attribute`` (string): Key of the information item.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * (string): Value of the information item, if the item exists.
							 | 
						||
| 
								 | 
							
								      The empty string, if the item does not exist.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See `os-release file`_ for details about these information items.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.os_release_attr(attribute)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def lsb_release_attr(attribute):
							 | 
						||
| 
								 | 
							
								    # type: (str) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a single named information item from the lsb_release command output
							 | 
						||
| 
								 | 
							
								    data source of the current OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``attribute`` (string): Key of the information item.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * (string): Value of the information item, if the item exists.
							 | 
						||
| 
								 | 
							
								      The empty string, if the item does not exist.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See `lsb_release command output`_ for details about these information
							 | 
						||
| 
								 | 
							
								    items.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.lsb_release_attr(attribute)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def distro_release_attr(attribute):
							 | 
						||
| 
								 | 
							
								    # type: (str) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a single named information item from the distro release file
							 | 
						||
| 
								 | 
							
								    data source of the current OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``attribute`` (string): Key of the information item.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * (string): Value of the information item, if the item exists.
							 | 
						||
| 
								 | 
							
								      The empty string, if the item does not exist.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See `distro release file`_ for details about these information items.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.distro_release_attr(attribute)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def uname_attr(attribute):
							 | 
						||
| 
								 | 
							
								    # type: (str) -> str
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return a single named information item from the distro release file
							 | 
						||
| 
								 | 
							
								    data source of the current OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * ``attribute`` (string): Key of the information item.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * (string): Value of the information item, if the item exists.
							 | 
						||
| 
								 | 
							
								                The empty string, if the item does not exist.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    return _distro.uname_attr(attribute)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								try:
							 | 
						||
| 
								 | 
							
								    from functools import cached_property
							 | 
						||
| 
								 | 
							
								except ImportError:
							 | 
						||
| 
								 | 
							
								    # Python < 3.8
							 | 
						||
| 
								 | 
							
								    class cached_property(object):  # type: ignore
							 | 
						||
| 
								 | 
							
								        """A version of @property which caches the value.  On access, it calls the
							 | 
						||
| 
								 | 
							
								        underlying function and sets the value in `__dict__` so future accesses
							 | 
						||
| 
								 | 
							
								        will not re-call the property.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        def __init__(self, f):
							 | 
						||
| 
								 | 
							
								            # type: (Callable[[Any], Any]) -> None
							 | 
						||
| 
								 | 
							
								            self._fname = f.__name__
							 | 
						||
| 
								 | 
							
								            self._f = f
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        def __get__(self, obj, owner):
							 | 
						||
| 
								 | 
							
								            # type: (Any, Type[Any]) -> Any
							 | 
						||
| 
								 | 
							
								            assert obj is not None, "call {} on an instance".format(self._fname)
							 | 
						||
| 
								 | 
							
								            ret = obj.__dict__[self._fname] = self._f(obj)
							 | 
						||
| 
								 | 
							
								            return ret
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class LinuxDistribution(object):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Provides information about a OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This package creates a private module-global instance of this class with
							 | 
						||
| 
								 | 
							
								    default initialization arguments, that is used by the
							 | 
						||
| 
								 | 
							
								    `consolidated accessor functions`_ and `single source accessor functions`_.
							 | 
						||
| 
								 | 
							
								    By using default initialization arguments, that module-global instance
							 | 
						||
| 
								 | 
							
								    returns data about the current OS distribution (i.e. the distro this
							 | 
						||
| 
								 | 
							
								    package runs on).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Normally, it is not necessary to create additional instances of this class.
							 | 
						||
| 
								 | 
							
								    However, in situations where control is needed over the exact data sources
							 | 
						||
| 
								 | 
							
								    that are used, instances of this class can be created with a specific
							 | 
						||
| 
								 | 
							
								    distro release file, or a specific os-release file, or without invoking the
							 | 
						||
| 
								 | 
							
								    lsb_release command.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(
							 | 
						||
| 
								 | 
							
								        self,
							 | 
						||
| 
								 | 
							
								        include_lsb=True,
							 | 
						||
| 
								 | 
							
								        os_release_file="",
							 | 
						||
| 
								 | 
							
								        distro_release_file="",
							 | 
						||
| 
								 | 
							
								        include_uname=True,
							 | 
						||
| 
								 | 
							
								        root_dir=None,
							 | 
						||
| 
								 | 
							
								    ):
							 | 
						||
| 
								 | 
							
								        # type: (bool, str, str, bool, Optional[str]) -> None
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        The initialization method of this class gathers information from the
							 | 
						||
| 
								 | 
							
								        available data sources, and stores that in private instance attributes.
							 | 
						||
| 
								 | 
							
								        Subsequent access to the information items uses these private instance
							 | 
						||
| 
								 | 
							
								        attributes, so that the data sources are read only once.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``include_lsb`` (bool): Controls whether the
							 | 
						||
| 
								 | 
							
								          `lsb_release command output`_ is included as a data source.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          If the lsb_release command is not available in the program execution
							 | 
						||
| 
								 | 
							
								          path, the data source for the lsb_release command will be empty.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``os_release_file`` (string): The path name of the
							 | 
						||
| 
								 | 
							
								          `os-release file`_ that is to be used as a data source.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          An empty string (the default) will cause the default path name to
							 | 
						||
| 
								 | 
							
								          be used (see `os-release file`_ for details).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          If the specified or defaulted os-release file does not exist, the
							 | 
						||
| 
								 | 
							
								          data source for the os-release file will be empty.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``distro_release_file`` (string): The path name of the
							 | 
						||
| 
								 | 
							
								          `distro release file`_ that is to be used as a data source.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          An empty string (the default) will cause a default search algorithm
							 | 
						||
| 
								 | 
							
								          to be used (see `distro release file`_ for details).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          If the specified distro release file does not exist, or if no default
							 | 
						||
| 
								 | 
							
								          distro release file can be found, the data source for the distro
							 | 
						||
| 
								 | 
							
								          release file will be empty.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``include_uname`` (bool): Controls whether uname command output is
							 | 
						||
| 
								 | 
							
								          included as a data source. If the uname command is not available in
							 | 
						||
| 
								 | 
							
								          the program execution path the data source for the uname command will
							 | 
						||
| 
								 | 
							
								          be empty.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``root_dir`` (string): The absolute path to the root directory to use
							 | 
						||
| 
								 | 
							
								          to find distro-related information files.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Public instance attributes:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``os_release_file`` (string): The path name of the
							 | 
						||
| 
								 | 
							
								          `os-release file`_ that is actually used as a data source. The
							 | 
						||
| 
								 | 
							
								          empty string if no distro release file is used as a data source.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``distro_release_file`` (string): The path name of the
							 | 
						||
| 
								 | 
							
								          `distro release file`_ that is actually used as a data source. The
							 | 
						||
| 
								 | 
							
								          empty string if no distro release file is used as a data source.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter.
							 | 
						||
| 
								 | 
							
								          This controls whether the lsb information will be loaded.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * ``include_uname`` (bool): The result of the ``include_uname``
							 | 
						||
| 
								 | 
							
								          parameter. This controls whether the uname information will
							 | 
						||
| 
								 | 
							
								          be loaded.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Raises:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * :py:exc:`IOError`: Some I/O issue with an os-release file or distro
							 | 
						||
| 
								 | 
							
								          release file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * :py:exc:`subprocess.CalledProcessError`: The lsb_release command had
							 | 
						||
| 
								 | 
							
								          some issue (other than not being available in the program execution
							 | 
						||
| 
								 | 
							
								          path).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * :py:exc:`UnicodeError`: A data source has unexpected characters or
							 | 
						||
| 
								 | 
							
								          uses an unexpected encoding.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        self.root_dir = root_dir
							 | 
						||
| 
								 | 
							
								        self.etc_dir = os.path.join(root_dir, "etc") if root_dir else _UNIXCONFDIR
							 | 
						||
| 
								 | 
							
								        self.usr_lib_dir = (
							 | 
						||
| 
								 | 
							
								            os.path.join(root_dir, "usr/lib") if root_dir else _UNIXUSRLIBDIR
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if os_release_file:
							 | 
						||
| 
								 | 
							
								            self.os_release_file = os_release_file
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            etc_dir_os_release_file = os.path.join(self.etc_dir, _OS_RELEASE_BASENAME)
							 | 
						||
| 
								 | 
							
								            usr_lib_os_release_file = os.path.join(
							 | 
						||
| 
								 | 
							
								                self.usr_lib_dir, _OS_RELEASE_BASENAME
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            # NOTE: The idea is to respect order **and** have it set
							 | 
						||
| 
								 | 
							
								            #       at all times for API backwards compatibility.
							 | 
						||
| 
								 | 
							
								            if os.path.isfile(etc_dir_os_release_file) or not os.path.isfile(
							 | 
						||
| 
								 | 
							
								                usr_lib_os_release_file
							 | 
						||
| 
								 | 
							
								            ):
							 | 
						||
| 
								 | 
							
								                self.os_release_file = etc_dir_os_release_file
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                self.os_release_file = usr_lib_os_release_file
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.distro_release_file = distro_release_file or ""  # updated later
							 | 
						||
| 
								 | 
							
								        self.include_lsb = include_lsb
							 | 
						||
| 
								 | 
							
								        self.include_uname = include_uname
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __repr__(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> str
							 | 
						||
| 
								 | 
							
								        """Return repr of all info"""
							 | 
						||
| 
								 | 
							
								        return (
							 | 
						||
| 
								 | 
							
								            "LinuxDistribution("
							 | 
						||
| 
								 | 
							
								            "os_release_file={self.os_release_file!r}, "
							 | 
						||
| 
								 | 
							
								            "distro_release_file={self.distro_release_file!r}, "
							 | 
						||
| 
								 | 
							
								            "include_lsb={self.include_lsb!r}, "
							 | 
						||
| 
								 | 
							
								            "include_uname={self.include_uname!r}, "
							 | 
						||
| 
								 | 
							
								            "_os_release_info={self._os_release_info!r}, "
							 | 
						||
| 
								 | 
							
								            "_lsb_release_info={self._lsb_release_info!r}, "
							 | 
						||
| 
								 | 
							
								            "_distro_release_info={self._distro_release_info!r}, "
							 | 
						||
| 
								 | 
							
								            "_uname_info={self._uname_info!r})".format(self=self)
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def linux_distribution(self, full_distribution_name=True):
							 | 
						||
| 
								 | 
							
								        # type: (bool) -> Tuple[str, str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return information about the OS distribution that is compatible
							 | 
						||
| 
								 | 
							
								        with Python's :func:`platform.linux_distribution`, supporting a subset
							 | 
						||
| 
								 | 
							
								        of its parameters.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.linux_distribution`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return (
							 | 
						||
| 
								 | 
							
								            self.name() if full_distribution_name else self.id(),
							 | 
						||
| 
								 | 
							
								            self.version(),
							 | 
						||
| 
								 | 
							
								            self.codename(),
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def id(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> str
							 | 
						||
| 
								 | 
							
								        """Return the distro ID of the OS distribution, as a string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.id`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        def normalize(distro_id, table):
							 | 
						||
| 
								 | 
							
								            # type: (str, Dict[str, str]) -> str
							 | 
						||
| 
								 | 
							
								            distro_id = distro_id.lower().replace(" ", "_")
							 | 
						||
| 
								 | 
							
								            return table.get(distro_id, distro_id)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        distro_id = self.os_release_attr("id")
							 | 
						||
| 
								 | 
							
								        if distro_id:
							 | 
						||
| 
								 | 
							
								            return normalize(distro_id, NORMALIZED_OS_ID)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        distro_id = self.lsb_release_attr("distributor_id")
							 | 
						||
| 
								 | 
							
								        if distro_id:
							 | 
						||
| 
								 | 
							
								            return normalize(distro_id, NORMALIZED_LSB_ID)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        distro_id = self.distro_release_attr("id")
							 | 
						||
| 
								 | 
							
								        if distro_id:
							 | 
						||
| 
								 | 
							
								            return normalize(distro_id, NORMALIZED_DISTRO_ID)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        distro_id = self.uname_attr("id")
							 | 
						||
| 
								 | 
							
								        if distro_id:
							 | 
						||
| 
								 | 
							
								            return normalize(distro_id, NORMALIZED_DISTRO_ID)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return ""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def name(self, pretty=False):
							 | 
						||
| 
								 | 
							
								        # type: (bool) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the name of the OS distribution, as a string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.name`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        name = (
							 | 
						||
| 
								 | 
							
								            self.os_release_attr("name")
							 | 
						||
| 
								 | 
							
								            or self.lsb_release_attr("distributor_id")
							 | 
						||
| 
								 | 
							
								            or self.distro_release_attr("name")
							 | 
						||
| 
								 | 
							
								            or self.uname_attr("name")
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								        if pretty:
							 | 
						||
| 
								 | 
							
								            name = self.os_release_attr("pretty_name") or self.lsb_release_attr(
							 | 
						||
| 
								 | 
							
								                "description"
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								            if not name:
							 | 
						||
| 
								 | 
							
								                name = self.distro_release_attr("name") or self.uname_attr("name")
							 | 
						||
| 
								 | 
							
								                version = self.version(pretty=True)
							 | 
						||
| 
								 | 
							
								                if version:
							 | 
						||
| 
								 | 
							
								                    name = name + " " + version
							 | 
						||
| 
								 | 
							
								        return name or ""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def version(self, pretty=False, best=False):
							 | 
						||
| 
								 | 
							
								        # type: (bool, bool) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the version of the OS distribution, as a string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.version`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        versions = [
							 | 
						||
| 
								 | 
							
								            self.os_release_attr("version_id"),
							 | 
						||
| 
								 | 
							
								            self.lsb_release_attr("release"),
							 | 
						||
| 
								 | 
							
								            self.distro_release_attr("version_id"),
							 | 
						||
| 
								 | 
							
								            self._parse_distro_release_content(self.os_release_attr("pretty_name")).get(
							 | 
						||
| 
								 | 
							
								                "version_id", ""
							 | 
						||
| 
								 | 
							
								            ),
							 | 
						||
| 
								 | 
							
								            self._parse_distro_release_content(
							 | 
						||
| 
								 | 
							
								                self.lsb_release_attr("description")
							 | 
						||
| 
								 | 
							
								            ).get("version_id", ""),
							 | 
						||
| 
								 | 
							
								            self.uname_attr("release"),
							 | 
						||
| 
								 | 
							
								        ]
							 | 
						||
| 
								 | 
							
								        version = ""
							 | 
						||
| 
								 | 
							
								        if best:
							 | 
						||
| 
								 | 
							
								            # This algorithm uses the last version in priority order that has
							 | 
						||
| 
								 | 
							
								            # the best precision. If the versions are not in conflict, that
							 | 
						||
| 
								 | 
							
								            # does not matter; otherwise, using the last one instead of the
							 | 
						||
| 
								 | 
							
								            # first one might be considered a surprise.
							 | 
						||
| 
								 | 
							
								            for v in versions:
							 | 
						||
| 
								 | 
							
								                if v.count(".") > version.count(".") or version == "":
							 | 
						||
| 
								 | 
							
								                    version = v
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            for v in versions:
							 | 
						||
| 
								 | 
							
								                if v != "":
							 | 
						||
| 
								 | 
							
								                    version = v
							 | 
						||
| 
								 | 
							
								                    break
							 | 
						||
| 
								 | 
							
								        if pretty and version and self.codename():
							 | 
						||
| 
								 | 
							
								            version = "{0} ({1})".format(version, self.codename())
							 | 
						||
| 
								 | 
							
								        return version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def version_parts(self, best=False):
							 | 
						||
| 
								 | 
							
								        # type: (bool) -> Tuple[str, str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the version of the OS distribution, as a tuple of version
							 | 
						||
| 
								 | 
							
								        numbers.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.version_parts`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        version_str = self.version(best=best)
							 | 
						||
| 
								 | 
							
								        if version_str:
							 | 
						||
| 
								 | 
							
								            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 "", "", ""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def major_version(self, best=False):
							 | 
						||
| 
								 | 
							
								        # type: (bool) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the major version number of the current distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.major_version`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self.version_parts(best)[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def minor_version(self, best=False):
							 | 
						||
| 
								 | 
							
								        # type: (bool) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the minor version number of the current distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.minor_version`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self.version_parts(best)[1]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def build_number(self, best=False):
							 | 
						||
| 
								 | 
							
								        # type: (bool) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the build number of the current distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.build_number`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self.version_parts(best)[2]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def like(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the IDs of distributions that are like the OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.like`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self.os_release_attr("id_like") or ""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def codename(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the codename of the OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.codename`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            # Handle os_release specially since distros might purposefully set
							 | 
						||
| 
								 | 
							
								            # this to empty string to have no codename
							 | 
						||
| 
								 | 
							
								            return self._os_release_info["codename"]
							 | 
						||
| 
								 | 
							
								        except KeyError:
							 | 
						||
| 
								 | 
							
								            return (
							 | 
						||
| 
								 | 
							
								                self.lsb_release_attr("codename")
							 | 
						||
| 
								 | 
							
								                or self.distro_release_attr("codename")
							 | 
						||
| 
								 | 
							
								                or ""
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def info(self, pretty=False, best=False):
							 | 
						||
| 
								 | 
							
								        # type: (bool, bool) -> InfoDict
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return certain machine-readable information about the OS
							 | 
						||
| 
								 | 
							
								        distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.info`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return dict(
							 | 
						||
| 
								 | 
							
								            id=self.id(),
							 | 
						||
| 
								 | 
							
								            version=self.version(pretty, best),
							 | 
						||
| 
								 | 
							
								            version_parts=dict(
							 | 
						||
| 
								 | 
							
								                major=self.major_version(best),
							 | 
						||
| 
								 | 
							
								                minor=self.minor_version(best),
							 | 
						||
| 
								 | 
							
								                build_number=self.build_number(best),
							 | 
						||
| 
								 | 
							
								            ),
							 | 
						||
| 
								 | 
							
								            like=self.like(),
							 | 
						||
| 
								 | 
							
								            codename=self.codename(),
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def os_release_info(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a dictionary containing key-value pairs for the information
							 | 
						||
| 
								 | 
							
								        items from the os-release file data source of the OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.os_release_info`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self._os_release_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def lsb_release_info(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a dictionary containing key-value pairs for the information
							 | 
						||
| 
								 | 
							
								        items from the lsb_release command data source of the OS
							 | 
						||
| 
								 | 
							
								        distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.lsb_release_info`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self._lsb_release_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def distro_release_info(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a dictionary containing key-value pairs for the information
							 | 
						||
| 
								 | 
							
								        items from the distro release file data source of the OS
							 | 
						||
| 
								 | 
							
								        distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.distro_release_info`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self._distro_release_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def uname_info(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a dictionary containing key-value pairs for the information
							 | 
						||
| 
								 | 
							
								        items from the uname command data source of the OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.uname_info`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self._uname_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def os_release_attr(self, attribute):
							 | 
						||
| 
								 | 
							
								        # type: (str) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a single named information item from the os-release file data
							 | 
						||
| 
								 | 
							
								        source of the OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.os_release_attr`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self._os_release_info.get(attribute, "")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def lsb_release_attr(self, attribute):
							 | 
						||
| 
								 | 
							
								        # type: (str) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a single named information item from the lsb_release command
							 | 
						||
| 
								 | 
							
								        output data source of the OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.lsb_release_attr`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self._lsb_release_info.get(attribute, "")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def distro_release_attr(self, attribute):
							 | 
						||
| 
								 | 
							
								        # type: (str) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a single named information item from the distro release file
							 | 
						||
| 
								 | 
							
								        data source of the OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.distro_release_attr`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self._distro_release_info.get(attribute, "")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def uname_attr(self, attribute):
							 | 
						||
| 
								 | 
							
								        # type: (str) -> str
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a single named information item from the uname command
							 | 
						||
| 
								 | 
							
								        output data source of the OS distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        For details, see :func:`distro.uname_attr`.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return self._uname_info.get(attribute, "")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @cached_property
							 | 
						||
| 
								 | 
							
								    def _os_release_info(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Get the information items from the specified os-release file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns:
							 | 
						||
| 
								 | 
							
								            A dictionary containing all information items.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if os.path.isfile(self.os_release_file):
							 | 
						||
| 
								 | 
							
								            with open(self.os_release_file) as release_file:
							 | 
						||
| 
								 | 
							
								                return self._parse_os_release_content(release_file)
							 | 
						||
| 
								 | 
							
								        return {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @staticmethod
							 | 
						||
| 
								 | 
							
								    def _parse_os_release_content(lines):
							 | 
						||
| 
								 | 
							
								        # type: (TextIO) -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Parse the lines of an os-release file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * lines: Iterable through the lines in the os-release file.
							 | 
						||
| 
								 | 
							
								                 Each line must be a unicode string or a UTF-8 encoded byte
							 | 
						||
| 
								 | 
							
								                 string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns:
							 | 
						||
| 
								 | 
							
								            A dictionary containing all information items.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        props = {}
							 | 
						||
| 
								 | 
							
								        lexer = shlex.shlex(lines, posix=True)
							 | 
						||
| 
								 | 
							
								        lexer.whitespace_split = True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # The shlex module defines its `wordchars` variable using literals,
							 | 
						||
| 
								 | 
							
								        # making it dependent on the encoding of the Python source file.
							 | 
						||
| 
								 | 
							
								        # In Python 2.6 and 2.7, the shlex source file is encoded in
							 | 
						||
| 
								 | 
							
								        # 'iso-8859-1', and the `wordchars` variable is defined as a byte
							 | 
						||
| 
								 | 
							
								        # string. This causes a UnicodeDecodeError to be raised when the
							 | 
						||
| 
								 | 
							
								        # parsed content is a unicode object. The following fix resolves that
							 | 
						||
| 
								 | 
							
								        # (... but it should be fixed in shlex...):
							 | 
						||
| 
								 | 
							
								        if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes):
							 | 
						||
| 
								 | 
							
								            lexer.wordchars = lexer.wordchars.decode("iso-8859-1")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        tokens = list(lexer)
							 | 
						||
| 
								 | 
							
								        for token in tokens:
							 | 
						||
| 
								 | 
							
								            # At this point, all shell-like parsing has been done (i.e.
							 | 
						||
| 
								 | 
							
								            # comments processed, quotes and backslash escape sequences
							 | 
						||
| 
								 | 
							
								            # processed, multi-line values assembled, trailing newlines
							 | 
						||
| 
								 | 
							
								            # stripped, etc.), so the tokens are now either:
							 | 
						||
| 
								 | 
							
								            # * variable assignments: var=value
							 | 
						||
| 
								 | 
							
								            # * commands or their arguments (not allowed in os-release)
							 | 
						||
| 
								 | 
							
								            if "=" in token:
							 | 
						||
| 
								 | 
							
								                k, v = token.split("=", 1)
							 | 
						||
| 
								 | 
							
								                props[k.lower()] = v
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                # Ignore any tokens that are not variable assignments
							 | 
						||
| 
								 | 
							
								                pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if "version_codename" in props:
							 | 
						||
| 
								 | 
							
								            # os-release added a version_codename field.  Use that in
							 | 
						||
| 
								 | 
							
								            # preference to anything else Note that some distros purposefully
							 | 
						||
| 
								 | 
							
								            # do not have code names.  They should be setting
							 | 
						||
| 
								 | 
							
								            # version_codename=""
							 | 
						||
| 
								 | 
							
								            props["codename"] = props["version_codename"]
							 | 
						||
| 
								 | 
							
								        elif "ubuntu_codename" in props:
							 | 
						||
| 
								 | 
							
								            # Same as above but a non-standard field name used on older Ubuntus
							 | 
						||
| 
								 | 
							
								            props["codename"] = props["ubuntu_codename"]
							 | 
						||
| 
								 | 
							
								        elif "version" in props:
							 | 
						||
| 
								 | 
							
								            # If there is no version_codename, parse it from the version
							 | 
						||
| 
								 | 
							
								            match = re.search(r"(\(\D+\))|,(\s+)?\D+", props["version"])
							 | 
						||
| 
								 | 
							
								            if match:
							 | 
						||
| 
								 | 
							
								                codename = match.group()
							 | 
						||
| 
								 | 
							
								                codename = codename.strip("()")
							 | 
						||
| 
								 | 
							
								                codename = codename.strip(",")
							 | 
						||
| 
								 | 
							
								                codename = codename.strip()
							 | 
						||
| 
								 | 
							
								                # codename appears within paranthese.
							 | 
						||
| 
								 | 
							
								                props["codename"] = codename
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return props
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @cached_property
							 | 
						||
| 
								 | 
							
								    def _lsb_release_info(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Get the information items from the lsb_release command output.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns:
							 | 
						||
| 
								 | 
							
								            A dictionary containing all information items.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if not self.include_lsb:
							 | 
						||
| 
								 | 
							
								            return {}
							 | 
						||
| 
								 | 
							
								        with open(os.devnull, "wb") as devnull:
							 | 
						||
| 
								 | 
							
								            try:
							 | 
						||
| 
								 | 
							
								                cmd = ("lsb_release", "-a")
							 | 
						||
| 
								 | 
							
								                stdout = subprocess.check_output(cmd, stderr=devnull)
							 | 
						||
| 
								 | 
							
								            # Command not found or lsb_release returned error
							 | 
						||
| 
								 | 
							
								            except (OSError, subprocess.CalledProcessError):
							 | 
						||
| 
								 | 
							
								                return {}
							 | 
						||
| 
								 | 
							
								        content = self._to_str(stdout).splitlines()
							 | 
						||
| 
								 | 
							
								        return self._parse_lsb_release_content(content)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @staticmethod
							 | 
						||
| 
								 | 
							
								    def _parse_lsb_release_content(lines):
							 | 
						||
| 
								 | 
							
								        # type: (Iterable[str]) -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Parse the output of the lsb_release command.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * lines: Iterable through the lines of the lsb_release output.
							 | 
						||
| 
								 | 
							
								                 Each line must be a unicode string or a UTF-8 encoded byte
							 | 
						||
| 
								 | 
							
								                 string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns:
							 | 
						||
| 
								 | 
							
								            A dictionary containing all information items.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        props = {}
							 | 
						||
| 
								 | 
							
								        for line in lines:
							 | 
						||
| 
								 | 
							
								            kv = line.strip("\n").split(":", 1)
							 | 
						||
| 
								 | 
							
								            if len(kv) != 2:
							 | 
						||
| 
								 | 
							
								                # Ignore lines without colon.
							 | 
						||
| 
								 | 
							
								                continue
							 | 
						||
| 
								 | 
							
								            k, v = kv
							 | 
						||
| 
								 | 
							
								            props.update({k.replace(" ", "_").lower(): v.strip()})
							 | 
						||
| 
								 | 
							
								        return props
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @cached_property
							 | 
						||
| 
								 | 
							
								    def _uname_info(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        with open(os.devnull, "wb") as devnull:
							 | 
						||
| 
								 | 
							
								            try:
							 | 
						||
| 
								 | 
							
								                cmd = ("uname", "-rs")
							 | 
						||
| 
								 | 
							
								                stdout = subprocess.check_output(cmd, stderr=devnull)
							 | 
						||
| 
								 | 
							
								            except OSError:
							 | 
						||
| 
								 | 
							
								                return {}
							 | 
						||
| 
								 | 
							
								        content = self._to_str(stdout).splitlines()
							 | 
						||
| 
								 | 
							
								        return self._parse_uname_content(content)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @staticmethod
							 | 
						||
| 
								 | 
							
								    def _parse_uname_content(lines):
							 | 
						||
| 
								 | 
							
								        # type: (Sequence[str]) -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        props = {}
							 | 
						||
| 
								 | 
							
								        match = re.search(r"^([^\s]+)\s+([\d\.]+)", lines[0].strip())
							 | 
						||
| 
								 | 
							
								        if match:
							 | 
						||
| 
								 | 
							
								            name, version = match.groups()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            # This is to prevent the Linux kernel version from
							 | 
						||
| 
								 | 
							
								            # appearing as the 'best' version on otherwise
							 | 
						||
| 
								 | 
							
								            # identifiable distributions.
							 | 
						||
| 
								 | 
							
								            if name == "Linux":
							 | 
						||
| 
								 | 
							
								                return {}
							 | 
						||
| 
								 | 
							
								            props["id"] = name.lower()
							 | 
						||
| 
								 | 
							
								            props["name"] = name
							 | 
						||
| 
								 | 
							
								            props["release"] = version
							 | 
						||
| 
								 | 
							
								        return props
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @staticmethod
							 | 
						||
| 
								 | 
							
								    def _to_str(text):
							 | 
						||
| 
								 | 
							
								        # type: (Union[bytes, str]) -> str
							 | 
						||
| 
								 | 
							
								        encoding = sys.getfilesystemencoding()
							 | 
						||
| 
								 | 
							
								        encoding = "utf-8" if encoding == "ascii" else encoding
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if sys.version_info[0] >= 3:
							 | 
						||
| 
								 | 
							
								            if isinstance(text, bytes):
							 | 
						||
| 
								 | 
							
								                return text.decode(encoding)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            if isinstance(text, unicode):  # noqa
							 | 
						||
| 
								 | 
							
								                return text.encode(encoding)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return text
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @cached_property
							 | 
						||
| 
								 | 
							
								    def _distro_release_info(self):
							 | 
						||
| 
								 | 
							
								        # type: () -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Get the information items from the specified distro release file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns:
							 | 
						||
| 
								 | 
							
								            A dictionary containing all information items.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if self.distro_release_file:
							 | 
						||
| 
								 | 
							
								            # If it was specified, we use it and parse what we can, even if
							 | 
						||
| 
								 | 
							
								            # its file name or content does not match the expected pattern.
							 | 
						||
| 
								 | 
							
								            distro_info = self._parse_distro_release_file(self.distro_release_file)
							 | 
						||
| 
								 | 
							
								            basename = os.path.basename(self.distro_release_file)
							 | 
						||
| 
								 | 
							
								            # The file name pattern for user-specified distro release files
							 | 
						||
| 
								 | 
							
								            # is somewhat more tolerant (compared to when searching for the
							 | 
						||
| 
								 | 
							
								            # file), because we want to use what was specified as best as
							 | 
						||
| 
								 | 
							
								            # possible.
							 | 
						||
| 
								 | 
							
								            match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename)
							 | 
						||
| 
								 | 
							
								            if "name" in distro_info and "cloudlinux" in distro_info["name"].lower():
							 | 
						||
| 
								 | 
							
								                distro_info["id"] = "cloudlinux"
							 | 
						||
| 
								 | 
							
								            elif match:
							 | 
						||
| 
								 | 
							
								                distro_info["id"] = match.group(1)
							 | 
						||
| 
								 | 
							
								            return distro_info
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            try:
							 | 
						||
| 
								 | 
							
								                basenames = os.listdir(self.etc_dir)
							 | 
						||
| 
								 | 
							
								                # We sort for repeatability in cases where there are multiple
							 | 
						||
| 
								 | 
							
								                # distro specific files; e.g. CentOS, Oracle, Enterprise all
							 | 
						||
| 
								 | 
							
								                # containing `redhat-release` on top of their own.
							 | 
						||
| 
								 | 
							
								                basenames.sort()
							 | 
						||
| 
								 | 
							
								            except OSError:
							 | 
						||
| 
								 | 
							
								                # This may occur when /etc is not readable but we can't be
							 | 
						||
| 
								 | 
							
								                # sure about the *-release files. Check common entries of
							 | 
						||
| 
								 | 
							
								                # /etc for information. If they turn out to not be there the
							 | 
						||
| 
								 | 
							
								                # error is handled in `_parse_distro_release_file()`.
							 | 
						||
| 
								 | 
							
								                basenames = [
							 | 
						||
| 
								 | 
							
								                    "SuSE-release",
							 | 
						||
| 
								 | 
							
								                    "arch-release",
							 | 
						||
| 
								 | 
							
								                    "base-release",
							 | 
						||
| 
								 | 
							
								                    "centos-release",
							 | 
						||
| 
								 | 
							
								                    "fedora-release",
							 | 
						||
| 
								 | 
							
								                    "gentoo-release",
							 | 
						||
| 
								 | 
							
								                    "mageia-release",
							 | 
						||
| 
								 | 
							
								                    "mandrake-release",
							 | 
						||
| 
								 | 
							
								                    "mandriva-release",
							 | 
						||
| 
								 | 
							
								                    "mandrivalinux-release",
							 | 
						||
| 
								 | 
							
								                    "manjaro-release",
							 | 
						||
| 
								 | 
							
								                    "oracle-release",
							 | 
						||
| 
								 | 
							
								                    "redhat-release",
							 | 
						||
| 
								 | 
							
								                    "sl-release",
							 | 
						||
| 
								 | 
							
								                    "slackware-version",
							 | 
						||
| 
								 | 
							
								                ]
							 | 
						||
| 
								 | 
							
								            for basename in basenames:
							 | 
						||
| 
								 | 
							
								                if basename in _DISTRO_RELEASE_IGNORE_BASENAMES:
							 | 
						||
| 
								 | 
							
								                    continue
							 | 
						||
| 
								 | 
							
								                match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename)
							 | 
						||
| 
								 | 
							
								                if match:
							 | 
						||
| 
								 | 
							
								                    filepath = os.path.join(self.etc_dir, basename)
							 | 
						||
| 
								 | 
							
								                    distro_info = self._parse_distro_release_file(filepath)
							 | 
						||
| 
								 | 
							
								                    if "name" in distro_info:
							 | 
						||
| 
								 | 
							
								                        # The name is always present if the pattern matches
							 | 
						||
| 
								 | 
							
								                        self.distro_release_file = filepath
							 | 
						||
| 
								 | 
							
								                        distro_info["id"] = match.group(1)
							 | 
						||
| 
								 | 
							
								                        if "cloudlinux" in distro_info["name"].lower():
							 | 
						||
| 
								 | 
							
								                            distro_info["id"] = "cloudlinux"
							 | 
						||
| 
								 | 
							
								                        return distro_info
							 | 
						||
| 
								 | 
							
								            return {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _parse_distro_release_file(self, filepath):
							 | 
						||
| 
								 | 
							
								        # type: (str) -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Parse a distro release file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * filepath: Path name of the distro release file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns:
							 | 
						||
| 
								 | 
							
								            A dictionary containing all information items.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            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())
							 | 
						||
| 
								 | 
							
								        except (OSError, IOError):
							 | 
						||
| 
								 | 
							
								            # Ignore not being able to read a specific, seemingly version
							 | 
						||
| 
								 | 
							
								            # related file.
							 | 
						||
| 
								 | 
							
								            # See https://github.com/python-distro/distro/issues/162
							 | 
						||
| 
								 | 
							
								            return {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @staticmethod
							 | 
						||
| 
								 | 
							
								    def _parse_distro_release_content(line):
							 | 
						||
| 
								 | 
							
								        # type: (str) -> Dict[str, str]
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Parse a line from a distro release file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters:
							 | 
						||
| 
								 | 
							
								        * line: Line from the distro release file. Must be a unicode string
							 | 
						||
| 
								 | 
							
								                or a UTF-8 encoded byte string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns:
							 | 
						||
| 
								 | 
							
								            A dictionary containing all information items.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match(line.strip()[::-1])
							 | 
						||
| 
								 | 
							
								        distro_info = {}
							 | 
						||
| 
								 | 
							
								        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
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								_distro = LinuxDistribution()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def main():
							 | 
						||
| 
								 | 
							
								    # type: () -> None
							 | 
						||
| 
								 | 
							
								    logger = logging.getLogger(__name__)
							 | 
						||
| 
								 | 
							
								    logger.setLevel(logging.DEBUG)
							 | 
						||
| 
								 | 
							
								    logger.addHandler(logging.StreamHandler(sys.stdout))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    parser = argparse.ArgumentParser(description="OS distro info tool")
							 | 
						||
| 
								 | 
							
								    parser.add_argument(
							 | 
						||
| 
								 | 
							
								        "--json", "-j", help="Output in machine readable format", action="store_true"
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    parser.add_argument(
							 | 
						||
| 
								 | 
							
								        "--root-dir",
							 | 
						||
| 
								 | 
							
								        "-r",
							 | 
						||
| 
								 | 
							
								        type=str,
							 | 
						||
| 
								 | 
							
								        dest="root_dir",
							 | 
						||
| 
								 | 
							
								        help="Path to the root filesystem directory (defaults to /)",
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    args = parser.parse_args()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if args.root_dir:
							 | 
						||
| 
								 | 
							
								        dist = LinuxDistribution(
							 | 
						||
| 
								 | 
							
								            include_lsb=False, include_uname=False, root_dir=args.root_dir
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        dist = _distro
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if args.json:
							 | 
						||
| 
								 | 
							
								        logger.info(json.dumps(dist.info(), indent=4, sort_keys=True))
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        logger.info("Name: %s", dist.name(pretty=True))
							 | 
						||
| 
								 | 
							
								        distribution_version = dist.version(pretty=True)
							 | 
						||
| 
								 | 
							
								        logger.info("Version: %s", distribution_version)
							 | 
						||
| 
								 | 
							
								        distribution_codename = dist.codename()
							 | 
						||
| 
								 | 
							
								        logger.info("Codename: %s", distribution_codename)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if __name__ == "__main__":
							 | 
						||
| 
								 | 
							
								    main()
							 |