From 6887d929d8b1d4fb6f0c4ab2075257c7a756ed83 Mon Sep 17 00:00:00 2001 From: Thiago Perrotta Date: Mon, 22 Apr 2024 15:51:09 +0200 Subject: [PATCH 1/4] add semantic versioning (semver.org) validator https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string --- README.md | 6 ++ yamale/validators/tests/test_validate.py | 81 ++++++++++++++++++++++++ yamale/validators/validators.py | 13 ++++ 3 files changed, 100 insertions(+) diff --git a/README.md b/README.md index afa957b..8620074 100644 --- a/README.md +++ b/README.md @@ -400,6 +400,12 @@ Validates MAC addresses. Examples: - `mac()`: Allows any valid MAC address +### SemVer (Semantic Versioning) - `SemVer()` +Validates [Semantic Versioning](https://semver.org/) strings. + +Examples: +- `SemVer()`: Allows any valid SemVer string + ### Any - `any([validators])` Validates against a union of types. Use when a node **must** contain **one and only one** of several types. It is valid if at least one of the listed validators is valid. If no validators are given, accept any value. diff --git a/yamale/validators/tests/test_validate.py b/yamale/validators/tests/test_validate.py index a3370fe..680b1c8 100644 --- a/yamale/validators/tests/test_validate.py +++ b/yamale/validators/tests/test_validate.py @@ -144,3 +144,84 @@ def test_mac(): assert not v.is_valid("ab:cd:ef:12:34:56:78") assert not v.is_valid("abcdefghijkl") assert not v.is_valid("1234567890ax") + + +def test_semver(): + """ + - https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + - https://regex101.com/r/Ly7O1x/3/ + """ + v = val.Semver() + + assert v.is_valid("0.0.4") + assert v.is_valid("1.2.3") + assert v.is_valid("10.20.30") + assert v.is_valid("1.1.2-prerelease+meta") + assert v.is_valid("1.1.2+meta") + assert v.is_valid("1.1.2+meta-valid") + assert v.is_valid("1.0.0-alpha") + assert v.is_valid("1.0.0-beta") + assert v.is_valid("1.0.0-alpha.beta") + assert v.is_valid("1.0.0-alpha.beta.1") + assert v.is_valid("1.0.0-alpha.1") + assert v.is_valid("1.0.0-alpha0.valid") + assert v.is_valid("1.0.0-alpha.0valid") + assert v.is_valid("1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay") + assert v.is_valid("1.0.0-rc.1+build.1") + assert v.is_valid("2.0.0-rc.1+build.123") + assert v.is_valid("1.2.3-beta") + assert v.is_valid("10.2.3-DEV-SNAPSHOT") + assert v.is_valid("1.2.3-SNAPSHOT-123") + assert v.is_valid("1.0.0") + assert v.is_valid("2.0.0") + assert v.is_valid("1.1.7") + assert v.is_valid("2.0.0+build.1848") + assert v.is_valid("2.0.1-alpha.1227") + assert v.is_valid("1.0.0-alpha+beta") + assert v.is_valid("1.2.3----RC-SNAPSHOT.12.9.1--.12+788") + assert v.is_valid("1.2.3----R-S.12.9.1--.12+meta") + assert v.is_valid("1.2.3----RC-SNAPSHOT.12.9.1--.12") + assert v.is_valid("1.0.0+0.build.1-rc.10000aaa-kk-0.1") + assert v.is_valid("99999999999999999999999.999999999999999999.99999999999999999") + assert v.is_valid("1.0.0-0A.is.legal") + + assert not v.is_valid("1") + assert not v.is_valid("1.2") + assert not v.is_valid("1.2.3-0123") + assert not v.is_valid("1.2.3-0123.0123") + assert not v.is_valid("1.1.2+.123") + assert not v.is_valid("+invalid") + assert not v.is_valid("-invalid") + assert not v.is_valid("-invalid+invalid") + assert not v.is_valid("-invalid.01") + assert not v.is_valid("alpha") + assert not v.is_valid("alpha.beta") + assert not v.is_valid("alpha.beta.1") + assert not v.is_valid("alpha.1") + assert not v.is_valid("alpha+beta") + assert not v.is_valid("alpha_beta") + assert not v.is_valid("alpha.") + assert not v.is_valid("alpha..") + assert not v.is_valid("beta") + assert not v.is_valid("1.0.0-alpha_beta") + assert not v.is_valid("-alpha.") + assert not v.is_valid("1.0.0-alpha..") + assert not v.is_valid("1.0.0-alpha..1") + assert not v.is_valid("1.0.0-alpha...1") + assert not v.is_valid("1.0.0-alpha....1") + assert not v.is_valid("1.0.0-alpha.....1") + assert not v.is_valid("1.0.0-alpha......1") + assert not v.is_valid("1.0.0-alpha.......1") + assert not v.is_valid("01.1.1") + assert not v.is_valid("1.01.1") + assert not v.is_valid("1.1.01") + assert not v.is_valid("1.2") + assert not v.is_valid("1.2.3.DEV") + assert not v.is_valid("1.2-SNAPSHOT") + assert not v.is_valid("1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788") + assert not v.is_valid("1.2-RC-SNAPSHOT") + assert not v.is_valid("-1.0.3-gamma+b7718") + assert not v.is_valid("+justmeta") + assert not v.is_valid("9.8.7+meta+meta") + assert not v.is_valid("9.8.7-whatever+meta+meta") + assert not v.is_valid("99999999999999999999999.999999999999999999.99999999999999999") diff --git a/yamale/validators/validators.py b/yamale/validators/validators.py index d72478e..026e540 100644 --- a/yamale/validators/validators.py +++ b/yamale/validators/validators.py @@ -248,6 +248,19 @@ def __init__(self, *args, **kwargs): ] +class SemVer(Regex): + """Semantic Versioning (semver.org) validator""" + + tag = "semver" + + def __init__(self, *args, **kwargs): + super(SemVer, self).__init__(*args, **kwargs) + self.regexes = [ + # https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + re.compile("^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"), + ] + + DefaultValidators = {} for v in util.get_subclasses(Validator): From 89619afe60d99462670f2c3c536e95cd727c80cf Mon Sep 17 00:00:00 2001 From: Thiago Perrotta Date: Thu, 25 Apr 2024 15:54:56 +0200 Subject: [PATCH 2/4] fix typo --- yamale/validators/tests/test_validate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yamale/validators/tests/test_validate.py b/yamale/validators/tests/test_validate.py index 680b1c8..67f0fe6 100644 --- a/yamale/validators/tests/test_validate.py +++ b/yamale/validators/tests/test_validate.py @@ -151,7 +151,7 @@ def test_semver(): - https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string - https://regex101.com/r/Ly7O1x/3/ """ - v = val.Semver() + v = val.SemVer() assert v.is_valid("0.0.4") assert v.is_valid("1.2.3") From b00ca2b985f6a39c86547d384befe92aef4db621 Mon Sep 17 00:00:00 2001 From: Thiago Perrotta Date: Thu, 25 Apr 2024 15:55:18 +0200 Subject: [PATCH 3/4] README: lowercase semver() --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8620074..5a1cf7e 100644 --- a/README.md +++ b/README.md @@ -400,11 +400,11 @@ Validates MAC addresses. Examples: - `mac()`: Allows any valid MAC address -### SemVer (Semantic Versioning) - `SemVer()` +### SemVer (Semantic Versioning) - `semver()` Validates [Semantic Versioning](https://semver.org/) strings. Examples: -- `SemVer()`: Allows any valid SemVer string +- `semver()`: Allows any valid SemVer string ### Any - `any([validators])` Validates against a union of types. Use when a node **must** contain **one and only one** of several types. It is valid From c45be0fee2453d707f60591a4d1e2de826ff8917 Mon Sep 17 00:00:00 2001 From: Thiago Perrotta Date: Thu, 25 Apr 2024 15:55:51 +0200 Subject: [PATCH 4/4] remove assertion --- yamale/validators/tests/test_validate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/yamale/validators/tests/test_validate.py b/yamale/validators/tests/test_validate.py index 67f0fe6..630ba3e 100644 --- a/yamale/validators/tests/test_validate.py +++ b/yamale/validators/tests/test_validate.py @@ -224,4 +224,3 @@ def test_semver(): assert not v.is_valid("+justmeta") assert not v.is_valid("9.8.7+meta+meta") assert not v.is_valid("9.8.7-whatever+meta+meta") - assert not v.is_valid("99999999999999999999999.999999999999999999.99999999999999999")