From 0d43f4a237ca7716ec81dfad730107b15b4f052e Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Thu, 5 Oct 2017 17:34:48 +0000 Subject: [PATCH 01/10] added DEBPackage.satisfies() --- niceman/distributions/debian.py | 15 ++++++++++++- niceman/distributions/tests/test_debian.py | 25 +++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/niceman/distributions/debian.py b/niceman/distributions/debian.py index 48d622174..aff88a7f9 100644 --- a/niceman/distributions/debian.py +++ b/niceman/distributions/debian.py @@ -109,8 +109,21 @@ class DEBPackage(Package): # nah -- ATM goes directly into DebianDistribution.apt_sources # apt_sources = TypedList(APTSource) files = attr.ib(default=attr.Factory(list)) # Might want a File structure for advanced tracking -_register_with_representer(DEBPackage) + def satisfies(self, other): + if not isinstance(other, Package): + raise TypeError('satisfies() requires a package argument') + if not isinstance(other, DEBPackage): + return False + if self.name != other.name: + return False + if self.version is None: + return other.version is None + if other.version is None: + return True + return self.version == other.version + +_register_with_representer(DEBPackage) @attr.s class DebianDistribution(Distribution): diff --git a/niceman/distributions/tests/test_debian.py b/niceman/distributions/tests/test_debian.py index 141936b5b..9638bc6bb 100644 --- a/niceman/distributions/tests/test_debian.py +++ b/niceman/distributions/tests/test_debian.py @@ -16,6 +16,9 @@ from pprint import pprint from niceman.distributions.debian import DebTracer +from niceman.distributions.debian import DEBPackage + +import pytest import mock from niceman.tests.utils import skip_if @@ -136,4 +139,24 @@ def _run_dpkg_query(subfiles): '/usr/bin/fail2ban-server': {'name': u'fail2ban'}, '/usr/lib/afni/bin/afni': {'name': u'afni'}, '/bin/sh': {'name': u'dash'} - } \ No newline at end of file + } + +@pytest.fixture +def setup_packages(): + """set up the package comparison tests""" + a = DEBPackage(name='p1') + b = DEBPackage(name='p1', version='1.0') + c = DEBPackage(name='p1', version='1.1') + d = DEBPackage(name='p2') + return (a, b, c, d) + +def test_package_satisfies(setup_packages): + (p1, p1v1, p1v11, p2) = setup_packages + assert p1.satisfies(p1) is True + assert p1v1.satisfies(p1v1) is True + assert p1.satisfies(p1v1) is False + assert p1v1.satisfies(p1) is True + assert p1v1.satisfies(p1v11) is False + assert p1.satisfies(p2) is False + assert p1v1.satisfies(p2) is False + assert p2.satisfies(p1v1) is False From 257575cbd08300eae14f3893ae2d292b8b795a02 Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Thu, 5 Oct 2017 18:19:40 +0000 Subject: [PATCH 02/10] added DebianDistribution.satisfies_package() --- niceman/distributions/debian.py | 14 +++++++++ niceman/distributions/tests/test_debian.py | 33 +++++++++++++++++----- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/niceman/distributions/debian.py b/niceman/distributions/debian.py index aff88a7f9..c7c1aef31 100644 --- a/niceman/distributions/debian.py +++ b/niceman/distributions/debian.py @@ -111,6 +111,8 @@ class DEBPackage(Package): files = attr.ib(default=attr.Factory(list)) # Might want a File structure for advanced tracking def satisfies(self, other): + """return True if this package (self) satisfies the requirements of + the passed package (other)""" if not isinstance(other, Package): raise TypeError('satisfies() requires a package argument') if not isinstance(other, DEBPackage): @@ -192,6 +194,18 @@ def normalize(self): # would make us require supporting flexible typing -- string or a list pass + def satisfies_package(self, package): + """return True if this distribution (self) satisfies the requirements + of the passed package""" + if not isinstance(package, Package): + raise TypeError('satisfies_package() requires a package argument') + if not isinstance(package, DEBPackage): + return False + for p in self.packages: + if p.satisfies(package): + return True + return False + # to grow: # def __iadd__(self, another_instance or DEBPackage, or APTSource) # def __add__(self, another_instance or DEBPackage, or APTSource) diff --git a/niceman/distributions/tests/test_debian.py b/niceman/distributions/tests/test_debian.py index 9638bc6bb..71e780895 100644 --- a/niceman/distributions/tests/test_debian.py +++ b/niceman/distributions/tests/test_debian.py @@ -17,6 +17,7 @@ from niceman.distributions.debian import DebTracer from niceman.distributions.debian import DEBPackage +from niceman.distributions.debian import DebianDistribution import pytest @@ -151,12 +152,30 @@ def setup_packages(): return (a, b, c, d) def test_package_satisfies(setup_packages): - (p1, p1v1, p1v11, p2) = setup_packages + (p1, p1v10, p1v11, p2) = setup_packages assert p1.satisfies(p1) is True - assert p1v1.satisfies(p1v1) is True - assert p1.satisfies(p1v1) is False - assert p1v1.satisfies(p1) is True - assert p1v1.satisfies(p1v11) is False + assert p1v10.satisfies(p1v10) is True + assert p1.satisfies(p1v10) is False + assert p1v10.satisfies(p1) is True + assert p1v10.satisfies(p1v11) is False assert p1.satisfies(p2) is False - assert p1v1.satisfies(p2) is False - assert p2.satisfies(p1v1) is False + assert p1v10.satisfies(p2) is False + assert p2.satisfies(p1v10) is False + +@pytest.fixture +def setup_distributions(): + (p1, p1v10, p1v11, p2) = setup_packages() + d1 = DebianDistribution(name='debian 1') + d1.packages = [p1] + d2 = DebianDistribution(name='debian 2') + d2.packages = [p1v11] + return (d1, d2) + +def test_distribution_satisfies_package(setup_distributions, setup_packages): + (d1, d2) = setup_distributions + (p1, p1v10, p1v11, p2) = setup_packages + assert d1.satisfies_package(p1) is True + assert d1.satisfies_package(p1v10) is False + assert d2.satisfies_package(p1) is True + assert d2.satisfies_package(p1v10) is False + assert d2.satisfies_package(p1v11) is True From ff25fedab27c16a32fc2061f0a168b82776c65e4 Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Thu, 5 Oct 2017 18:23:18 +0000 Subject: [PATCH 03/10] created DebianDistribution.satisfies() --- niceman/distributions/debian.py | 12 ++++++++++++ niceman/distributions/tests/test_debian.py | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/niceman/distributions/debian.py b/niceman/distributions/debian.py index c7c1aef31..4f7fc53f4 100644 --- a/niceman/distributions/debian.py +++ b/niceman/distributions/debian.py @@ -206,6 +206,18 @@ def satisfies_package(self, package): return True return False + def satisfies(self, other): + """return True if this distribution (self) satisfies the requirements + of the other distribution (other)""" + if not isinstance(other, Distribution): + raise TypeError('satisfies() requires a package argument') + if not isinstance(other, DebianDistribution): + return False + for p in other.packages: + if not self.satisfies_package(p): + return False + return True + # to grow: # def __iadd__(self, another_instance or DEBPackage, or APTSource) # def __add__(self, another_instance or DEBPackage, or APTSource) diff --git a/niceman/distributions/tests/test_debian.py b/niceman/distributions/tests/test_debian.py index 71e780895..a046807aa 100644 --- a/niceman/distributions/tests/test_debian.py +++ b/niceman/distributions/tests/test_debian.py @@ -179,3 +179,8 @@ def test_distribution_satisfies_package(setup_distributions, setup_packages): assert d2.satisfies_package(p1) is True assert d2.satisfies_package(p1v10) is False assert d2.satisfies_package(p1v11) is True + +def test_distributions(setup_distributions): + (d1, d2) = setup_distributions + assert d1.satisfies(d2) is False + assert d2.satisfies(d1) is True From c7809dab173212a5ade912e01ac250dd1bab2477 Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Fri, 6 Oct 2017 18:50:31 +0000 Subject: [PATCH 04/10] tightened DebianDistribution.satisfies() test --- niceman/distributions/debian.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/niceman/distributions/debian.py b/niceman/distributions/debian.py index 4f7fc53f4..5149f3215 100644 --- a/niceman/distributions/debian.py +++ b/niceman/distributions/debian.py @@ -15,6 +15,8 @@ import collections from collections import defaultdict +from six.moves import map + import pytz import yaml @@ -213,10 +215,7 @@ def satisfies(self, other): raise TypeError('satisfies() requires a package argument') if not isinstance(other, DebianDistribution): return False - for p in other.packages: - if not self.satisfies_package(p): - return False - return True + return all(map(self.satisfies_package, other.packages)) # to grow: # def __iadd__(self, another_instance or DEBPackage, or APTSource) From 9c0039d0782a6c56327fad9431d101659408d19a Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Fri, 6 Oct 2017 18:51:01 +0000 Subject: [PATCH 05/10] tightened distribution operations test assertions --- niceman/distributions/tests/test_debian.py | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/niceman/distributions/tests/test_debian.py b/niceman/distributions/tests/test_debian.py index a046807aa..7e339fc2b 100644 --- a/niceman/distributions/tests/test_debian.py +++ b/niceman/distributions/tests/test_debian.py @@ -153,14 +153,14 @@ def setup_packages(): def test_package_satisfies(setup_packages): (p1, p1v10, p1v11, p2) = setup_packages - assert p1.satisfies(p1) is True - assert p1v10.satisfies(p1v10) is True - assert p1.satisfies(p1v10) is False - assert p1v10.satisfies(p1) is True - assert p1v10.satisfies(p1v11) is False - assert p1.satisfies(p2) is False - assert p1v10.satisfies(p2) is False - assert p2.satisfies(p1v10) is False + assert p1.satisfies(p1) + assert p1v10.satisfies(p1v10) + assert not p1.satisfies(p1v10) + assert p1v10.satisfies(p1) + assert not p1v10.satisfies(p1v11) + assert not p1.satisfies(p2) + assert not p1v10.satisfies(p2) + assert not p2.satisfies(p1v10) @pytest.fixture def setup_distributions(): @@ -174,13 +174,13 @@ def setup_distributions(): def test_distribution_satisfies_package(setup_distributions, setup_packages): (d1, d2) = setup_distributions (p1, p1v10, p1v11, p2) = setup_packages - assert d1.satisfies_package(p1) is True - assert d1.satisfies_package(p1v10) is False - assert d2.satisfies_package(p1) is True - assert d2.satisfies_package(p1v10) is False - assert d2.satisfies_package(p1v11) is True + assert d1.satisfies_package(p1) + assert not d1.satisfies_package(p1v10) + assert d2.satisfies_package(p1) + assert not d2.satisfies_package(p1v10) + assert d2.satisfies_package(p1v11) def test_distributions(setup_distributions): (d1, d2) = setup_distributions - assert d1.satisfies(d2) is False - assert d2.satisfies(d1) is True + assert not d1.satisfies(d2) + assert d2.satisfies(d1) From 9d92c48f16310da7f02d7f94e24fe3979e37d11a Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Thu, 12 Oct 2017 15:05:19 +0000 Subject: [PATCH 06/10] fixed test name --- niceman/distributions/tests/test_debian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/niceman/distributions/tests/test_debian.py b/niceman/distributions/tests/test_debian.py index 7e339fc2b..982179831 100644 --- a/niceman/distributions/tests/test_debian.py +++ b/niceman/distributions/tests/test_debian.py @@ -180,7 +180,7 @@ def test_distribution_satisfies_package(setup_distributions, setup_packages): assert not d2.satisfies_package(p1v10) assert d2.satisfies_package(p1v11) -def test_distributions(setup_distributions): +def test_distribution_statisfies(setup_distributions): (d1, d2) = setup_distributions assert not d1.satisfies(d2) assert d2.satisfies(d1) From 829ecde9a34f34295797c8006071064c3a6e68c4 Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Thu, 12 Oct 2017 15:08:53 +0000 Subject: [PATCH 07/10] fixed error message --- niceman/distributions/debian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/niceman/distributions/debian.py b/niceman/distributions/debian.py index 5149f3215..b5bfcc58b 100644 --- a/niceman/distributions/debian.py +++ b/niceman/distributions/debian.py @@ -212,7 +212,7 @@ def satisfies(self, other): """return True if this distribution (self) satisfies the requirements of the other distribution (other)""" if not isinstance(other, Distribution): - raise TypeError('satisfies() requires a package argument') + raise TypeError('satisfies() requires a distribution argument') if not isinstance(other, DebianDistribution): return False return all(map(self.satisfies_package, other.packages)) From 161ae93eca60cd0b08ee74ad5eff3e8767d66367 Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Thu, 12 Oct 2017 15:35:10 +0000 Subject: [PATCH 08/10] added DebianDistribution.__sub__() --- niceman/distributions/debian.py | 7 +++++++ niceman/distributions/tests/test_debian.py | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/niceman/distributions/debian.py b/niceman/distributions/debian.py index b5bfcc58b..49eb83f85 100644 --- a/niceman/distributions/debian.py +++ b/niceman/distributions/debian.py @@ -217,6 +217,13 @@ def satisfies(self, other): return False return all(map(self.satisfies_package, other.packages)) + def __sub__(self, other): + # the semantics of distribution subtraction are, for d1 - d2: + # what is specified in d1 that is not specified in d2 + # or how does d2 fall short of d1 + # or what is in d1 that isn't satisfied by d2 + return [ p for p in self.packages if not other.satisfies_package(p) ] + # to grow: # def __iadd__(self, another_instance or DEBPackage, or APTSource) # def __add__(self, another_instance or DEBPackage, or APTSource) diff --git a/niceman/distributions/tests/test_debian.py b/niceman/distributions/tests/test_debian.py index 982179831..d9762d6fb 100644 --- a/niceman/distributions/tests/test_debian.py +++ b/niceman/distributions/tests/test_debian.py @@ -184,3 +184,14 @@ def test_distribution_statisfies(setup_distributions): (d1, d2) = setup_distributions assert not d1.satisfies(d2) assert d2.satisfies(d1) + +def test_distribution_sub(): + (p1, p1v10, p1v11, p2) = setup_packages() + d1 = DebianDistribution(name='debian 1') + d1.packages = [p1, p2] + d2 = DebianDistribution(name='debian 2') + d2.packages = [p1v11, p2] + assert d1-d2 == [] + result = d2-d1 + assert len(result) == 1 + assert result[0] == p1v11 From d45a25cf5edda188455da851feaee8447317b0d2 Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Wed, 18 Oct 2017 17:44:12 +0000 Subject: [PATCH 09/10] added architecture to debian package and distribution satisfies() operations --- niceman/distributions/debian.py | 11 ++++++----- niceman/distributions/tests/test_debian.py | 21 +++++++++++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/niceman/distributions/debian.py b/niceman/distributions/debian.py index 49eb83f85..ccf50202e 100644 --- a/niceman/distributions/debian.py +++ b/niceman/distributions/debian.py @@ -121,11 +121,12 @@ def satisfies(self, other): return False if self.name != other.name: return False - if self.version is None: - return other.version is None - if other.version is None: - return True - return self.version == other.version + if other.version is not None and self.version != other.version: + return False + if other.architecture is not None \ + and self.architecture != other.architecture: + return False + return True _register_with_representer(DEBPackage) diff --git a/niceman/distributions/tests/test_debian.py b/niceman/distributions/tests/test_debian.py index d9762d6fb..8ce244374 100644 --- a/niceman/distributions/tests/test_debian.py +++ b/niceman/distributions/tests/test_debian.py @@ -148,11 +148,14 @@ def setup_packages(): a = DEBPackage(name='p1') b = DEBPackage(name='p1', version='1.0') c = DEBPackage(name='p1', version='1.1') - d = DEBPackage(name='p2') - return (a, b, c, d) + d = DEBPackage(name='p1', architecture='i386') + e = DEBPackage(name='p1', architecture='alpha') + f = DEBPackage(name='p1', version='1.1', architecture='i386') + g = DEBPackage(name='p2') + return (a, b, c, d, e, f, g) def test_package_satisfies(setup_packages): - (p1, p1v10, p1v11, p2) = setup_packages + (p1, p1v10, p1v11, p1ai, p1aa, p1v11ai, p2) = setup_packages assert p1.satisfies(p1) assert p1v10.satisfies(p1v10) assert not p1.satisfies(p1v10) @@ -161,10 +164,16 @@ def test_package_satisfies(setup_packages): assert not p1.satisfies(p2) assert not p1v10.satisfies(p2) assert not p2.satisfies(p1v10) + assert not p1v10.satisfies(p1aa) + assert p1aa.satisfies(p1) + assert not p1aa.satisfies(p1v10) + assert not p1aa.satisfies(p1ai) + assert not p1v11.satisfies(p1v11ai) + assert p1v11ai.satisfies(p1v11) @pytest.fixture def setup_distributions(): - (p1, p1v10, p1v11, p2) = setup_packages() + (p1, p1v10, p1v11, p1ai, p1aa, p1v11ai, p2) = setup_packages() d1 = DebianDistribution(name='debian 1') d1.packages = [p1] d2 = DebianDistribution(name='debian 2') @@ -173,7 +182,7 @@ def setup_distributions(): def test_distribution_satisfies_package(setup_distributions, setup_packages): (d1, d2) = setup_distributions - (p1, p1v10, p1v11, p2) = setup_packages + (p1, p1v10, p1v11, p1ai, p1aa, p1v11ai, p2) = setup_packages assert d1.satisfies_package(p1) assert not d1.satisfies_package(p1v10) assert d2.satisfies_package(p1) @@ -186,7 +195,7 @@ def test_distribution_statisfies(setup_distributions): assert d2.satisfies(d1) def test_distribution_sub(): - (p1, p1v10, p1v11, p2) = setup_packages() + (p1, p1v10, p1v11, p1ai, p1aa, p1v11ai, p2) = setup_packages() d1 = DebianDistribution(name='debian 1') d1.packages = [p1, p2] d2 = DebianDistribution(name='debian 2') From 1116e4adc491ecc98180d0b87175edf9ca0bb78c Mon Sep 17 00:00:00 2001 From: Christian Haselgrove Date: Wed, 18 Oct 2017 17:47:19 +0000 Subject: [PATCH 10/10] refactored final logic in DebianDistribution.satisfies_package() --- niceman/distributions/debian.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/niceman/distributions/debian.py b/niceman/distributions/debian.py index ccf50202e..a18e06a23 100644 --- a/niceman/distributions/debian.py +++ b/niceman/distributions/debian.py @@ -204,10 +204,7 @@ def satisfies_package(self, package): raise TypeError('satisfies_package() requires a package argument') if not isinstance(package, DEBPackage): return False - for p in self.packages: - if p.satisfies(package): - return True - return False + return any([ p.satisfies(package) for p in self.packages ]) def satisfies(self, other): """return True if this distribution (self) satisfies the requirements