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"))