Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions care/utils/models/validators.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import re
from collections.abc import Iterable
from collections.abc import Collection, Iterable
from fractions import Fraction
from pathlib import Path

Expand Down Expand Up @@ -103,9 +103,23 @@ class PhoneNumberValidator(RegexValidator):
"support": support_number_regex,
}

def __init__(self, types: Iterable[str], *args, **kwargs):
if not isinstance(types, Iterable) or isinstance(types, str) or len(types) == 0:
msg = "The `types` argument must be a non-empty iterable."
def __init__(self, types: Collection[str], *args, **kwargs):
if not isinstance(types, Collection) or isinstance(types, str):
msg = "The `types` argument must be a non-empty collection."
raise ValueError(msg)

types = tuple(types)
if not types:
msg = "The `types` argument must be a non-empty collection."
raise ValueError(msg)

unsupported_types = [
type_
for type_ in types
if not isinstance(type_, str) or type_ not in self.regex_map
]
if unsupported_types:
msg = f"Unsupported phone number type(s): {', '.join(str(type_) for type_ in unsupported_types)}."
raise ValueError(msg)

self.types = types
Expand Down
37 changes: 37 additions & 0 deletions care/utils/tests/test_phone_number_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,40 @@ def test_invalid_support_numbers(self):
for number in self.invalid_support_numbers:
with self.assertRaises(ValidationError, msg=f"Failed for {number}"):
self.support_validator(number)

def test_types_must_be_non_empty_collection(self):
invalid_types = ["mobile", (), (type_ for type_ in ("mobile",))]

for types in invalid_types:
with self.assertRaisesMessage(
ValueError,
"The `types` argument must be a non-empty collection.",
):
PhoneNumberValidator(types=types)

def test_unsupported_types_raise_value_error(self):
with self.assertRaisesMessage(
ValueError,
"Unsupported phone number type(s): pager.",
):
PhoneNumberValidator(types=("mobile", "pager"))

def test_unhashable_types_raise_value_error(self):
with self.assertRaisesMessage(
ValueError,
"Unsupported phone number type(s): [].",
):
PhoneNumberValidator(types=([],))

def test_non_string_types_raise_value_error(self):
with self.assertRaisesMessage(
ValueError,
"Unsupported phone number type(s): 1.",
):
PhoneNumberValidator(types=(1,))

def test_types_accepts_reiterable_collection(self):
validator = PhoneNumberValidator(types=["mobile", "landline"])

self.assertIsNone(validator("+919876543210"))
self.assertIsNone(validator("+914902626488"))