diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ddefadcb..930f81d3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -24,6 +24,7 @@ Bug Fixes * :gh:`224` (:pr:`226`): In ``setup.py``, replaced in class ``clean``, ``super(CleanCommand, self).run()`` with ``CleanCommand.run(self)`` +* :gh:`244` (:pr:`245`): Allow comparison with ``VersionInfo``, tuple/list, dict, and string. Additions diff --git a/docs/usage.rst b/docs/usage.rst index 91e4d069..0f1f21d3 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -295,7 +295,7 @@ To compare two versions depends on your type: The return value is negative if ``version1 < version2``, zero if ``version1 == version2`` and strictly positive if ``version1 > version2``. -* **Two** :class:`semver.VersionInfo` **types** +* **Two** :class:`semver.VersionInfo` **instances** Use the specific operator. Currently, the operators ``<``, ``<=``, ``>``, ``>=``, ``==``, and ``!=`` are supported:: @@ -307,24 +307,68 @@ To compare two versions depends on your type: >>> v1 > v2 False -* **A** :class:`semver.VersionInfo` **type and a** ``tuple`` +* **A** :class:`semver.VersionInfo` **type and a** :func:`tuple` **or** :func:`list` Use the operator as with two :class:`semver.VersionInfo` types:: >>> v = semver.VersionInfo.parse("3.4.5") >>> v > (1, 0) True - >>> v < (3, 5) + >>> v < [3, 5] True The opposite does also work:: >>> (1, 0) < v True - >>> (3, 5) > v + >>> [3, 5] > v True -Other types cannot be compared (like dictionaries, lists etc). +* **A** :class:`semver.VersionInfo` **type and a** :func:`str` + + You can use also raw strings to compare:: + + >>> v > "1.0.0" + True + >>> v < "3.5.0" + True + + The opposite does also work:: + + >>> "1.0.0" < v + True + >>> "3.5.0" > v + True + + However, if you compare incomplete strings, you get a :class:`ValueError` exception:: + + >>> v > "1.0" + Traceback (most recent call last): + ... + ValueError: 1.0 is not valid SemVer string + +* **A** :class:`semver.VersionInfo` **type and a** :func:`dict` + + You can also use a dictionary. In contrast to strings, you can have an "incomplete" + version (as the other parts are set to zero):: + + >>> v > dict(major=1) + True + + The opposite does also work:: + + >>> dict(major=1) < v + True + + If the dictionary contains unknown keys, you get a :class:`TypeError` exception:: + + >>> v > dict(major=1, unknown=42) + Traceback (most recent call last): + ... + TypeError: __init__() got an unexpected keyword argument 'unknown' + + +Other types cannot be compared. If you need to convert some types into other, refer to :ref:`sec.convert.versions`. diff --git a/semver.py b/semver.py index a5739b16..a512a431 100644 --- a/semver.py +++ b/semver.py @@ -112,7 +112,7 @@ def comparator(operator): @wraps(operator) def wrapper(self, other): - comparable_types = (VersionInfo, dict, tuple) + comparable_types = (VersionInfo, dict, tuple, list, str) if not isinstance(other, comparable_types): raise TypeError( "other type %r must be in %r" % (type(other), comparable_types) diff --git a/test_semver.py b/test_semver.py index 5daf3f1a..3737bbcb 100644 --- a/test_semver.py +++ b/test_semver.py @@ -557,37 +557,100 @@ def test_should_compare_version_dictionaries(): assert not (v1 == v4) -def test_should_compare_version_tuples(): - v0 = VersionInfo(major=0, minor=4, patch=5, prerelease="pre.2", build="build.4") - v1 = VersionInfo(major=3, minor=4, patch=5, prerelease="pre.2", build="build.4") - for t in ( +@pytest.mark.parametrize( + "t", # fmt: off + ( (1, 0, 0), (1, 0), (1,), (1, 0, 0, "pre.2"), (1, 0, 0, "pre.2", "build.4"), - ): - assert v0 < t - assert v0 <= t - assert v0 != t - assert not v0 == t - assert v1 > t - assert v1 >= t - # Symmetric - assert t > v0 - assert t >= v0 - assert t < v1 - assert t <= v1 - assert t != v0 - assert not t == v0 - - -def test_should_not_allow_to_compare_version_with_string(): + ), # fmt: on +) +def test_should_compare_version_tuples(t): + v0 = VersionInfo(major=0, minor=4, patch=5, prerelease="pre.2", build="build.4") v1 = VersionInfo(major=3, minor=4, patch=5, prerelease="pre.2", build="build.4") - with pytest.raises(TypeError): - v1 > "1.0.0" - with pytest.raises(TypeError): - "1.0.0" > v1 + + assert v0 < t + assert v0 <= t + assert v0 != t + assert not v0 == t + assert v1 > t + assert v1 >= t + # Symmetric + assert t > v0 + assert t >= v0 + assert t < v1 + assert t <= v1 + assert t != v0 + assert not t == v0 + + +@pytest.mark.parametrize( + "lst", # fmt: off + ( + [1, 0, 0], + [1, 0], + [1], + [1, 0, 0, "pre.2"], + [1, 0, 0, "pre.2", "build.4"], + ), # fmt: on +) +def test_should_compare_version_list(lst): + v0 = VersionInfo(major=0, minor=4, patch=5, prerelease="pre.2", build="build.4") + v1 = VersionInfo(major=3, minor=4, patch=5, prerelease="pre.2", build="build.4") + + assert v0 < lst + assert v0 <= lst + assert v0 != lst + assert not v0 == lst + assert v1 > lst + assert v1 >= lst + # Symmetric + assert lst > v0 + assert lst >= v0 + assert lst < v1 + assert lst <= v1 + assert lst != v0 + assert not lst == v0 + + +@pytest.mark.parametrize( + "s", # fmt: off + ( + "1.0.0", + # "1.0", + # "1", + "1.0.0-pre.2", + "1.0.0-pre.2+build.4", + ), # fmt: on +) +def test_should_compare_version_string(s): + v0 = VersionInfo(major=0, minor=4, patch=5, prerelease="pre.2", build="build.4") + v1 = VersionInfo(major=3, minor=4, patch=5, prerelease="pre.2", build="build.4") + + assert v0 < s + assert v0 <= s + assert v0 != s + assert not v0 == s + assert v1 > s + assert v1 >= s + # Symmetric + assert s > v0 + assert s >= v0 + assert s < v1 + assert s <= v1 + assert s != v0 + assert not s == v0 + + +@pytest.mark.parametrize("s", ("1", "1.0", "1.0.x")) +def test_should_not_allow_to_compare_invalid_versionstring(s): + v = VersionInfo(major=3, minor=4, patch=5, prerelease="pre.2", build="build.4") + with pytest.raises(ValueError): + v < s + with pytest.raises(ValueError): + s > v def test_should_not_allow_to_compare_version_with_int(): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy