Skip to content

Commit

Permalink
Merge pull request #75 from keshav-space/refactor_gem
Browse files Browse the repository at this point in the history
Refactor gem and make nuget hashable
  • Loading branch information
TG1999 committed Apr 11, 2023
2 parents 5dc7d88 + 19de006 commit 205da7e
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 76 deletions.
123 changes: 48 additions & 75 deletions src/univers/gem.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,19 +199,14 @@ def __init__(self, version):
if not self.is_correct(version):
raise InvalidVersionError(version)

# If version is an empty string convert it to 0
version = str(version).strip()

self.original = version

# If version is an empty string convert it to 0
if not version:
version = "0"

self.version = version.replace("-", ".pre.")
self._segments = ()
self._canonical_segments = ()
self._bump = None
self._release = None

def __str__(self):
return self.original
Expand All @@ -225,7 +220,7 @@ def equal_strictly(self, other):
return self.version == other.version

def __hash__(self):
return hash(tuple(self.canonical_segments))
return hash(self.canonical_segments)

def __eq__(self, other):
return self.canonical_segments == other.canonical_segments
Expand All @@ -242,6 +237,32 @@ def __gt__(self, other):
def __ge__(self, other):
return self.__cmp__(other) >= 0

@property
def segments(self):
"""
Returns segments for this version where segments are
ints or strings parsed from the original version string.
"""
segments = []
find_segments = re.compile(r"[0-9]+|[a-z]+", re.IGNORECASE).findall
for seg in find_segments(self.version):
sub_segments = [int(seg) if seg.isdigit() else seg]
segments.extend(sub_segments)
return tuple(segments)

@property
def canonical_segments(self):
"""
Returns "canonical segments" for this version using
the Rubygems way for canonicalization.
"""
canonical_segments = []
for segments in self.split_segments():
# drop the section preceding the least significant zero (if exists)
segs = list(dropwhile(lambda s: s == 0, reversed(segments)))
canonical_segments.extend(reversed(segs))
return tuple(canonical_segments)

def bump(self):
"""
Return a new version object where the next to the last revision number
Expand All @@ -252,40 +273,33 @@ def bump(self):
>>> assert GemVersion("5.3.1").bump() == GemVersion("5.4"), repr(GemVersion("5.3.1").bump())
>>> assert GemVersion("5.3.1.4-2").bump() == GemVersion("5.3.2"), GemVersion("5.3.1.4-2").bump()
"""
if not self._bump:
segments = []
for seg in self.segments:
if isinstance(seg, str):
break
else:
segments.append(seg)

if len(segments) > 1:
segments.pop()
segments = []
for seg in self.segments:
if isinstance(seg, str):
break
else:
segments.append(seg)

segments[-1] += 1
segments = [str(r) for r in segments]
self._bump = GemVersion(".".join(segments))
if len(segments) > 1:
segments.pop()

return self._bump
segments[-1] += 1
segments = [str(r) for r in segments]
return GemVersion(".".join(segments))

def release(self):
"""
Return a new GemVersion which is the release for this version (e.g.,
1.2.0.a -> 1.2.0). Non-prerelease versions return themselves. A release
is composed only of numeric segments.
"""
if not self._release:
if self.prerelease():
segments = self.segments
while any(isinstance(s, str) for s in segments):
segments.pop()
segments = (str(s) for s in segments)
self._release = GemVersion(".".join(segments))
else:
self._release = self

return self._release
if self.prerelease():
segments = list(self.segments)
while any(isinstance(s, str) for s in segments):
segments.pop()
segments = (str(s) for s in segments)
return GemVersion(".".join(segments))
return self

def prerelease(self):
"""
Expand All @@ -294,47 +308,6 @@ def prerelease(self):
"""
return any(not str(s).isdigit() for s in self.segments)

@property
def segments(self):
"""
Return a new sequence of segments for this version where segments are
ints or strings parsed from the original version string.
"""
if not self._segments:
self._segments = self.get_segments()
return list(self._segments)

def get_segments(self):
"""
Return a sequence of segments for this version where segments are ints
or strings parsed from the original version string.
"""
find_segments = re.compile(r"[0-9]+|[a-z]+", re.IGNORECASE).findall
segments = []
for seg in find_segments(self.version):
if seg.isdigit():
seg = int(seg)
segments.append(seg)
return tuple(segments)

@property
def canonical_segments(self):
if not self._canonical_segments:
self._canonical_segments = self.get_canonical_segments()
return tuple(self._canonical_segments)

def get_canonical_segments(self):
"""
Return a new sequence of "canonical segments" for this version using
the Rubygems way.
"""
canonical_segments = []
for segments in self.split_segments():
segs = list(dropwhile(lambda s: s == 0, reversed(segments)))
segs = reversed(segs)
canonical_segments.extend(segs)
return tuple(canonical_segments)

def split_segments(self):
"""
Return a two-tuple of segments:
Expand Down Expand Up @@ -380,11 +353,11 @@ def __cmp__(self, other, trace=False):
if self.version == other.version:
return 0

lhsegments = self.canonical_segments
lhsegments = list(self.canonical_segments)
if trace:
print(f" lhsegments: canonical_segments: {lhsegments!r}")

rhsegments = other.canonical_segments
rhsegments = list(other.canonical_segments)
if trace:
print(f" rhsegments: canonical_segments: {rhsegments!r}")

Expand Down
8 changes: 8 additions & 0 deletions src/univers/nuget.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ def __lt__(self, other):
# Revision is the same, so ignore it for comparison purposes.
return self._base_semver < other._base_semver

def __hash__(self):
return hash(
(
self._base_semver.to_tuple(),
self._revision,
)
)

@classmethod
def from_string(cls, str_version):
if not str_version:
Expand Down
11 changes: 11 additions & 0 deletions tests/test_nuget.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import unittest

from univers.nuget import Version
from univers.versions import NugetVersion


Expand Down Expand Up @@ -77,3 +78,13 @@ def test_less(self):
self.check_order(self.assertLess, "1.0.0-pre", "1.0.0.1-alpha")
self.check_order(self.assertLess, "1.0.0", "1.0.0.1-alpha")
self.check_order(self.assertLess, "0.9.9.1", "1.0.0")

def test_NugetVersion_hash(self):
vers1 = NugetVersion("1.0.1+23")
vers2 = NugetVersion("1.0.1+23")
assert hash(vers1) == hash(vers2)

def test_nuget_semver_hash(self):
vers1 = Version.from_string("51.0.0+2")
vers2 = Version.from_string("51.0.0+2")
assert hash(vers1) == hash(vers2)
17 changes: 17 additions & 0 deletions tests/test_python_semver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#
# Copyright (c) nexB Inc. and others.
# SPDX-License-Identifier: Apache-2.0
#
# Visit https://aboutcode.org and https://github.com/nexB/univers for support and download.

from unittest import TestCase

import semver


class TestPythonSemver(TestCase):
def test_semver_hash(self):
# python-semver doesn't consider build while hashing
vers1 = semver.VersionInfo.parse("1.2.3")
vers2 = semver.VersionInfo.parse("1.2.3+1")
assert hash(vers1) == hash(vers2)
2 changes: 1 addition & 1 deletion tests/test_rubygems_gem_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def test_segments():
secondseg += 1

refute_version_eql("9.8.8", "9.8.7")
assert GemVersion("9.8.7").segments == [9, 8, 7]
assert GemVersion("9.8.7").segments == (9, 8, 7)


def test_split_segments():
Expand Down

0 comments on commit 205da7e

Please sign in to comment.