Skip to content

Commit 5c0119d

Browse files
committed
intdot versioning scheme
Signed-off-by: Kunz, Immanuel <immanuel.kunz@aisec.fraunhofer.de>
1 parent a8920ff commit 5c0119d

5 files changed

Lines changed: 152 additions & 1 deletion

File tree

src/univers/intdot.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# Visit https://aboutcode.org and https://github.com/aboutcode-org/univers for support and download.
4+
5+
import re
6+
7+
8+
class IntdotVersion:
9+
"""
10+
intdot version.
11+
12+
The regex pattern for the intdot version is any number (>0) of integers separated by dots, followed by an arbitrary number of other characters, e.g., 1.2.3.5543, 123.234-prerelease, 1.2.3alpha
13+
"""
14+
15+
VERSION_PATTERN = r"^(\d+(\.\d+)*)(.*)$"
16+
17+
def __init__(self, version):
18+
if not self.is_valid(version):
19+
raise InvalidVersionError(version)
20+
21+
version = str(version).strip()
22+
self.original = version
23+
24+
def __eq__(self, other):
25+
return self.original == other.original
26+
27+
def __lt__(self, other):
28+
return self.__cmp__(other) < 0
29+
30+
def __le__(self, other):
31+
return self.__cmp__(other) <= 0
32+
33+
def __gt__(self, other):
34+
return self.__cmp__(other) > 0
35+
36+
def __ge__(self, other):
37+
return self.__cmp__(other) >= 0
38+
39+
@classmethod
40+
def is_valid(cls, string):
41+
return re.compile(IntdotVersion.VERSION_PATTERN).match(string)
42+
43+
def extract_numeric_labels(self, version):
44+
"""
45+
Check if the version matches the pattern; if it matches, extract the first group (identified by parentheses) which is the numeric part of the version
46+
"""
47+
match = re.match(IntdotVersion.VERSION_PATTERN, version)
48+
49+
if match:
50+
version_labels = match.group(1)
51+
return version_labels
52+
else:
53+
raise InvalidVersionError(version)
54+
55+
def __cmp__(self, other):
56+
"""
57+
Compare this version with ``other`` returning -1, 0, or 1 if the
58+
other version is larger, the same, or smaller than this
59+
one.
60+
"""
61+
if isinstance(other, str):
62+
other = IntdotVersion(other)
63+
64+
if not isinstance(other, IntdotVersion):
65+
raise InvalidVersionError
66+
67+
if self.original == other.original:
68+
return 0
69+
70+
lhlabels = self.extract_numeric_labels(self.original)
71+
rhlabels = self.extract_numeric_labels(other.original)
72+
73+
if lhlabels == rhlabels:
74+
return 0
75+
76+
lhsize = len(lhlabels)
77+
rhsize = len(rhlabels)
78+
79+
if lhsize > rhsize:
80+
limit = lhsize
81+
else:
82+
limit = rhsize
83+
84+
limit -= 1
85+
86+
i = 0
87+
88+
while i <= limit:
89+
try:
90+
lhs = lhlabels[i]
91+
except IndexError:
92+
lhs = 0
93+
94+
try:
95+
rhs = rhlabels[i]
96+
except IndexError:
97+
rhs = 0
98+
99+
i += 1
100+
101+
if lhs == rhs:
102+
continue
103+
104+
if int(lhs) > int(rhs):
105+
return 1
106+
if int(lhs) < int(rhs):
107+
return -1
108+
return 0
109+
110+
111+
class InvalidVersionError(ValueError):
112+
pass

src/univers/version_range.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,11 @@ class GolangVersionRange(VersionRange):
968968
}
969969

970970

971+
class IntdotVersionRange(VersionRange):
972+
scheme = "intdot"
973+
version_class = versions.IntdotVersion
974+
975+
971976
class GenericVersionRange(VersionRange):
972977
scheme = "generic"
973978
version_class = versions.SemverVersion
@@ -1440,7 +1445,7 @@ def build_range_from_snyk_advisory_string(scheme: str, string: Union[str, List])
14401445
"conan": ConanVersionRange,
14411446
"all": AllVersionRange,
14421447
"none": NoneVersionRange,
1443-
}
1448+
"intdot": IntdotVersionRange,
14441449

14451450
PURL_TYPE_BY_GITLAB_SCHEME = {
14461451
"gem": "gem",

src/univers/versions.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from univers import debian
1313
from univers import gem
1414
from univers import gentoo
15+
from univers import intdot
1516
from univers import maven
1617
from univers import nuget
1718
from univers import rpm
@@ -145,6 +146,16 @@ def is_valid(cls, string):
145146
return string == "vers:none/*"
146147

147148

149+
class IntdotVersion(Version):
150+
@classmethod
151+
def build_value(cls, string):
152+
return intdot.IntdotVersion(string)
153+
154+
@classmethod
155+
def is_valid(cls, string):
156+
return intdot.IntdotVersion.is_valid(string)
157+
158+
148159
class GenericVersion(Version):
149160
@classmethod
150161
def is_valid(cls, string):
@@ -714,4 +725,5 @@ def bump(self, index):
714725
OpensslVersion,
715726
LegacyOpensslVersion,
716727
AlpineLinuxVersion,
728+
IntdotVersion,
717729
]

tests/test_version_range.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,13 @@ def test_version_range_none():
355355
VersionRange.from_string("vers:none/!1.2.3")
356356
with pytest.raises(Exception):
357357
VersionRange.from_string("vers:none/*|>1.2.3")
358+
359+
360+
def test_version_range_intdot():
361+
intdot_range = IntdotVersionRange.from_string("vers:intdot/>1.2.3.4")
362+
assert IntdotVersion("1.3.3") in intdot_range
363+
assert IntdotVersion("0.3.3") not in intdot_range
364+
assert IntdotVersion("1.3.3alpha") in intdot_range
365+
assert IntdotVersion("1.2.2.pre") not in intdot_range
366+
assert IntdotVersion("1010.23.234203.0") in IntdotVersionRange.from_string("vers:intdot/*")
367+

tests/test_versions.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from univers.versions import EnhancedSemanticVersion
1313
from univers.versions import GentooVersion
1414
from univers.versions import GolangVersion
15+
from univers.versions import IntdotVersion
1516
from univers.versions import MavenVersion
1617
from univers.versions import NginxVersion
1718
from univers.versions import NugetVersion
@@ -218,3 +219,14 @@ def test_golang_version():
218219
assert GolangVersion("v0.1.1") >= GolangVersion("v0.1.1")
219220
assert GolangVersion("v0.1.1") <= GolangVersion("v0.1.1")
220221
assert GolangVersion("v0.1.1") <= GolangVersion("v0.1.2")
222+
223+
224+
def test_intdot_version():
225+
assert IntdotVersion("1.2.3.4.5") == IntdotVersion("1.2.3.4.5")
226+
assert IntdotVersion("1.2.3.4.6") > IntdotVersion("1.2.3.4.5")
227+
assert IntdotVersion("1.2.3.4.6") < IntdotVersion("2.2.3.4.5")
228+
assert IntdotVersion("1.2.3.4.6") <= IntdotVersion("2.2.3.4.5")
229+
assert IntdotVersion("1.2.3.4.6-pre") <= IntdotVersion("2.2.3.4.5")
230+
assert IntdotVersion("1.2.3.4.6-pre") <= IntdotVersion("2.2.3.4.5.pre")
231+
assert IntdotVersion("1.2.3.4.6-pre") <= IntdotVersion("2.2.3.4.5-10")
232+
assert IntdotVersion("1.2.3.4.6-pre") <= IntdotVersion("2.2.3.4.5-10")

0 commit comments

Comments
 (0)