Skip to content

Commit a544a55

Browse files
committed
fix: Address code review issues
Signed-off-by: Terri Oda <[email protected]>
1 parent 52804a5 commit a544a55

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

cve_bin_tool/version_compare.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,33 @@ class CannotParseVersionException(Exception):
2020
"""
2121

2222

23+
class UnknownVersion(Exception):
24+
"""
25+
Thrown if version is null or "unknown".
26+
"""
27+
28+
2329
def parse_version(version_string: str):
2430
"""
2531
Splits a version string into an array for comparison.
2632
This includes dealing with some letters.
2733
2834
e.g. 1.1.1a would become [1, 1, 1, a]
2935
"""
30-
versionString = version_string
36+
37+
if not version_string or version_string.lower() == "unknown":
38+
raise UnknownVersion(f"version string = {version_string}")
39+
40+
versionString = version_string.strip()
3141
versionArray = []
3242

3343
# convert - and _ to be treated like . below
3444
# we could switch to a re split but it seems to leave blanks so this is less hassle
3545
versionString = versionString.replace("-", ".")
3646
versionString = versionString.replace("_", ".")
47+
# Note: there may be other non-alphanumeric characters we want to add here in the
48+
# future, but we'd like to look at those cases before adding them in case the version
49+
# logic is very different.
3750

3851
# Attempt a split
3952
split_version = versionString.split(".")
@@ -52,6 +65,7 @@ def parse_version(version_string: str):
5265
versionArray.append(section)
5366

5467
# if it looks like 42a split out the letters and numbers
68+
# We will treat 42a as coming *after* version 42.
5569
elif re.match(number_letter, section):
5670
result = re.findall(number_letter, section)
5771

@@ -65,6 +79,7 @@ def parse_version(version_string: str):
6579

6680
# if it looks like rc1 or dev7 we'll leave it together as it may be some kind of pre-release
6781
# and we'll probably want to handle it specially in the compare.
82+
# We need to threat 42dev7 as coming *before* version 42.
6883
elif re.match(letter_number, section):
6984
versionArray.append(section)
7085

@@ -101,10 +116,12 @@ def version_compare(v1: str, v2: str):
101116
# This might be a bad choice in some cases: Do we want ag < z?
102117
# I suspect projects using letters in version names may not use ranges in nvd
103118
# for this reason (e.g. openssl)
119+
# Converting to lower() so that 3.14a == 3.14A
120+
# but this may not be ideal in all cases
104121
elif v1_array[i].isalpha() and v2_array[i].isalpha():
105-
if v1_array[i] > v2_array[i]:
122+
if v1_array[i].lower() > v2_array[i].lower():
106123
return 1
107-
if v1_array[i] < v2_array[i]:
124+
if v1_array[i].lower() < v2_array[i].lower():
108125
return -1
109126

110127
else:
@@ -170,25 +187,33 @@ class Version(str):
170187
"""
171188

172189
def __cmp__(self, other):
190+
"""compare"""
173191
return version_compare(self, other)
174192

175193
def __lt__(self, other):
194+
"""<"""
176195
return bool(version_compare(self, other) < 0)
177196

178197
def __le__(self, other):
198+
"""<="""
179199
return bool(version_compare(self, other) <= 0)
180200

181201
def __gt__(self, other):
202+
""">"""
182203
return bool(version_compare(self, other) > 0)
183204

184205
def __ge__(self, other):
206+
""">="""
185207
return bool(version_compare(self, other) >= 0)
186208

187209
def __eq__(self, other):
210+
"""=="""
188211
return bool(version_compare(self, other) == 0)
189212

190213
def __ne__(self, other):
214+
"""!="""
191215
return bool(version_compare(self, other) != 0)
192216

193217
def __repr__(self):
218+
"""print the version string"""
194219
return f"Version: {self}"

test/test_version_compare.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
# Copyright (C) 2023 Intel Corporation
22
# SPDX-License-Identifier: GPL-3.0-or-later
33

4+
import pytest
45

5-
from cve_bin_tool.version_compare import Version
6+
from cve_bin_tool.version_compare import UnknownVersion, Version
67

78

89
class TestVersionCompare:
10+
"""Test the cve_bin_tool.version_compare functionality"""
11+
912
def test_eq(self):
1013
"""Make sure == works between versions"""
1114
assert Version("1.2") == Version("1.2")
15+
assert Version("1.1a") == Version("1.1A")
16+
assert Version("4.4.A") == Version("4.4.a")
17+
assert Version("5.6 ") == Version("5.6")
1218

1319
def test_lt(self):
1420
"""Make sure < works between versions, including some with unusual version schemes"""
@@ -23,6 +29,7 @@ def test_lt(self):
2329
assert Version("1.2.post8") < Version("1.2.1")
2430
assert Version("rc5") < Version("rc10")
2531
assert Version("9.10") < Version("9.10.post")
32+
assert Version("5.3.9") < Version("5.4")
2633

2734
def test_gt(self):
2835
"""Make sure > works between versions, including some with unusual version schemes"""
@@ -34,3 +41,10 @@ def test_gt(self):
3441
assert Version("10.2.3.rc1") > Version("10.2.3.rc0")
3542
assert Version("10.2.3.rc10") > Version("10.2.3.rc2")
3643
assert Version("9.10.post") > Version("9.10")
44+
assert Version("5.5") > Version("5.4.1")
45+
46+
def test_error(self):
47+
"""Make sure 'unknown' and blank strings raise appropriate errors"""
48+
with pytest.raises(UnknownVersion):
49+
Version("6") > Version("unknown")
50+
Version("") > Version("6")

0 commit comments

Comments
 (0)