Skip to content

Commit 1689ed7

Browse files
committed
feat: adds base58 and base64 validators
1 parent 29e8f01 commit 1689ed7

File tree

7 files changed

+123
-5
lines changed

7 files changed

+123
-5
lines changed

CHANGES.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@ Note to self: Breaking changes must increment either
99
1010
-->
1111

12+
## 0.26.0 (2024-04-02)
13+
14+
_**Breaking**_
15+
16+
> No breaking changes were introduced in this version.
17+
18+
_**Features**_
19+
20+
- feat: adds `base58` and `base64` validators by @yozachar in [#351](https://github.com/python-validators/validators/pull/351)
21+
22+
_**Maintenance**_
23+
24+
- fix: regex ignore-case uses only `a-z` by @yozachar in [#349](https://github.com/python-validators/validators/pull/349)
25+
- patch: supported extended latin in username by @yozachar in [#350](https://github.com/python-validators/validators/pull/350)
26+
27+
**Full Changelog**: [`0.25.0...0.26.0`](https://github.com/python-validators/validators/compare/0.25.0...0.26.0)
28+
29+
---
30+
1231
## 0.25.0 (2024-04-02)
1332

1433
_**Breaking**_
@@ -24,7 +43,7 @@ _**Maintenance**_
2443
- maint: adds quick start docs by @yozachar in [#344](https://github.com/python-validators/validators/pull/344)
2544
- fix: `domain` validation is now more consistent across rfcs by @yozachar in [#347](https://github.com/python-validators/validators/pull/347)
2645

27-
**Full Changelog**: [`0.24.2...0.25.0`](https://github.com/python-validators/validators/compare/0.23.2...0.24.0)
46+
**Full Changelog**: [`0.24.2...0.25.0`](https://github.com/python-validators/validators/compare/0.24.2...0.25.0)
2847

2948
---
3049

SECURITY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
| Version | Supported |
66
| ---------- | ------------------ |
7-
| `>=0.25.0` | :white_check_mark: |
7+
| `>=0.26.0` | :white_check_mark: |
88

99
## Reporting a Vulnerability
1010

docs/api/hashes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# hashes
22

3+
::: validators.hashes.base58
4+
::: validators.hashes.base64
35
::: validators.hashes.md5
46
::: validators.hashes.sha1
57
::: validators.hashes.sha224

docs/api/hashes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ hashes
22
------
33

44
.. module:: validators.hashes
5+
.. autofunction:: base58
6+
.. autofunction:: base64
57
.. autofunction:: md5
68
.. autofunction:: sha1
79
.. autofunction:: sha224

src/validators/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .cron import cron
99
from .domain import domain
1010
from .email import email
11-
from .hashes import md5, sha1, sha224, sha256, sha512
11+
from .hashes import base58, base64, md5, sha1, sha224, sha256, sha512
1212
from .hostname import hostname
1313
from .i18n import es_cif, es_doi, es_nie, es_nif, fi_business_id, fi_ssn, fr_department, fr_ssn
1414
from .iban import iban
@@ -46,6 +46,8 @@
4646
# ...
4747
"email",
4848
# hashes
49+
"base58",
50+
"base64",
4951
"md5",
5052
"sha1",
5153
"sha224",
@@ -82,4 +84,4 @@
8284
"validator",
8385
)
8486

85-
__version__ = "0.25.0"
87+
__version__ = "0.26.0"

src/validators/hashes.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,52 @@
77
from .utils import validator
88

99

10+
@validator
11+
def base58(value: str, /):
12+
"""Return whether or not given value is a valid base58 hash.
13+
14+
Examples:
15+
>>> base58('14pq6y9H2DLGahPsM4s7ugsNSD2uxpHsJx')
16+
# Output: True
17+
>>> base58('cUSECm5YzcXJwP')
18+
# Output: ValidationError(func=base58, args={'value': 'cUSECm5YzcXJwP'})
19+
20+
Args:
21+
value:
22+
base58 string to validate.
23+
24+
Returns:
25+
(Literal[True]): If `value` is a valid base58 hash.
26+
(ValidationError): If `value` is an invalid base58 hash.
27+
"""
28+
return re.match(r"^[1-9A-HJ-NP-Za-km-z]+$", value) if value else False
29+
30+
31+
@validator
32+
def base64(value: str, /):
33+
"""Return whether or not given value is a valid base64 hash.
34+
35+
Examples:
36+
>>> base64('Y2hhcmFjdGVyIHNldA==')
37+
# Output: True
38+
>>> base64('cUSECm5YzcXJwP')
39+
# Output: ValidationError(func=base64, args={'value': 'cUSECm5YzcXJwP'})
40+
41+
Args:
42+
value:
43+
base64 string to validate.
44+
45+
Returns:
46+
(Literal[True]): If `value` is a valid base64 hash.
47+
(ValidationError): If `value` is an invalid base64 hash.
48+
"""
49+
return (
50+
re.match(r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", value)
51+
if value
52+
else False
53+
)
54+
55+
1056
@validator
1157
def md5(value: str, /):
1258
"""Return whether or not given value is a valid MD5 hash.

tests/test_hashes.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,54 @@
44
import pytest
55

66
# local
7-
from validators import ValidationError, md5, sha1, sha224, sha256, sha512
7+
from validators import ValidationError, base58, base64, md5, sha1, sha224, sha256, sha512
8+
9+
# ==> base58 <== #
10+
11+
12+
@pytest.mark.parametrize(
13+
"value",
14+
[
15+
"cUSECaVvAiV3srWbFRvVPzm5YzcXJwPSwZfE7veYPHoXmR9h6YMQ",
16+
"18KToMF5ckjXBYt2HAj77qsG3GPeej3PZn",
17+
"n4FFXRNNEW1aA2WPscSuzHTCjzjs4TVE2Z",
18+
"38XzQ9dPGb1uqbZsjPtUajp7omy8aefjqj",
19+
],
20+
)
21+
def test_returns_true_on_valid_base58(value: str):
22+
"""Test returns true on valid base58."""
23+
assert base58(value)
24+
25+
26+
@pytest.mark.parametrize(
27+
"value",
28+
["ThisIsAReallyLongStringThatIsDefinitelyNotBase58Encoded", "abcABC!@#", "InvalidBase58!"],
29+
)
30+
def test_returns_failed_validation_on_invalid_base58(value: str):
31+
"""Test returns failed validation on invalid base58."""
32+
assert isinstance(base58(value), ValidationError)
33+
34+
35+
# ==> base64 <== #
36+
37+
38+
@pytest.mark.parametrize(
39+
"value",
40+
["SGVsbG8gV29ybGQ=", "U29tZSBkYXRhIHN0cmluZw==", "YW55IGNhcm5hbCBwbGVhcw=="],
41+
)
42+
def test_returns_true_on_valid_base64(value: str):
43+
"""Test returns true on valid base64."""
44+
assert base64(value)
45+
46+
47+
@pytest.mark.parametrize(
48+
"value",
49+
["SGVsbG8gV29ybGQ", "U29tZSBkYXRhIHN0cmluZw", "YW55IGNhcm5hbCBwbGVhc"],
50+
)
51+
def test_returns_failed_validation_on_invalid_base64(value: str):
52+
"""Test returns failed validation on invalid base64."""
53+
assert isinstance(base64(value), ValidationError)
54+
855

956
# ==> md5 <== #
1057

0 commit comments

Comments
 (0)