feat: add area name to telephone number (#90)
reference: https://www.prokerala.com/how-to/call/nepal/area-codes/?utm_source=chatgpt.com potential issue: some districts use same code, eg: gandaki and gorkha, might not return the expected district
This commit is contained in:
1 parent
8148bbf851
commit
e693606ab1
3 files changed
+165
-3
No files matched your search
@@ -344,6 +344,7 @@ number_text = number.add_comma("1234567890") # 1,23,45,67,890
|
||||
```
|
||||
|
||||
### nepalinumber
|
||||
|
||||
`nepalinumber` is a new data type, which can be used to represent Nepali (Devanagari) numbers. It allows us to perform arithmetic operations, just like with int and float. Additionally, it can be used to parse numbers and output them in Devanagari format.
|
||||
|
||||
```python
|
||||
@@ -351,6 +352,7 @@ from nepali.number import nepalinumber
|
||||
```
|
||||
|
||||
**Parsing**
|
||||
|
||||
```python
|
||||
a = nepalinumber("१८.२७")
|
||||
print(a) # 18.27
|
||||
@@ -360,18 +362,21 @@ print(b) # 15
|
||||
```
|
||||
|
||||
**Nepali (Devanagari) output**
|
||||
|
||||
```python
|
||||
a = nepalinumber("18.27")
|
||||
print(a.str_ne()) # १८.२७
|
||||
```
|
||||
|
||||
**Arithmetic operations**
|
||||
|
||||
```python
|
||||
a = nepalinumber("1")
|
||||
b = nepalinumber("२")
|
||||
c = a + b * 3
|
||||
print(c) # 7
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phone Number
|
||||
@@ -398,7 +403,7 @@ phone_number.parse("9851377890")
|
||||
# {'type': 'Mobile', 'number': '9851377890', 'operator': <Operator: Nepal Telecom>}
|
||||
|
||||
phone_number.parse("+977-142314819")
|
||||
# {'type': 'Landline', 'number': '0142314819', 'area_code': '01'}
|
||||
# {'type': 'Landline', 'number': '0142314819', 'area_code': '01', 'area': ['Bhaktapur', 'Kathmandu', 'Lalitpur']}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
+124
-2
@@ -21,6 +21,113 @@ class Operator(Enum):
|
||||
return f"<Operator: {self.value}>"
|
||||
|
||||
|
||||
class Area(Enum):
|
||||
# Koshi Province
|
||||
BHOJPUR = ("Bhojpur", "029")
|
||||
DHANKUTA = ("Dhankuta", "026")
|
||||
ILAM = ("Ilam", "027")
|
||||
JHAPA = ("Jhapa", "023")
|
||||
KHOTANG = ("Khotang", "036")
|
||||
MORANG = ("Morang", "021")
|
||||
OKHALDHUNGA = ("Okhaldhunga", "037")
|
||||
PANCHTHAR = ("Panchthar", "024")
|
||||
SANKHUWASABHA = ("Sankhuwasabha", "029")
|
||||
SOLUKHUMBU = ("Solukhumbu", "038")
|
||||
SUNSARI = ("Sunsari", "025")
|
||||
TAPLEJUNG = ("Taplejung", "024")
|
||||
TERHATHUM = ("Terhathum", "026")
|
||||
UDAYAPUR = ("Udayapur", "035")
|
||||
|
||||
# Madhesh Province
|
||||
BARA = ("Bara", "053")
|
||||
DHANUSA = ("Dhanusa", "041")
|
||||
MAHOTTARI = ("Mahottari", "044")
|
||||
PARSA = ("Parsa", "051")
|
||||
RAUTAHAT = ("Rautahat", "055")
|
||||
SAPTARI = ("Saptari", "031")
|
||||
SARLAHI = ("Sarlahi", "046")
|
||||
SIRAHA = ("Siraha", "033")
|
||||
|
||||
# Bagmati Province
|
||||
BHAKTAPUR = ("Bhaktapur", "01")
|
||||
CHITWAN = ("Chitwan", "056")
|
||||
DHADING = ("Dhading", "010")
|
||||
DOLAKHA = ("Dolakha", "049")
|
||||
KATHMANDU = ("Kathmandu", "01")
|
||||
KAVREPALANCHOK = ("Kavrepalanchok", "011")
|
||||
LALITPUR = ("Lalitpur", "01")
|
||||
MAKWANPUR = ("Makwanpur", "057")
|
||||
NUWAKOT = ("Nuwakot", "010")
|
||||
RAMECHHAP = ("Ramechhap", "048")
|
||||
RASUWA = ("Rasuwa", "010")
|
||||
SINDHUPALCHOK = ("Sindhupalchok", "011")
|
||||
SINDHULI = ("Sindhuli", "047")
|
||||
|
||||
# Gandaki Province
|
||||
BAGLUNG = ("Baglung", "068")
|
||||
GORKHA = ("Gorkha", "064")
|
||||
KASKI = ("Kaski", "061")
|
||||
LAMJUNG = ("Lamjung", "066")
|
||||
MANANG = ("Manang", "066")
|
||||
MUSTANG = ("Mustang", "069")
|
||||
MYAGDI = ("Myagdi", "069")
|
||||
NAWALPUR = ("Nawalpur", "078")
|
||||
PARBAT = ("Parbat", "067")
|
||||
SYANGJA = ("Syangja", "063")
|
||||
TANAHU = ("Tanahu", "065")
|
||||
|
||||
# Lumbini Provinc
|
||||
ARGHAKHANCHI = ("Arghakhanchi", "077")
|
||||
BANKE = ("Banke", "081")
|
||||
BARDIYA = ("Bardiya", "084")
|
||||
DANG = ("Dang", "082")
|
||||
GULMI = ("Gulmi", "079")
|
||||
KAPILVASTU = ("Kapilvastu", "076")
|
||||
PARASI = ("Parasi", "078")
|
||||
PALPA = ("Palpa", "075")
|
||||
PYUTHAN = ("Pyuthan", "086")
|
||||
ROLPA = ("Rolpa", "086")
|
||||
RUKUM_EAST = ("Rukum East", "088")
|
||||
RUPANDEHI = ("Rupandehi", "071")
|
||||
|
||||
# Karnali Province
|
||||
DAILEKH = ("Dailekh", "089")
|
||||
DOLPA = ("Dolpa", "087")
|
||||
HUMLA = ("Humla", "019")
|
||||
JAJARKOT = ("Jajarkot", "089")
|
||||
JUMLA = ("Jumla", "087")
|
||||
KALIKOT = ("Kalikot", "087")
|
||||
MUGU = ("Mugu", "019")
|
||||
RUKUM_WEST = ("Rukum West", "088")
|
||||
SALYAN = ("Salyan", "088")
|
||||
SURKHET = ("Surkhet", "083")
|
||||
|
||||
# Sudurpashchim Province
|
||||
ACHHAM = ("Achham", "097")
|
||||
BAITADI = ("Baitadi", "095")
|
||||
BAJHANG = ("Bajhang", "092")
|
||||
BAJURA = ("Bajura", "097")
|
||||
DADELDHURA = ("Dadeldhura", "096")
|
||||
DARCHULA = ("Darchula", "093")
|
||||
DOTI = ("Doti", "094")
|
||||
KAILALI = ("Kailali", "091")
|
||||
KANCHANPUR = ("Kanchanpur", "099")
|
||||
|
||||
def __init__(self, area: str, area_code: str):
|
||||
self.area = area
|
||||
self.area_code = area_code
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.area}: {self.area_code}"
|
||||
|
||||
@classmethod
|
||||
def get_by_area_code(cls, area_code: str = None) -> list[str]:
|
||||
if not area_code:
|
||||
return []
|
||||
results = [area.value[0] for area in cls if area.value[1] == area_code]
|
||||
return results
|
||||
|
||||
|
||||
def is_mobile_number(number: str) -> bool:
|
||||
"""
|
||||
Returns True is the input number is mobile number.
|
||||
@@ -168,16 +275,31 @@ def _parse_landline_number(number) -> dict:
|
||||
"type": "Landline",
|
||||
"number": "98XXXXXXXX",
|
||||
"area_code": <AreaCode>
|
||||
"area": list of areas/districts
|
||||
}
|
||||
"""
|
||||
number = get_exact_number(number)
|
||||
|
||||
# adding zero
|
||||
if number[0] != "0":
|
||||
number = f"0{number}"
|
||||
|
||||
number = get_exact_number(number)
|
||||
area_code = _get_area_code(number)
|
||||
area = _get_area(area_code)
|
||||
|
||||
if not area:
|
||||
return None
|
||||
|
||||
return {
|
||||
"type": "Landline",
|
||||
"number": number,
|
||||
"area_code": _get_area_code(number),
|
||||
"area_code": area_code,
|
||||
"area": area,
|
||||
}
|
||||
|
||||
|
||||
def _get_area(area_code: str) -> list[str] | None:
|
||||
"""
|
||||
Returns the details of the area code.
|
||||
"""
|
||||
return Area.get_by_area_code(area_code)
|
||||
@@ -3,8 +3,10 @@ from unittest import mock
|
||||
|
||||
from nepali.phone_number import (
|
||||
Operator,
|
||||
Area,
|
||||
_get_area_code,
|
||||
_get_operator,
|
||||
_get_area,
|
||||
_parse_landline_number,
|
||||
_parse_mobile_number,
|
||||
get_exact_number,
|
||||
@@ -33,6 +35,28 @@ class TestOperator(unittest.TestCase):
|
||||
self.assertEqual(repr(operator), f"<Operator: {operator.value}>")
|
||||
|
||||
|
||||
class TestArea(unittest.TestCase):
|
||||
def test_area_with_invalid_data(self):
|
||||
with self.assertRaises(ValueError):
|
||||
Area(("Bhojpur", "026"))
|
||||
Area(("India", "01"))
|
||||
|
||||
def test_area_with_valid_data(self):
|
||||
a_1 = Area(("Udayapur", "035"))
|
||||
a_2 = Area(("Rolpa", "086"))
|
||||
self.assertEqual(a_1, Area.UDAYAPUR)
|
||||
self.assertEqual(a_2, Area.ROLPA)
|
||||
|
||||
def test_get_by_area_code(self):
|
||||
self.assertEqual(
|
||||
set(Area.get_by_area_code("01")),
|
||||
set(["Bhaktapur", "Kathmandu", "Lalitpur"]),
|
||||
)
|
||||
|
||||
self.assertEqual(Area.get_by_area_code(""), [])
|
||||
self.assertEqual(Area.get_by_area_code(), [])
|
||||
|
||||
|
||||
class TestPhoneNumberValidation(unittest.TestCase):
|
||||
def test_is_mobile_number(self):
|
||||
# True case
|
||||
@@ -202,19 +226,27 @@ class TestLandlineNumberParser(unittest.TestCase):
|
||||
self.assertEqual(_get_area_code("063420211"), "063")
|
||||
|
||||
@mock.patch("nepali.phone_number._get_area_code", return_value="test")
|
||||
@mock.patch("nepali.phone_number._get_area", return_value="area name")
|
||||
def test__parse_landline_number_returns_valid_data(self, *_):
|
||||
data = _parse_landline_number("0142314819")
|
||||
self.assertEqual(data["type"], "Landline")
|
||||
self.assertEqual(data["area_code"], "test")
|
||||
self.assertEqual(data["area"], "area name")
|
||||
self.assertEqual(data["number"], "0142314819")
|
||||
|
||||
@mock.patch("nepali.phone_number._get_area_code", return_value="test")
|
||||
@mock.patch("nepali.phone_number._get_area", return_value="area name")
|
||||
def test__parse_landline_number_returns_valid_data_for_977(self, *_):
|
||||
data = _parse_landline_number("+977142314819")
|
||||
self.assertEqual(data["type"], "Landline")
|
||||
self.assertEqual(data["area_code"], "test")
|
||||
self.assertEqual(data["area"], "area name")
|
||||
self.assertEqual(data["number"], "0142314819")
|
||||
|
||||
@mock.patch("nepali.phone_number.Area.get_by_area_code", return_value="area")
|
||||
def test__get_area(self, *_):
|
||||
self.assertEqual(_get_area("code"), "area")
|
||||
|
||||
|
||||
class TestParser(unittest.TestCase):
|
||||
def test_none_number_returns_none(self):
|
||||
@@ -252,3 +284,6 @@ class TestParseIntegration(unittest.TestCase):
|
||||
self.assertEqual(data and data["type"], "Landline")
|
||||
self.assertEqual(data and data["number"], "0142314819")
|
||||
self.assertEqual(data and data["area_code"], "01")
|
||||
self.assertEqual(
|
||||
data and set(data["area"]), set(["Kathmandu", "Bhaktapur", "Lalitpur"])
|
||||
)
|
||||
Reference in new issue
Block a user