Skip to content

Commit 2dac115

Browse files
committed
feat: added is_palindrome validator
1 parent efb6146 commit 2dac115

File tree

6 files changed

+105
-2
lines changed

6 files changed

+105
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ dist
44
build
55
py.validator.egg-info
66
*.pyc
7+
*.tmp

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ Validator | Description
9494
**is_octal(str)** | check if the string is a valid octal number.
9595
**is_odd(str/int)** | checks if the input is an odd number, it accepts either a string or an int.
9696
**is_online(str)** | checks if the internet connection is available, where the input argument is an optional url, if passed it will be check if it is reachable _(if it is reachable it will evaluate to *True*)_.
97+
**is_palindrome(str, options)** | checks if the string is a palindrom. The options argument is a optional dictionary which can contain a `insensitive` boolean property that will enable / disable case sensitivity, the default value is *True*. Special character that are contained in the string are ignored.
9798
**is_passport_number(str, country_code)** | check if the string is a valid passport number.<br/><br/>country_code is one of `['AM', 'AR', 'AT', 'AU', 'BA', 'BE', 'BG', 'BY', 'BR', 'CA', 'CH', 'CN', 'CY', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE' 'IN', 'IR', 'ID', 'IS', 'IT', 'JP', 'KR', 'LT', 'LU', 'LV', 'LY', 'MT', 'MY', 'MZ', 'NL', 'PL', 'PT', 'RO', 'RS', 'RU', 'SE', 'SL', 'SK', 'TR', 'UA', 'US']`.
9899
**is_port(str)** | check if the string is a valid port number.
99100
**is_prime(str/int)** | checks if the input is an prime number, it accepts either a string or an int.

pyvalidator/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
from pyvalidator.is_octal import is_octal
4949
from pyvalidator.is_odd import is_odd
5050
from pyvalidator.is_online import is_online
51+
from pyvalidator.is_palindrome import is_palindrome
5152
from pyvalidator.is_passport_number import is_passport_number
5253
from pyvalidator.is_port import is_port
5354
from pyvalidator.is_prime import is_prime

pyvalidator/is_palindrome.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from typing import TypedDict
2+
from .utils.assert_string import assert_string
3+
from .utils.merge import merge
4+
5+
6+
class IsPalindromeOptions(TypedDict):
7+
insensitive: bool
8+
9+
default_is_palindrome_options: IsPalindromeOptions = {
10+
"insensitive": True,
11+
}
12+
13+
def is_palindrome(input: str, options: IsPalindromeOptions = {}) -> bool:
14+
input = assert_string(input)
15+
16+
options = merge(options, default_is_palindrome_options)
17+
18+
input = input.sub(r'[^a-zA-Z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]', '')
19+
20+
if not options['insensitive']:
21+
return input == input[::-1]
22+
23+
return input.lower() == input[::-1].lower()

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
readme = f.read()
55

66
MAJOR = 0
7-
MINOR = 13
8-
PATCH = 6
7+
MINOR = 14
8+
PATCH = 0
99

1010
VERSION = '{}.{}.{}'.format(MAJOR, MINOR, PATCH)
1111
DESCRIPTION = 'String validation and sanitization'

test/test_is_palindrome.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import unittest
2+
3+
from pyvalidator import *
4+
5+
6+
class TestIsPalindrome(unittest.TestCase):
7+
def valid_check(self, items, options = {}):
8+
for item in items:
9+
try:
10+
self.assertTrue(is_palindrome(item, options))
11+
except Exception as e:
12+
print(f'failed for input: {item}')
13+
raise e
14+
15+
def invalid_check(self, items, options = {}):
16+
for item in items:
17+
try:
18+
self.assertFalse(is_palindrome(item, options))
19+
except Exception as e:
20+
print(f'failed for input: {item}')
21+
raise e
22+
23+
def test_valid_palindrome(self):
24+
valid_items = [
25+
'',
26+
'A',
27+
'EVE',
28+
'radar',
29+
'reviver',
30+
'top spot',
31+
'ROTATOR',
32+
'step not on pets.',
33+
'MADAM I\'M ADAM',
34+
'no lemon, NO Melon'
35+
'No LeMoN, nomelon',
36+
'Able was I, ere I saw Elba!',
37+
'Was it a car or a cat I saw',
38+
'Eine treue Familie bei Lima feuerte nie',
39+
'Die Liebe ist Sieger; stets rege ist sie bei Leid',
40+
'O Genie, der Herr ehre Dein Ego',
41+
'Elu par cette crapule',
42+
'Tu l\'as trop ecrase cesar ce port salut.',
43+
'A l\'autel elle alla, elle le tua la',
44+
'Caser vite ce palindrome ne mord ni lape cet ivre sac',
45+
'isälläsi',
46+
'Ana, kanna kana',
47+
'Hupaisa asia, Puh',
48+
'Isorikas sika sökösakissa kirosi',
49+
'I jogurt ujutru goji?',
50+
'УЈАК ИМА РАДАР А МИ КАЈУ',
51+
'око',
52+
'12321'
53+
54+
]
55+
self.valid_check(valid_items)
56+
print('OK - test_valid_palindrome')
57+
58+
def test_invalid_palindrome(self):
59+
invalid_items = [
60+
'asd',
61+
'hello, world'
62+
'this is not a palindrome',
63+
'12345',
64+
'ок0'
65+
66+
]
67+
self.invalid_check(invalid_items)
68+
print('OK - test_invalid_palindrome')
69+
70+
def test_invalid_case_sensitive_palindrome(self):
71+
invalid_items = [
72+
'No LeMoN, nomelon',
73+
'Was it a car or a cat I saw',
74+
'isäLläSi',
75+
]
76+
self.invalid_check(invalid_items, { "insensitive": False })
77+
print('OK - test_invalid_case_sensitive_palindrome')

0 commit comments

Comments
 (0)