Skip to content

Commit d7f0424

Browse files
committed
Do not allow creation of VersionRange with empty constraints
A VersionRange constructed directly with an empty constraints sequence serialized to an invalid vers string such as 'vers:apache/' with no constraint. from_string() already rejects such strings, so only direct construction could produce these invalid ranges. Raise ValueError from __attrs_post_init__ when constraints is empty. The four Conan from_native test cases that expected an empty native range to produce 'vers:conan/' now expect a ValueError instead, and the schema-driven test harness gains an optional expected_error field to express that. Fixes #203 Signed-off-by: Manoj Gowda <manojgowdabs18@gmail.com>
1 parent 92b1a24 commit d7f0424

5 files changed

Lines changed: 37 additions & 5 deletions

File tree

src/univers/version_range.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ class VersionRange:
6767
constraints = attr.ib(type=tuple, default=attr.Factory(tuple))
6868

6969
def __attrs_post_init__(self, *args, **kwargs):
70+
if not self.constraints:
71+
raise ValueError(
72+
f"{self.__class__.__name__} requires at least one VersionConstraint."
73+
)
7074
constraints = tuple(sorted(self.constraints))
7175
# Notes: setattr is used because this is an immutable frozen instance.
7276
# See https://www.attrs.org/en/stable/init.html?#post-init

tests/__init__.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Visit https://aboutcode.org and https://github.com/aboutcode-org/univers for support and download.
66

77
from typing import NamedTuple
8+
from typing import Optional
89
from typing import Union
910

1011

@@ -14,13 +15,26 @@ class SchemaDrivenVersTest(NamedTuple):
1415
input: dict
1516
expected_output: Union[list, bool]
1617
description: str = ""
18+
# name of the exception class expected to be raised while computing the
19+
# result, for test cases whose input is invalid
20+
expected_error: Optional[str] = None
1721

1822
@classmethod
1923
def from_data(cls, data: dict):
2024
return cls(**data)
2125

2226
def assert_result(self):
23-
assert self.result == self.expected_output
27+
if self.expected_error:
28+
try:
29+
self.result
30+
except Exception as e:
31+
assert type(e).__name__ == self.expected_error
32+
else:
33+
raise AssertionError(
34+
f"{self.expected_error} not raised for input: {self.input!r}"
35+
)
36+
else:
37+
assert self.result == self.expected_output
2438

2539
@property
2640
def result(self):

tests/data/schema/range/conan_range_from_native.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,8 @@
11371137
"native_range": "",
11381138
"scheme": "conan"
11391139
},
1140-
"expected_output": "vers:conan/"
1140+
"expected_output": null,
1141+
"expected_error": "ValueError"
11411142
},
11421143
{
11431144
"description": "Construct VERS range from native conan range.",
@@ -1437,7 +1438,8 @@
14371438
"native_range": "",
14381439
"scheme": "conan"
14391440
},
1440-
"expected_output": "vers:conan/"
1441+
"expected_output": null,
1442+
"expected_error": "ValueError"
14411443
},
14421444
{
14431445
"description": "Construct VERS range from native conan range.",

tests/data/schema/range/gitlab/conan_gitlab_range_from_native.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,8 @@
11371137
"native_range": "",
11381138
"scheme": "conan"
11391139
},
1140-
"expected_output": "vers:conan/"
1140+
"expected_output": null,
1141+
"expected_error": "ValueError"
11411142
},
11421143
{
11431144
"description": "Construct VERS range from GitLab native conan range.",
@@ -1437,7 +1438,8 @@
14371438
"native_range": "",
14381439
"scheme": "conan"
14391440
},
1440-
"expected_output": "vers:conan/"
1441+
"expected_output": null,
1442+
"expected_error": "ValueError"
14411443
},
14421444
{
14431445
"description": "Construct VERS range from GitLab native conan range.",

tests/test_version_range.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,3 +458,13 @@ def test_version_range_lexicographic():
458458
assert LexicographicVersion(-123) in VersionRange.from_string("vers:lexicographic/<~")
459459
assert LexicographicVersion(None) in VersionRange.from_string("vers:lexicographic/*")
460460
assert LexicographicVersion("ABC") in VersionRange.from_string("vers:lexicographic/>abc|<=None")
461+
462+
463+
def test_version_range_with_empty_constraints_is_invalid():
464+
# https://github.com/aboutcode-org/univers/issues/203
465+
with pytest.raises(ValueError):
466+
VersionRange(constraints=[])
467+
with pytest.raises(ValueError):
468+
RANGE_CLASS_BY_SCHEMES["apache"](constraints=[])
469+
with pytest.raises(ValueError):
470+
VersionRange.from_string("vers:apache/")

0 commit comments

Comments
 (0)