Skip to content

Commit

Permalink
Raise CannotDecide for missing version part
Browse files Browse the repository at this point in the history
If you want to compare you need to have version defined on both sides.
Alphabetical order doesn't make sense for these use cases

Resolves #89
  • Loading branch information
lukaszachy committed Nov 23, 2020
1 parent fa05dd9 commit eb07eec
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 20 deletions.
29 changes: 16 additions & 13 deletions fmf/context.py
Expand Up @@ -50,14 +50,17 @@ def __str__(self):
def __repr__(self):
return "{}({})".format(self.__class__.__name__, repr(self._to_compare))

def version_cmp(self, other, minor_mode=False):
def version_cmp(self, other, minor_mode=False, ordered=False):

if not isinstance(other, self.__class__):
raise CannotDecide("Invalid types")

if len(self._to_compare) == 0 or len(other._to_compare) == 0:
raise CannotDecide("Empty name part")

if ordered and (len(self._to_compare) == 1 or len(other._to_compare) == 1):
raise CannotDecide("Missing version part, cannot evaluate order")

if minor_mode:
if self._to_compare[0] != other._to_compare[0]:
raise CannotDecide("Name parts differ")
Expand Down Expand Up @@ -120,95 +123,95 @@ def _op_eq(self, dimension_name, values):
""" '=' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val) == 0
return dimension_value.version_cmp(it_val, ordered=False) == 0

return self._op_core(dimension_name, values, comparator)

def _op_not_eq(self, dimension_name, values):
""" '!=' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val) != 0
return dimension_value.version_cmp(it_val, ordered=False) != 0

return self._op_core(dimension_name, values, comparator)

def _op_minor_eq(self, dimension_name, values):
""" '~=' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val, minor_mode=True) == 0
return dimension_value.version_cmp(it_val, minor_mode=True, ordered=False) == 0

return self._op_core(dimension_name, values, comparator)

def _op_minor_not_eq(self, dimension_name, values):
""" '~!=' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val, minor_mode=True) != 0
return dimension_value.version_cmp(it_val, minor_mode=True, ordered=False) != 0

return self._op_core(dimension_name, values, comparator)

def _op_minor_less_or_eq(self, dimension_name, values):
""" '~<=' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val, minor_mode=True) <= 0
return dimension_value.version_cmp(it_val, minor_mode=True, ordered=False) <= 0

return self._op_core(dimension_name, values, comparator)

def _op_minor_less(self, dimension_name, values):
""" '~<' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val, minor_mode=True) < 0
return dimension_value.version_cmp(it_val, minor_mode=True, ordered=True) < 0

return self._op_core(dimension_name, values, comparator)

def _op_less(self, dimension_name, values):
""" '<' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val) < 0
return dimension_value.version_cmp(it_val, ordered=True) < 0

return self._op_core(dimension_name, values, comparator)

def _op_less_or_equal(self, dimension_name, values):
""" '<=' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val) <= 0
return dimension_value.version_cmp(it_val, ordered=False) <= 0

return self._op_core(dimension_name, values, comparator)

def _op_greater_or_equal(self, dimension_name, values):
""" '>=' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val) >= 0
return dimension_value.version_cmp(it_val, ordered=False) >= 0

return self._op_core(dimension_name, values, comparator)

def _op_minor_greater_or_equal(self, dimension_name, values):
""" '~>=' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val, minor_mode=True) >= 0
return dimension_value.version_cmp(it_val, minor_mode=True, ordered=False) >= 0

return self._op_core(dimension_name, values, comparator)

def _op_greater(self, dimension_name, values):
""" '>' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val) > 0
return dimension_value.version_cmp(it_val, ordered=True) > 0

return self._op_core(dimension_name, values, comparator)

def _op_minor_greater(self, dimension_name, values):
""" '~>' operator """

def comparator(dimension_value, it_val):
return dimension_value.version_cmp(it_val, minor_mode=True) > 0
return dimension_value.version_cmp(it_val, minor_mode=True, ordered=True) > 0

return self._op_core(dimension_name, values, comparator)

Expand Down
43 changes: 36 additions & 7 deletions tests/unit/test_context.py
Expand Up @@ -141,16 +141,29 @@ def test_version_cmp(self):
first = ContextValue("name")
assert first.version_cmp(ContextValue("name")) == 0
assert first.version_cmp(ContextValue("name"), minor_mode=True) == 0
assert first.version_cmp(ContextValue("name-1")) == 0
assert first.version_cmp(ContextValue("name-1"), minor_mode=True) == 0
assert first.version_cmp(ContextValue("name-1-2")) == 0
with pytest.raises(CannotDecide):
first.version_cmp(ContextValue("name"), ordered=True)
assert first.version_cmp(ContextValue("name"), ordered=False) == 0

assert first.version_cmp(ContextValue("name-1"), ordered=False) == 0
assert first.version_cmp(ContextValue("name-1"), minor_mode=True, ordered=False) == 0
with pytest.raises(CannotDecide):
first.version_cmp(ContextValue("name-1"), ordered=True)
with pytest.raises(CannotDecide):
first.version_cmp(ContextValue("name-1"), minor_mode=True, ordered=True)

assert first.version_cmp(ContextValue("name-1-2"), ordered=False) == 0
# Name X name-1-2 has no major nor minor on the left side
assert (
first.version_cmp(ContextValue("name-1-2"), minor_mode=True) == 0)
first.version_cmp(ContextValue("name-1-2"), minor_mode=True, ordered=False) == 0)

second = ContextValue("name-1-2-3")
assert second.version_cmp(ContextValue("name")) == 0
assert second.version_cmp(ContextValue("name"), minor_mode=True) == 0
assert second.version_cmp(ContextValue("name"), ordered=False) == 0
with pytest.raises(CannotDecide):
second.version_cmp(ContextValue("name"), ordered=True)
assert second.version_cmp(ContextValue("name"), minor_mode=True, ordered=False) == 0
with pytest.raises(CannotDecide):
second.version_cmp(ContextValue("name"), minor_mode=True, ordered=True) == 0
assert second.version_cmp(ContextValue("name-1")) == 0
assert (
second.version_cmp(ContextValue("name-1"), minor_mode=True) == 0)
Expand Down Expand Up @@ -377,19 +390,22 @@ def test_matches(self):

# ==
assert context.matches("distro == fedora-32")
assert context.matches("distro == fedora")
assert not context.matches("distro == centos-8")
with pytest.raises(CannotDecide):
context.matches("product == fedora-32")

# !=
assert not context.matches("distro != fedora-32")
assert not context.matches("distro != fedora")
assert context.matches("distro != centos-8")
with pytest.raises(CannotDecide):
context.matches("product != fedora-32")

# ~= aka major/minor mode
assert context.matches("distro ~= fedora")
context.matches("distro ~= fedora-45")
assert context.matches("distro ~= fedora-32")
assert not context.matches("distro ~= fedora-45")
with pytest.raises(CannotDecide): # fedora is not centos
context.matches("distro ~= centos-8")
with pytest.raises(CannotDecide): # dimension product is not defined
Expand All @@ -400,22 +416,28 @@ def test_matches(self):
assert not context.matches("distro < fedora-32")
with pytest.raises(CannotDecide):
context.matches("product < centos-8")
with pytest.raises(CannotDecide):
context.matches("distro < fedora")

# '~<':
assert context.matches("distro ~< fedora-33")
with pytest.raises(CannotDecide):
context.matches("distro ~< centos-8")
with pytest.raises(CannotDecide):
context.matches("product ~< centos-8")
with pytest.raises(CannotDecide):
context.matches("distro ~< fedora")

# '<=':
assert context.matches("distro <= fedora-32")
assert context.matches("distro <= fedora")
assert not context.matches("distro <= fedora-30")
with pytest.raises(CannotDecide):
context.matches("product <= centos-8")

# '~<='
assert context.matches("distro ~<= fedora-33")
assert context.matches("distro ~<= fedora")
with pytest.raises(CannotDecide):
context.matches("distro ~<= centos-8")
with pytest.raises(CannotDecide):
Expand All @@ -424,19 +446,22 @@ def test_matches(self):
# '~!=':
assert context.matches("distro ~!= fedora-33")
assert not context.matches("distro ~!= fedora-32")
assert not context.matches("distro ~!= fedora")
with pytest.raises(CannotDecide):
context.matches("distro ~!= centos-8")
with pytest.raises(CannotDecide):
context.matches("product ~!= centos-8")

# '>=':
assert context.matches("distro >= fedora-32")
assert context.matches("distro >= fedora")
assert not context.matches("distro >= fedora-40")
with pytest.raises(CannotDecide):
context.matches("product >= centos-8")

# '~>=':
assert context.matches("distro ~>= fedora-32")
assert context.matches("distro ~>= fedora")
assert not context.matches("distro ~>= fedora-33")
with pytest.raises(CannotDecide):
context.matches("distro ~>= centos-8")
Expand All @@ -446,6 +471,8 @@ def test_matches(self):
# '>':
assert context.matches("distro > fedora-30")
assert not context.matches("distro > fedora-40")
with pytest.raises(CannotDecide):
context.matches("distro > fedora")
with pytest.raises(CannotDecide):
context.matches("product > centos-8")

Expand All @@ -456,6 +483,8 @@ def test_matches(self):
context.matches("distro ~> centos-8")
with pytest.raises(CannotDecide):
context.matches("product ~> centos-8")
with pytest.raises(CannotDecide):
context.matches("distro ~> fedora")


class TestOperators(object):
Expand Down

0 comments on commit eb07eec

Please sign in to comment.