diff --git a/src/univers/version_constraint.py b/src/univers/version_constraint.py index 36ec6d81..2b782037 100644 --- a/src/univers/version_constraint.py +++ b/src/univers/version_constraint.py @@ -202,6 +202,11 @@ def split(string): >>> assert VersionConstraint.split("<2.3") == ("<", "2.3",) >>> assert VersionConstraint.split(">2.3") == (">", "2.3",) >>> assert VersionConstraint.split("!=2.3") == ("!=", "2.3",) + >>> try: + ... VersionConstraint.split("<<2.3") + ... raise Exception("ValueError should be raised") + ... except ValueError: + ... pass """ constraint_string = remove_spaces(string) @@ -212,9 +217,15 @@ def split(string): for comparator in COMPARATORS: if constraint_string.startswith(comparator): # NOTE: we do not report an error if this is not valid - version = constraint_string.lstrip(comparator) + version = constraint_string[len(comparator) :] if comparator == "*": version = "" + + # Reject malformed repeated comparator prefixes such as + # "<<2.3" and ">>2.3" in VERS constraints which are explicitly not supported in VERS. + elif version and version[0] in "<>!=*": + raise ValueError(f"Unknown comparator in constraint: {constraint_string!r}") + return comparator, version # default to equality diff --git a/tests/test_version_constraint.py b/tests/test_version_constraint.py index b58828ec..34c1450e 100644 --- a/tests/test_version_constraint.py +++ b/tests/test_version_constraint.py @@ -87,3 +87,11 @@ def test_invert_opertaion(original, inverted): assert constraint.invert() == inverted_constraint else: assert constraint.invert() is None + +@pytest.mark.parametrize("spec", ["<<2.3", ">>2.3"]) +def test_invalid_vers_comparator_prefixes(spec): + with pytest.raises(ValueError, match="Unknown comparator"): + VersionConstraint.from_string( + string=spec, + version_class=versions.SemverVersion, + ) \ No newline at end of file