From fe145b66c1849513412532d24c994e016530e757 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 20 May 2017 23:07:42 +0200 Subject: [PATCH] Add a version.distribution() See #2369 --- qutebrowser/utils/version.py | 48 +++++++++++ tests/unit/utils/test_version.py | 134 +++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index a8e115ca5..14f9099dd 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -27,6 +27,7 @@ import platform import subprocess import importlib import collections +import pkg_resources from PyQt5.QtCore import (QT_VERSION_STR, PYQT_VERSION_STR, qVersion, QLibraryInfo) @@ -49,6 +50,53 @@ from qutebrowser.misc import objects from qutebrowser.browser import pdfjs +DistributionInfo = collections.namedtuple( + 'DistributionInfo', ['id', 'parsed', 'version', 'pretty']) + + +Distribution = usertypes.enum( + 'Distribution', ['unknown', 'ubuntu', 'debian', 'void', 'arch', + 'gentoo', 'fedora', 'opensuse', 'linuxmint', 'manjaro']) + + +def distribution(filename='/etc/os-release'): + """Get some information about the running Linux distribution. + + Returns: + A DistributionInfo object, or None if no info could be determined. + parsed: A Distribution enum member + version: A Version object, or None + pretty: Always a string (might be "Unknown") + """ + info = {} + try: + with open(filename, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if (not line) or line.startswith('#'): + continue + k, v = line.split("=", maxsplit=1) + info[k] = v.strip('"') + except (OSError, UnicodeDecodeError): + return None + + pretty = info.get('PRETTY_NAME', 'Unknown') + + if 'VERSION_ID' in info: + dist_version = pkg_resources.parse_version(info['VERSION_ID']) + else: + dist_version = None + + dist_id = info.get('ID', None) + try: + parsed = Distribution[dist_id] + except KeyError: + parsed = Distribution.unknown + + return DistributionInfo(parsed=parsed, version=dist_version, pretty=pretty, + id=dist_id) + + def _git_str(): """Try to find out git version. diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 96f4bf88f..70f3d1290 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -29,6 +29,7 @@ import types import importlib import logging import textwrap +import pkg_resources import pytest @@ -37,6 +38,139 @@ from qutebrowser.utils import version, usertypes from qutebrowser.browser import pdfjs +@pytest.mark.parametrize('os_release, expected', [ + # No file + (None, None), + # Invalid file + ("\n# foo\n foo=bar=baz", + version.DistributionInfo(id=None, parsed=version.Distribution.unknown, + version=None, pretty='Unknown')), + # Archlinux + (""" + NAME="Arch Linux" + PRETTY_NAME="Arch Linux" + ID=arch + ID_LIKE=archlinux + ANSI_COLOR="0;36" + HOME_URL="https://www.archlinux.org/" + SUPPORT_URL="https://bbs.archlinux.org/" + BUG_REPORT_URL="https://bugs.archlinux.org/" + """, + version.DistributionInfo( + id='arch', parsed=version.Distribution.arch, version=None, + pretty='Arch Linux')), + # Ubuntu 14.04 + (""" + NAME="Ubuntu" + VERSION="14.04.5 LTS, Trusty Tahr" + ID=ubuntu + ID_LIKE=debian + PRETTY_NAME="Ubuntu 14.04.5 LTS" + VERSION_ID="14.04" + """, + version.DistributionInfo( + id='ubuntu', parsed=version.Distribution.ubuntu, + version=pkg_resources.parse_version('14.4'), + pretty='Ubuntu 14.04.5 LTS')), + # Ubuntu 17.04 + (""" + NAME="Ubuntu" + VERSION="17.04 (Zesty Zapus)" + ID=ubuntu + ID_LIKE=debian + PRETTY_NAME="Ubuntu 17.04" + VERSION_ID="17.04" + """, + version.DistributionInfo( + id='ubuntu', parsed=version.Distribution.ubuntu, + version=pkg_resources.parse_version('17.4'), + pretty='Ubuntu 17.04')), + # Debian Jessie + (""" + PRETTY_NAME="Debian GNU/Linux 8 (jessie)" + NAME="Debian GNU/Linux" + VERSION_ID="8" + VERSION="8 (jessie)" + ID=debian + """, + version.DistributionInfo( + id='debian', parsed=version.Distribution.debian, + version=pkg_resources.parse_version('8'), + pretty='Debian GNU/Linux 8 (jessie)')), + # Void Linux + (""" + NAME="void" + ID="void" + DISTRIB_ID="void" + PRETTY_NAME="void" + """, + version.DistributionInfo( + id='void', parsed=version.Distribution.void, + version=None, pretty='void')), + # Gentoo + (""" + NAME=Gentoo + ID=gentoo + PRETTY_NAME="Gentoo/Linux" + """, + version.DistributionInfo( + id='gentoo', parsed=version.Distribution.gentoo, + version=None, pretty='Gentoo/Linux')), + # Fedora + (""" + NAME=Fedora + VERSION="25 (Twenty Five)" + ID=fedora + VERSION_ID=25 + PRETTY_NAME="Fedora 25 (Twenty Five)" + """, + version.DistributionInfo( + id='fedora', parsed=version.Distribution.fedora, + version=pkg_resources.parse_version('25'), + pretty='Fedora 25 (Twenty Five)')), + # OpenSUSE + (""" + NAME="openSUSE Leap" + VERSION="42.2" + ID=opensuse + ID_LIKE="suse" + VERSION_ID="42.2" + PRETTY_NAME="openSUSE Leap 42.2" + """, + version.DistributionInfo( + id='opensuse', parsed=version.Distribution.opensuse, + version=pkg_resources.parse_version('42.2'), + pretty='openSUSE Leap 42.2')), + # Linux Mint + (""" + NAME="Linux Mint" + VERSION="18.1 (Serena)" + ID=linuxmint + ID_LIKE=ubuntu + PRETTY_NAME="Linux Mint 18.1" + VERSION_ID="18.1" + """, + version.DistributionInfo( + id='linuxmint', parsed=version.Distribution.linuxmint, + version=pkg_resources.parse_version('18.1'), + pretty='Linux Mint 18.1')), + # Manjaro + (""" + NAME="Manjaro Linux" + ID=manjaro + PRETTY_NAME="Manjaro Linux" + """, + version.DistributionInfo( + id='manjaro', parsed=version.Distribution.manjaro, + version=None, pretty='Manjaro Linux')), +]) +def test_distribution(tmpdir, os_release, expected): + os_release_file = tmpdir / 'os-release' + if os_release is not None: + os_release_file.write(textwrap.dedent(os_release)) + assert version.distribution(str(os_release_file)) == expected + + class GitStrSubprocessFake: """Object returned by the git_str_subprocess_fake fixture.