Skip to content

Fix #244: Allow list & str for comparison #245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
54 changes: 49 additions & 5 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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::
Expand All @@ -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`.

Expand Down
2 changes: 1 addition & 1 deletion semver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
113 changes: 88 additions & 25 deletions test_semver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
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