From 5ff210229763bf2c83d61113b2c773de51497bb9 Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Thu, 28 Feb 2019 08:52:38 +0000 Subject: [PATCH] Expose base python version as an atom Adds two new atoms `base-py2` and `base-py3` that can be used to identify the primary python version supported by the current operating system. This allows bindep file authors to mention correct python package names without having to hardcode each operating system version, which is not future proof, as it would break when new versions are released. New way to use bindep: python3-lxml [platform:base-py3] python-lxml [platform:base-py2] Before this users had to rely on hacks like including the operating system name and version [platform:centos-7] and negative variants, something that would being broken as soon a new release is made. Initial implementation covers RedHat flavored, Ubuntu, Debian and MacOS which do come with an official Python version but is made in such way that we could enable it for any other platforms. Change-Id: I506699fb0c80f8d9ca84e20154d1c282a08708bb Task: https://tree.taiga.io/project/tripleo-ci-board/task/809 --- README.rst | 12 +++++++++ bindep/depends.py | 25 ++++++++++++++++++- bindep/tests/bindep.txt | 5 +++- .../{fedora => fedora23}/etc/os-release | 0 bindep/tests/fixtures/rhel8/etc/os-release | 16 ++++++++++++ .../etc/os-release | 0 .../etc/os-release | 0 bindep/tests/test_depends.py | 24 ++++++++++++------ 8 files changed, 73 insertions(+), 9 deletions(-) rename bindep/tests/fixtures/{fedora => fedora23}/etc/os-release (100%) create mode 100644 bindep/tests/fixtures/rhel8/etc/os-release rename bindep/tests/fixtures/{rhelserver => rhelserver7}/etc/os-release (100%) rename bindep/tests/fixtures/{rhelworkstation => rhelworkstation7}/etc/os-release (100%) diff --git a/README.rst b/README.rst index 171a178..eecdeee 100644 --- a/README.rst +++ b/README.rst @@ -143,6 +143,18 @@ following example:: openssh-server [platform:redhat] openssh [platform:suse] +If you need to distinguish between operating systems where python2 or python3 +is the official interpreter, you can use `base-py2` and `base-py3` labels. +Keep in mind that only one would be exposed for a specific operating system +even if the system could support installation of multiple python versions. + + python3-lxml [(platform:redhat platform:base-py3)] + python-lxml [(platform:redhat platform:base-py2)] + +The example above will install lxml python modules on official python used +by platform. Keep it mind that ``base-py[23]`` support is currently implemented +only on Debian, Ubuntu, RedHat flavours and MacOS. + To select Python3 development packages, the OpenStack CI default file uses:: python3-all-dev [platform:dpkg !platform:ubuntu-precise] diff --git a/bindep/depends.py b/bindep/depends.py index 244700d..cd33c92 100644 --- a/bindep/depends.py +++ b/bindep/depends.py @@ -22,7 +22,11 @@ from parsley import makeGrammar import platform import subprocess import sys - +# packaging is newer, usually available but not guaranteed +try: + from packaging.version import parse as as_ver +except ImportError: + from distutils.version import LooseVersion as as_ver import distro @@ -60,6 +64,8 @@ comment = ws? '#' any* '\n' -> None any = ~'\n' anything blank = ws? '\n' -> None """ +PY2 = "base-py2" +PY3 = "base-py3" def get_depends(filename=None): @@ -303,6 +309,7 @@ class Depends(object): # detect available macos package managers if os.system('which brew >/dev/null') == 0: atoms.add('brew') + atoms.add(PY2) self.platform = Brew() return ["platform:%s" % (atom,) for atom in sorted(atoms)] distro_id = distro.id() @@ -315,6 +322,7 @@ class Depends(object): # NOTE(toabctl): distro can be more than one string (i.e. "SUSE LINUX") codename = distro.codename().lower() release = distro.version().lower() + release_version = as_ver(release) # NOTE(toabctl): space is a delimiter for bindep, so remove the spaces distro_id = "".join(distro_id.split()).lower() atoms = set([distro_id]) @@ -322,6 +330,14 @@ class Depends(object): atoms.update(self.releasebits(distro_id, release)) if distro_id in ["debian", "ubuntu"]: atoms.add("dpkg") + # https://wiki.debian.org/Python + # https://wiki.ubuntu.com/Python + if (distro_id == 'ubuntu' and release_version >= + as_ver("16.04")) or (distro_id == 'debian' and + release_version >= as_ver("10")): + atoms.add(PY3) + else: + atoms.add(PY2) self.platform = Dpkg() # RPM distros seem to be especially complicated elif distro_id in ["amzn", "amazonami", @@ -338,12 +354,14 @@ class Depends(object): atoms.add("rhel") atoms.update(self.codenamebits("rhel", codename)) atoms.update(self.releasebits("rhel", release)) + atoms.add(PY2 if release_version < as_ver("8") else PY3) elif distro_id == 'rhel' and 'server' in distro.name().lower(): atoms.add("redhatenterpriseserver") atoms.update(self.codenamebits("redhatenterpriseserver", codename)) atoms.update(self.releasebits("redhatenterpriseserver", release)) + atoms.add(PY2 if release_version < as_ver("8") else PY3) elif (distro_id == 'rhel' and 'workstation' in distro.name().lower()): atoms.add("redhatenterpriseworkstation") @@ -351,6 +369,7 @@ class Depends(object): codename)) atoms.update(self.releasebits("redhatenterpriseworkstation", release)) + atoms.add(PY2 if release_version < as_ver("8") else PY3) elif "amzn" in distro_id: atoms.add("amazonami") atoms.update(self.codenamebits("amazonami", codename)) @@ -375,6 +394,10 @@ class Depends(object): atoms.add("sles") atoms.update(self.codenamebits("sles", codename)) atoms.update(self.releasebits("sles", release)) + elif "fedora" in distro_id: + atoms.add(PY2 if release_version < as_ver("23") else PY3) + elif "centos" in distro_id or "rhel" in distro_id: + atoms.add(PY2 if release_version < as_ver("8") else PY3) # Family aliases if 'suse' in distro_id or distro_id == 'sles': diff --git a/bindep/tests/bindep.txt b/bindep/tests/bindep.txt index bc4c3d7..0966332 100644 --- a/bindep/tests/bindep.txt +++ b/bindep/tests/bindep.txt @@ -85,7 +85,10 @@ python-devel [platform:rpm] dev-lang/python [platform:gentoo] python-libvirt [platform:dpkg] python-lxml [!platform:gentoo !platform:fedora] -python2-lxml [platform:fedora] +# base-py3 covers CentOS>=8, Fedora>=23, RHEL>=8 +python3-lxml [(platform:redhat platform:base-py3)] +# base-py2 covers CentOS<8, Fedora<23, RHEL<8 +python-lxml [(platform:redhat platform:base-py2)] dev-python/lxml [platform:gentoo] # Note that python3-all-dev includes python3-all, added # both here for documentary purpose. diff --git a/bindep/tests/fixtures/fedora/etc/os-release b/bindep/tests/fixtures/fedora23/etc/os-release similarity index 100% rename from bindep/tests/fixtures/fedora/etc/os-release rename to bindep/tests/fixtures/fedora23/etc/os-release diff --git a/bindep/tests/fixtures/rhel8/etc/os-release b/bindep/tests/fixtures/rhel8/etc/os-release new file mode 100644 index 0000000..36051a7 --- /dev/null +++ b/bindep/tests/fixtures/rhel8/etc/os-release @@ -0,0 +1,16 @@ +NAME="Red Hat Enterprise Linux" +VERSION="8.0 (Ootpa)" +ID="rhel" +ID_LIKE="fedora" +VERSION_ID="8.0" +PLATFORM_ID="platform:el8" +PRETTY_NAME="Red Hat Enterprise Linux 8.0 (Ootpa)" +ANSI_COLOR="0;31" +CPE_NAME="cpe:/o:redhat:enterprise_linux:8.0:GA" +HOME_URL="https://www.redhat.com/" +BUG_REPORT_URL="https://bugzilla.redhat.com/" + +REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 8" +REDHAT_BUGZILLA_PRODUCT_VERSION=8.0 +REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" +REDHAT_SUPPORT_PRODUCT_VERSION="8.0" diff --git a/bindep/tests/fixtures/rhelserver/etc/os-release b/bindep/tests/fixtures/rhelserver7/etc/os-release similarity index 100% rename from bindep/tests/fixtures/rhelserver/etc/os-release rename to bindep/tests/fixtures/rhelserver7/etc/os-release diff --git a/bindep/tests/fixtures/rhelworkstation/etc/os-release b/bindep/tests/fixtures/rhelworkstation7/etc/os-release similarity index 100% rename from bindep/tests/fixtures/rhelworkstation/etc/os-release rename to bindep/tests/fixtures/rhelworkstation7/etc/os-release diff --git a/bindep/tests/test_depends.py b/bindep/tests/test_depends.py index 31f227f..3c4224a 100644 --- a/bindep/tests/test_depends.py +++ b/bindep/tests/test_depends.py @@ -129,8 +129,8 @@ class TestDepends(TestCase): platform_profiles = depends.platform_profiles() self.assertThat(platform_profiles, Contains("platform:darwin")) - def test_detects_rhel(self): - with DistroFixture("RHELServer"): + def test_detects_rhel7(self): + with DistroFixture("RHELServer7"): depends = Depends("") platform_profiles = depends.platform_profiles() self.assertThat( @@ -142,9 +142,10 @@ class TestDepends(TestCase): self.assertThat( platform_profiles, Contains("platform:redhat")) + self.assertThat(platform_profiles, Contains("platform:base-py2")) def test_detects_rhel_workstation(self): - with DistroFixture("RHELWorkstation"): + with DistroFixture("RHELWorkstation7"): depends = Depends("") platform_profiles = depends.platform_profiles() self.assertThat( @@ -156,13 +157,22 @@ class TestDepends(TestCase): self.assertThat( platform_profiles, Contains("platform:redhat")) + self.assertThat(platform_profiles, Contains("platform:base-py2")) - def test_detects_fedora(self): - with DistroFixture("Fedora"): + def test_detects_fedora23(self): + with DistroFixture("Fedora23"): depends = Depends("") platform_profiles = depends.platform_profiles() self.assertThat(platform_profiles, Contains("platform:fedora")) self.assertThat(platform_profiles, Contains("platform:redhat")) + self.assertThat(platform_profiles, Contains("platform:base-py3")) + + def test_detects_rhel8(self): + with DistroFixture("rhel8"): + depends = Depends("") + platform_profiles = depends.platform_profiles() + self.assertThat(platform_profiles, Contains("platform:redhat")) + self.assertThat(platform_profiles, Contains("platform:base-py3")) def test_detects_opensuse_project(self): # TODO what does an os-release for opensuse project look like? @@ -243,14 +253,14 @@ class TestDepends(TestCase): self.assertIsInstance(depends.platform, Rpm) def test_rhel_implies_rpm(self): - with DistroFixture("RHELServer"): + with DistroFixture("RHELServer7"): depends = Depends("") self.assertThat( depends.platform_profiles(), Contains("platform:rpm")) self.assertIsInstance(depends.platform, Rpm) def test_fedora_implies_rpm(self): - with DistroFixture("Fedora"): + with DistroFixture("Fedora23"): depends = Depends("") self.assertThat( depends.platform_profiles(), Contains("platform:rpm"))