From e72657775cd8746c12b4ae34be36bfa9c3f51255 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 | 11 +++++++++++ tests/test_versions.py | 11 +++++++++++ 4 files changed, 51 insertions(+) diff --git a/src/univers/version_range.py b/src/univers/version_range.py index 4c2a0baf..627a75ac 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -1196,6 +1196,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(): @@ -1440,6 +1445,7 @@ def build_range_from_snyk_advisory_string(scheme: str, string: Union[str, List]) "conan": ConanVersionRange, "all": AllVersionRange, "none": NoneVersionRange, + "lexicographic": LexicographicVersionRange, } PURL_TYPE_BY_GITLAB_SCHEME = { diff --git a/src/univers/versions.py b/src/univers/versions.py index c06f4ff0..f2dee071 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -143,6 +143,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 GenericVersion(Version): @@ -714,4 +736,5 @@ def bump(self, index): OpensslVersion, LegacyOpensslVersion, AlpineLinuxVersion, + LexicographicVersion, ] diff --git a/tests/test_version_range.py b/tests/test_version_range.py index 104646f8..43a6c233 100644 --- a/tests/test_version_range.py +++ b/tests/test_version_range.py @@ -23,6 +23,7 @@ from univers.version_range import build_range_from_snyk_advisory_string from univers.version_range import from_gitlab_native from univers.versions import InvalidVersion +from univers.versions import LexicographicVersion from univers.versions import NugetVersion from univers.versions import OpensslVersion from univers.versions import PypiVersion @@ -569,3 +570,13 @@ def test_version_range_none(): VersionRange.from_string("vers:none/!1.2.3") with pytest.raises(Exception): VersionRange.from_string("vers:none/*|>1.2.3") + + +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") + \ No newline at end of file diff --git a/tests/test_versions.py b/tests/test_versions.py index 57ded4c0..a995cae0 100644 --- a/tests/test_versions.py +++ b/tests/test_versions.py @@ -20,6 +20,7 @@ from univers.versions import RubygemsVersion from univers.versions import SemverVersion from univers.versions import Version +from univers.versions import LexicographicVersion def test_version(): @@ -218,3 +219,13 @@ def test_golang_version(): assert GolangVersion("v0.1.1") >= GolangVersion("v0.1.1") assert GolangVersion("v0.1.1") <= GolangVersion("v0.1.1") assert GolangVersion("v0.1.1") <= GolangVersion("v0.1.2") + + +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") \ No newline at end of file From e37ee6fdeec4ae362c10ce8ea2a17a3b349ca92b 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 +++++---- tests/test_version_range.py | 1 - tests/test_versions.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/univers/versions.py b/src/univers/versions.py index f2dee071..e5d0d794 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -143,7 +143,7 @@ class NoneVersion(Version): @classmethod def is_valid(cls, string): return string == "vers:none/*" - + class LexicographicVersion(Version): @classmethod @@ -153,18 +153,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 GenericVersion(Version): diff --git a/tests/test_version_range.py b/tests/test_version_range.py index 43a6c233..7c87186b 100644 --- a/tests/test_version_range.py +++ b/tests/test_version_range.py @@ -579,4 +579,3 @@ def test_version_range_lexicographic(): 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") - \ No newline at end of file diff --git a/tests/test_versions.py b/tests/test_versions.py index a995cae0..b00a3607 100644 --- a/tests/test_versions.py +++ b/tests/test_versions.py @@ -228,4 +228,4 @@ def test_lexicographic_version(): assert LexicographicVersion("abc") > LexicographicVersion(None) assert LexicographicVersion("Abc") < LexicographicVersion(None) assert LexicographicVersion("123") < LexicographicVersion("bbc") - assert LexicographicVersion("2.3.4") > LexicographicVersion("1.2.3") \ No newline at end of file + assert LexicographicVersion("2.3.4") > LexicographicVersion("1.2.3") From 13e36ad7221e0d9d6117454ba91836d45ae26675 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 b00a3607..ecbfdaf9 100644 --- a/tests/test_versions.py +++ b/tests/test_versions.py @@ -12,6 +12,7 @@ from univers.versions import EnhancedSemanticVersion from univers.versions import GentooVersion from univers.versions import GolangVersion +from univers.versions import LexicographicVersion from univers.versions import MavenVersion from univers.versions import NginxVersion from univers.versions import NugetVersion @@ -20,7 +21,6 @@ from univers.versions import RubygemsVersion from univers.versions import SemverVersion from univers.versions import Version -from univers.versions import LexicographicVersion def test_version():