Skip to content

Commit 6bcfea0

Browse files
committed
Fix comparison in version subclasses
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent af41220 commit 6bcfea0

2 files changed

Lines changed: 104 additions & 5 deletions

File tree

src/univers/versions.py

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ def is_valid(cls, string):
172172
# 10.2alpha3..patch.4. → 10, 2, alpha, 3, patch, 4
173173
return super(GenericVersion, cls).is_valid(string)
174174

175+
def __lt__(self, other):
176+
if not isinstance(other, self.__class__):
177+
return NotImplemented
178+
return self.value < other.value
179+
180+
def __eq__(self, other):
181+
if not isinstance(other, self.__class__):
182+
return NotImplemented
183+
return self.value == other.value
184+
175185

176186
@attr.s(frozen=True, order=False, eq=False, hash=True)
177187
class PypiVersion(Version):
@@ -198,7 +208,15 @@ def is_valid(cls, string):
198208
except packaging_version.InvalidVersion:
199209
return False
200210

201-
return False
211+
def __lt__(self, other):
212+
if not isinstance(other, self.__class__):
213+
return NotImplemented
214+
return self.value < other.value
215+
216+
def __eq__(self, other):
217+
if not isinstance(other, self.__class__):
218+
return NotImplemented
219+
return self.value == other.value
202220

203221

204222
@attr.s(frozen=True, order=False, eq=False, hash=True)
@@ -248,6 +266,16 @@ def next_minor(self):
248266
def next_patch(self):
249267
return self.value and self.value.next_patch()
250268

269+
def __lt__(self, other):
270+
if not isinstance(other, self.__class__):
271+
return NotImplemented
272+
return self.value < other.value
273+
274+
def __eq__(self, other):
275+
if not isinstance(other, self.__class__):
276+
return NotImplemented
277+
return self.value == other.value
278+
251279

252280
def is_even(s):
253281
"""
@@ -264,7 +292,7 @@ def is_even(s):
264292
return (int(s) % 2) == 0
265293

266294

267-
@attr.s(frozen=True, order=False, eq=False, hash=True)
295+
# @attr.s(frozen=True, order=False, eq=False, hash=True)
268296
class NginxVersion(SemverVersion):
269297
"""
270298
Semver with 3 segments and extra attribute for stable vs. unstable branches
@@ -294,6 +322,16 @@ def build_value(cls, string):
294322
def is_valid(cls, string):
295323
return gem.GemVersion.is_correct(string)
296324

325+
def __lt__(self, other):
326+
if not isinstance(other, self.__class__):
327+
return NotImplemented
328+
return self.value < other.value
329+
330+
def __eq__(self, other):
331+
if not isinstance(other, self.__class__):
332+
return NotImplemented
333+
return self.value == other.value
334+
297335

298336
@attr.s(frozen=True, order=False, eq=False, hash=True)
299337
class ArchLinuxVersion(Version):
@@ -333,6 +371,16 @@ def build_value(cls, string):
333371
def is_valid(cls, string):
334372
return debian.Version.is_valid(string)
335373

374+
def __lt__(self, other):
375+
if not isinstance(other, self.__class__):
376+
return NotImplemented
377+
return self.value < other.value
378+
379+
def __eq__(self, other):
380+
if not isinstance(other, self.__class__):
381+
return NotImplemented
382+
return self.value == other.value
383+
336384

337385
@attr.s(frozen=True, order=False, eq=False, hash=True)
338386
class MavenVersion(Version):
@@ -343,6 +391,16 @@ class MavenVersion(Version):
343391
def build_value(cls, string):
344392
return maven.Version(string)
345393

394+
def __lt__(self, other):
395+
if not isinstance(other, self.__class__):
396+
return NotImplemented
397+
return self.value < other.value
398+
399+
def __eq__(self, other):
400+
if not isinstance(other, self.__class__):
401+
return NotImplemented
402+
return self.value == other.value
403+
346404

347405
# We will use total ordering to sort the versions, since these versions also consider prereleases.
348406
@attr.s(frozen=True, order=False, eq=False, hash=True)
@@ -386,6 +444,16 @@ class RpmVersion(Version):
386444
def build_value(cls, string):
387445
return rpm.RpmVersion.from_string(string)
388446

447+
def __lt__(self, other):
448+
if not isinstance(other, self.__class__):
449+
return NotImplemented
450+
return self.value < other.value
451+
452+
def __eq__(self, other):
453+
if not isinstance(other, self.__class__):
454+
return NotImplemented
455+
return self.value == other.value
456+
389457

390458
@total_ordering
391459
@attr.s(frozen=True, order=False, eq=False, hash=True)
@@ -433,13 +501,33 @@ class ComposerVersion(SemverVersion):
433501
def build_value(cls, string):
434502
return semantic_version.Version.coerce(string.lstrip("vV"))
435503

504+
def __lt__(self, other):
505+
if not isinstance(other, self.__class__):
506+
return NotImplemented
507+
return self.value < other.value
508+
509+
def __eq__(self, other):
510+
if not isinstance(other, self.__class__):
511+
return NotImplemented
512+
return self.value == other.value
513+
436514

437515
@attr.s(frozen=True, order=False, eq=False, hash=True)
438516
class GolangVersion(SemverVersion):
439517
@classmethod
440518
def build_value(cls, string):
441519
return semantic_version.Version.coerce(string.lstrip("vV"))
442520

521+
def __lt__(self, other):
522+
if not isinstance(other, self.__class__):
523+
return NotImplemented
524+
return self.value < other.value
525+
526+
def __eq__(self, other):
527+
if not isinstance(other, self.__class__):
528+
return NotImplemented
529+
return self.value == other.value
530+
443531

444532
@attr.s(frozen=True, order=False, eq=False, hash=True)
445533
class LegacyOpensslVersion(Version):

tests/test_pypi_version.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,25 @@
88

99
from packaging import version as packaging_version
1010

11-
from univers import versions
11+
from univers.versions import InvalidVersion
12+
from univers.versions import PypiVersion
1213

1314
# version comparison is already tested at:
1415
# https://github.com/pypa/packaging/blob/main/tests/test_version.py
1516

1617

1718
class TestPYPIVersion(TestCase):
1819
def test_constructor(self):
19-
pypi_version = versions.PypiVersion("2.4.5")
20+
pypi_version = PypiVersion("2.4.5")
2021
assert pypi_version.value == packaging_version.Version("2.4.5")
21-
self.assertRaises(versions.InvalidVersion, versions.PypiVersion, "2.//////")
22+
self.assertRaises(InvalidVersion, PypiVersion, "2.//////")
23+
24+
def test_compare(self):
25+
pypi_version = PypiVersion("2.4.5")
26+
assert pypi_version == PypiVersion("2.4.5")
27+
assert pypi_version != PypiVersion("2.4.6")
28+
assert pypi_version > PypiVersion("2.4.4")
29+
assert pypi_version >= PypiVersion("2.4.4")
30+
assert pypi_version < PypiVersion("2.4.6")
31+
assert pypi_version <= PypiVersion("2.4.6")
32+
assert PypiVersion("2.4") == PypiVersion("2.4.0")

0 commit comments

Comments
 (0)