diff options
| author | Julian Andres Klode <jak@debian.org> | 2016-09-21 11:17:25 (GMT) |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2016-09-21 11:17:25 (GMT) |
| commit | 6ce94b3a83b751052b885cd3684d2bfb9c713c5d (patch) | |
| tree | 8422738dadc2cf9b730ba0d6e9c1dbe736221641 | |
| parent | 23dfbc2137774b8f4a24a080f88c3b6ceee40746 (diff) | |
| parent | 8a619a70251abef6bf93524889a0221a1c2802e9 (diff) | |
Merge github.com:apachelogger/python-apt into debian/sid
| -rw-r--r-- | aptsources/distro.py | 94 | ||||
| -rw-r--r-- | tests/data/aptsources/lsb-release | 4 | ||||
| -rw-r--r-- | tests/data/aptsources/os-release | 10 | ||||
| -rw-r--r-- | tests/test_aptsources.py | 20 |
4 files changed, 116 insertions, 12 deletions
diff --git a/aptsources/distro.py b/aptsources/distro.py index 883420f..b2cda05 100644 --- a/aptsources/distro.py +++ b/aptsources/distro.py @@ -2,9 +2,11 @@ # # Copyright (c) 2004-2009 Canonical Ltd. # Copyright (c) 2006-2007 Sebastian Heinlein +# Copyright (c) 2016 Harald Sitter # # Authors: Sebastian Heinlein <glatzor@ubuntu.com> # Michael Vogt <mvo@debian.org> +# Harald Sitter <sitter@kde.org> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -24,6 +26,7 @@ import gettext import logging import re +import shlex import os from xml.etree.ElementTree import ElementTree @@ -37,13 +40,14 @@ class NoDistroTemplateException(Exception): class Distribution(object): - def __init__(self, id, codename, description, release): + def __init__(self, id, codename, description, release, is_like=[]): """ Container for distribution specific informations """ # LSB information self.id = id self.codename = codename self.description = description self.release = release + self.is_like = is_like self.binary_type = "deb" self.source_type = "deb-src" @@ -504,8 +508,59 @@ def _system_image_channel(): 'system-image-cli failed, using defaults: %s' % exc) return None - -def get_distro(id=None, codename=None, description=None, release=None): +class _OSRelease: + + DEFAULT_OS_RELEASE_FILE = '/etc/os-release' + OS_RELEASE_FILE = '/etc/os-release' + + def __init__(self, lsb_compat=True): + self.result = {} + self.valid = False + self.file = _OSRelease.OS_RELEASE_FILE + + if not os.path.isfile(self.file): + return + + self.parse() + self.valid = True + + if lsb_compat: + self.inject_lsb_compat() + + def inject_lsb_compat(self): + self.result['Distributor ID'] = self.result['ID'] + self.result['Description'] = self.result['PRETTY_NAME'] + # Optionals as per os-release spec. + self.result['Codename'] = self.result.get('VERSION_CODENAME') + if not self.result['Codename']: + # Transient Ubuntu 16.04 field (LP: #1598212) + self.result['Codename'] = self.result.get('UBUNTU_CODENAME') + self.result['Release'] = self.result.get('VERSION_ID') + + def parse(self): + f = open(self.file, 'r') + for line in f: + line = line.strip() + if not line: + continue + self.parse_entry(*line.split('=', 1)) + f.close() + + def parse_entry(self, key, value): + value = self.parse_value(value) # Values can be shell strings... + if key == "ID_LIKE" and isinstance(value, str): + # ID_LIKE is specified as quoted space-separated list. This will + # be parsed as string that we need to split manually. + value = value.split(' ') + self.result[key] = value + + def parse_value(self, value): + values = shlex.split(value) + if len(values) == 1: + return values[0] + return values + +def get_distro(id=None, codename=None, description=None, release=None, is_like=[]): """ Check the currently used distribution and return the corresponding distriubtion class that supports distro specific features. @@ -515,11 +570,26 @@ def get_distro(id=None, codename=None, description=None, release=None): """ # make testing easier if not (id and codename and description and release): - result = _lsb_release() - id = result['Distributor ID'] - codename = result['Codename'] - description = result['Description'] - release = result['Release'] + os_release = _OSRelease() + os_result = [] + lsb_result = _lsb_release() + if os_release.valid: + os_result = os_release.result + # TODO: We cannot presently use os-release to fully replace lsb_release + # because os-release's ID, VERSION_ID and VERSION_CODENAME fields + # are specified as lowercase. In lsb_release they can be upcase + # or captizalized. So, switching to os-release would consitute + # a behavior break a which point lsb_release support should be + # fully removed. + # This in particular is a problem for template matching, as this + # matches against Distribution objects and depends on string case. + lsb_result = _lsb_release() + id = lsb_result['Distributor ID'] + codename = lsb_result['Codename'] + description = lsb_result['Description'] + release = lsb_result['Release'] + # Not available with LSB, use get directly. + is_like = os_result.get('ID_LIKE', []) if id == "Ubuntu": channel = _system_image_channel() if channel is not None and "ubuntu-rtm/" in channel: @@ -528,10 +598,10 @@ def get_distro(id=None, codename=None, description=None, release=None): description = codename release = codename if id == "Ubuntu": - return UbuntuDistribution(id, codename, description, release) + return UbuntuDistribution(id, codename, description, release, is_like) if id == "Ubuntu-RTM": - return UbuntuRTMDistribution(id, codename, description, release) + return UbuntuRTMDistribution(id, codename, description, release, is_like) elif id == "Debian": - return DebianDistribution(id, codename, description, release) + return DebianDistribution(id, codename, description, release, is_like) else: - return Distribution(id, codename, description, release) + return Distribution(id, codename, description, release, is_like) diff --git a/tests/data/aptsources/lsb-release b/tests/data/aptsources/lsb-release new file mode 100644 index 0000000..c4b5944 --- /dev/null +++ b/tests/data/aptsources/lsb-release @@ -0,0 +1,4 @@ +DISTRIB_ID=Ubuntu +DISTRIB_RELEASE=16.04 +DISTRIB_CODENAME=xenial +DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS" diff --git a/tests/data/aptsources/os-release b/tests/data/aptsources/os-release new file mode 100644 index 0000000..95a5bcd --- /dev/null +++ b/tests/data/aptsources/os-release @@ -0,0 +1,10 @@ +NAME="KDE neon" +VERSION="16.04 LTS" +ID=neon +ID_LIKE="ubuntu debian" +PRETTY_NAME="KDE neon User Edition on 16.04 LTS" +VERSION_ID="16.04" +HOME_URL="http://neon.kde.org/" +SUPPORT_URL="http://neon.kde.org/" +BUG_REPORT_URL="http://bugs.kde.org/" +UBUNTU_CODENAME=xenial diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py index dec0dee..58957d7 100644 --- a/tests/test_aptsources.py +++ b/tests/test_aptsources.py @@ -27,6 +27,12 @@ class TestAptSources(testcommon.TestCase): else: self.templates = "/usr/share/python-apt/templates/" + def tearDown(self): + aptsources.distro._OSRelease.OS_RELEASE_FILE = \ + aptsources.distro._OSRelease.DEFAULT_OS_RELEASE_FILE + if "LSB_ETC_LSB_RELEASE" in os.environ: + del os.environ["LSB_ETC_LSB_RELEASE"] + def testIsMirror(self): """aptsources: Test mirror detection.""" yes = aptsources.sourceslist.is_mirror("http://archive.ubuntu.com", @@ -248,6 +254,20 @@ class TestAptSources(testcommon.TestCase): for key in found: self.assertEqual(found[key], 1) + def test_os_release_distribution(self): + """os-release file can be read and is_like is populated accordingly""" + os.environ["LSB_ETC_LSB_RELEASE"] = \ + os.path.abspath("./data/aptsources/lsb-release") + aptsources.distro._OSRelease.OS_RELEASE_FILE = \ + os.path.abspath("./data/aptsources/os-release") + distro = aptsources.distro.get_distro() + # Everything but is_like comes from lsb_release, see TODO in get_distro. + self.assertEqual('Ubuntu', distro.id) + self.assertEqual('xenial', distro.codename) + self.assertEqual('Ubuntu 16.04.1 LTS', distro.description) + self.assertEqual('16.04', distro.release) + self.assertEqual(['ubuntu', 'debian'], distro.is_like) + def test_enable_disabled(self): """LP: #1042916: Test enabling disabled entry.""" apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" |
