From 2cf2ca6f54dac893f3005ed846e601ae52e939ff Mon Sep 17 00:00:00 2001 From: "Kunz, Immanuel" Date: Wed, 16 Jul 2025 17:46:44 +0200 Subject: [PATCH 1/3] add lexicographic versioning scheme Signed-off-by: Kunz, Immanuel --- src/univers/version_range.py | 6 ++++++ src/univers/versions.py | 23 +++++++++++++++++++++++ tests/test_version_range.py | 10 ++++++++++ tests/test_versions.py | 11 +++++++++++ 4 files changed, 50 insertions(+) diff --git a/src/univers/version_range.py b/src/univers/version_range.py index 76539006..ecb68041 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -1201,6 +1201,11 @@ class NoneVersionRange(VersionRange): version_class = versions.NoneVersion +class LexicographicVersionRange(VersionRange): + scheme = "lexicographic" + version_class = versions.LexicographicVersion + + def from_gitlab_native(gitlab_scheme, string): purl_scheme = gitlab_scheme if gitlab_scheme not in PURL_TYPE_BY_GITLAB_SCHEME.values(): @@ -1446,6 +1451,7 @@ def build_range_from_snyk_advisory_string(scheme: str, string: Union[str, List]) "all": AllVersionRange, "none": NoneVersionRange, "intdot": IntdotVersionRange, + "lexicographic": LexicographicVersionRange, } PURL_TYPE_BY_GITLAB_SCHEME = { diff --git a/src/univers/versions.py b/src/univers/versions.py index cf8c0bc7..e6ea1a23 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -144,6 +144,28 @@ class NoneVersion(Version): @classmethod def is_valid(cls, string): return string == "vers:none/*" + + +class LexicographicVersion(Version): + @classmethod + def build_value(cls, string): + return str(string) + + """ + Create a string, even if, e.g., an integer is given + """ + @classmethod + def normalize(cls, string): + return remove_spaces(str(string)) + + def __lt__(self, other): + return self.value.encode('utf-8') < other.value.encode('utf-8') + + def __gt__(self, other): + return self.value.encode('utf-8') > other.value.encode('utf-8') + + def __eq__(self, other): + return self.value.encode('utf-8') == other.value.encode('utf-8') class IntdotVersion(Version): @@ -726,4 +748,5 @@ def bump(self, index): LegacyOpensslVersion, AlpineLinuxVersion, IntdotVersion, + LexicographicVersion, ] diff --git a/tests/test_version_range.py b/tests/test_version_range.py index 16cac2dc..e05a41e2 100644 --- a/tests/test_version_range.py +++ b/tests/test_version_range.py @@ -22,6 +22,7 @@ from univers.version_range import build_range_from_snyk_advisory_string from univers.version_range import from_gitlab_native from univers.versions import IntdotVersion +from univers.versions import LexicographicVersion from univers.versions import OpensslVersion from univers.versions import PypiVersion from univers.versions import SemverVersion @@ -366,3 +367,12 @@ def test_version_range_intdot(): assert IntdotVersion("1.3.3alpha") in intdot_range assert IntdotVersion("1.2.2.pre") not in intdot_range assert IntdotVersion("1010.23.234203.0") in IntdotVersionRange.from_string("vers:intdot/*") + + +def test_version_range_lexicographic(): + assert LexicographicVersion("1.2.3") in VersionRange.from_string( + "vers:lexicographic/<1.2.4|>0.9" + ) + assert LexicographicVersion(-123) in VersionRange.from_string("vers:lexicographic/<~") + assert LexicographicVersion(None) in VersionRange.from_string("vers:lexicographic/*") + assert LexicographicVersion("ABC") in VersionRange.from_string("vers:lexicographic/>abc|<=None") diff --git a/tests/test_versions.py b/tests/test_versions.py index 7ceb80cb..eb9de290 100644 --- a/tests/test_versions.py +++ b/tests/test_versions.py @@ -21,6 +21,7 @@ from univers.versions import RubygemsVersion from univers.versions import SemverVersion from univers.versions import Version +from univers.versions import LexicographicVersion def test_version(): @@ -230,3 +231,13 @@ def test_intdot_version(): assert IntdotVersion("1.2.3.4.6-pre") <= IntdotVersion("2.2.3.4.5.pre") assert IntdotVersion("1.2.3.4.6-pre") <= IntdotVersion("2.2.3.4.5-10") assert IntdotVersion("1.2.3.4.6-pre") <= IntdotVersion("2.2.3.4.5-10") + + +def test_lexicographic_version(): + assert LexicographicVersion("abc") == LexicographicVersion("abc") + assert LexicographicVersion(" abc") == LexicographicVersion("abc") + assert LexicographicVersion("123") == LexicographicVersion(123) + assert LexicographicVersion("abc") > LexicographicVersion(None) + assert LexicographicVersion("Abc") < LexicographicVersion(None) + assert LexicographicVersion("123") < LexicographicVersion("bbc") + assert LexicographicVersion("2.3.4") > LexicographicVersion("1.2.3") From 00a0de093fc7258cccc6406178f8880fc75f33d8 Mon Sep 17 00:00:00 2001 From: "Kunz, Immanuel" Date: Mon, 21 Jul 2025 12:59:55 +0200 Subject: [PATCH 2/3] code style Signed-off-by: Kunz, Immanuel --- src/univers/versions.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/univers/versions.py b/src/univers/versions.py index e6ea1a23..69df9d40 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -144,7 +144,7 @@ class NoneVersion(Version): @classmethod def is_valid(cls, string): return string == "vers:none/*" - + class LexicographicVersion(Version): @classmethod @@ -154,18 +154,19 @@ def build_value(cls, string): """ Create a string, even if, e.g., an integer is given """ + @classmethod def normalize(cls, string): return remove_spaces(str(string)) def __lt__(self, other): - return self.value.encode('utf-8') < other.value.encode('utf-8') + return self.value.encode("utf-8") < other.value.encode("utf-8") def __gt__(self, other): - return self.value.encode('utf-8') > other.value.encode('utf-8') + return self.value.encode("utf-8") > other.value.encode("utf-8") def __eq__(self, other): - return self.value.encode('utf-8') == other.value.encode('utf-8') + return self.value.encode("utf-8") == other.value.encode("utf-8") class IntdotVersion(Version): From 9064438660308316fd493af82c6ffddb8615ec6e Mon Sep 17 00:00:00 2001 From: "Kunz, Immanuel" Date: Mon, 21 Jul 2025 13:10:48 +0200 Subject: [PATCH 3/3] fix import order Signed-off-by: Kunz, Immanuel --- tests/test_versions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_versions.py b/tests/test_versions.py index eb9de290..7f7f81b8 100644 --- a/tests/test_versions.py +++ b/tests/test_versions.py @@ -13,6 +13,7 @@ from univers.versions import GentooVersion from univers.versions import GolangVersion from univers.versions import IntdotVersion +from univers.versions import LexicographicVersion from univers.versions import MavenVersion from univers.versions import NginxVersion from univers.versions import NugetVersion @@ -21,7 +22,6 @@ from univers.versions import RubygemsVersion from univers.versions import SemverVersion from univers.versions import Version -from univers.versions import LexicographicVersion def test_version():