Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PIN Code range and union territories in en_IN address provider #2091

Merged
merged 7 commits into from
Sep 30, 2024
Merged
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
178 changes: 177 additions & 1 deletion faker/providers/address/en_IN/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from .. import Provider as AddressProvider
import random
from typing import Optional
from faker.providers.address import Provider as AddressProvider


class Provider(AddressProvider):
Expand Down Expand Up @@ -391,10 +393,184 @@ class Provider(AddressProvider):
"West Bengal",
)

states_abbr = (
"AP",
"AR",
"AS",
"BR",
"CG",
"GA",
"GJ",
"HR",
"HP",
"JH",
"KA",
"KL",
"MP",
"MH",
"MN",
"ML",
"MZ",
"NL",
"OD",
"PB",
"RJ",
"SK",
"TN",
"TG",
"TR",
"UK",
"UP",
"WB",
)

union_territories = (
("Andaman and Nicobar Islands",),
("Chandigarh",),
("Dadra and Nagar Haveli, Dadra & Nagar Haveli",),
("Daman and Diu",),
("Delhi, National Capital Territory of Delhi",),
("Jammu and Kashmir",),
("Ladakh",),
("Lakshadweep",),
("Pondicherry",),
("Puducherry",),
)

union_territories_abbr = (
"AN",
"CH",
"DN",
"DD",
"DL",
"JK",
"LA",
"LD",
"PY",
)

# https://en.wikipedia.org/wiki/Postal_Index_Number

# FIXME: Some states such as `BR/JH` / `UK/UP` have similar PIN code ranges
# FIXME: as mentioned in above link.

state_pincode = {
"AP": [(510_000, 539_999)],
"AR": [(790_000, 792_999)],
"AS": [(780_000, 789_999)],
"BR": [(800_000, 859_999)],
"CG": [(490_000, 499_999)],
"GA": [(403_000, 403_999)],
"GJ": [(360_000, 399_999)],
"HR": [(120_000, 139_999)],
"HP": [(170_000, 179_999)],
"JH": [(800_000, 859_999)],
"KA": [(560_000, 599_999)],
"KL": [(670_000, 681_999), (683_000, 699_999)],
fcurella marked this conversation as resolved.
Show resolved Hide resolved
"MP": [(450_000, 489_999)],
"MH": [(400_000, 402_999), (404_000, 449_999)],
"MN": [(795_000, 795_999)],
"ML": [(793_000, 794_999)],
"MZ": [(796_000, 796_999)],
"NL": [(797_000, 798_999)],
"OD": [(750_000, 779_999)],
"PB": [(140_000, 159_999)],
"RJ": [(300_000, 349_999)],
"SK": [(737_000, 737_999)],
"TN": [(600_000, 669_999)],
"TG": [(500_000, 509_999)],
"TR": [(799_000, 799_999)],
"UK": [(200_000, 289_999)],
"UP": [(200_000, 289_999)],
"WB": [(700_000, 736_999), (738_000, 743_999), (745_000, 749_999)],
}

union_territories_pincode = {
"AN": [(744_000, 744_999)],
"CH": [(160_000, 169_999)],
"DN": [(396_000, 396_999)],
"DD": [(396_000, 396_999)],
"DL": [(110_000, 119_999)],
"JK": [(180_000, 199_999)],
"LA": [(180_000, 199_999)],
"LD": [(682_000, 682_999)],
"PY": [(605_000, 605_999)],
}

army_pincode = {"APS": (900_000, 999_999)}

def city_name(self) -> str:
return self.random_element(self.cities)

def administrative_unit(self) -> str:
return self.random_element(self.states)

state = administrative_unit

def union_territory(self) -> str:
"""Returns random union territory name"""

return self.random_element(self.union_territories)[0]

def pincode_in_state(
self, state_abbr: Optional[str] = None, include_union_territories=False
) -> int:
"""Random PIN Code within provided state abbreviation

:param state_abbr: State Abbr, defaults to None
:param include_union_territories: Include Union Territories ?, defaults to False
:raises ValueError: If incorrect state abbr
:return: PIN Code
"""

known_abbrs = self.states_abbr
if include_union_territories:
known_abbrs += self.union_territories_abbr

if state_abbr is None:
state_abbr = self.random_element(known_abbrs)

if state_abbr in known_abbrs:
codes = self.state_pincode
if include_union_territories:
codes = codes | self.union_territories_pincode

pincode_range = self.random_element(codes[state_abbr])

return self.generator.random.randint(*pincode_range)

raise ValueError("State Abbreviation not found in list")

def pincode_in_military(self) -> int:
"""Random PIN Code within Army Postal Service range"""

key = self.random_element(self.army_pincode.keys())

return self.generator.random.randint(*self.army_pincode[key])

# Aliases

def zipcode_in_state(
self, state_abbr: Optional[str] = None, include_union_territories=False
) -> int:
return self.pincode_in_state(state_abbr, include_union_territories)

def postcode_in_state(
self, state_abbr: Optional[str] = None, include_union_territories=False
) -> int:
return self.pincode_in_state(state_abbr, include_union_territories)

def pincode_in_army(self) -> int:
return self.pincode_in_military()

def zipcode_in_military(self) -> int:
return self.pincode_in_military()

def zipcode_in_army(self) -> int:
return self.pincode_in_military()

def postcode_in_military(self) -> int:
return self.pincode_in_military()

def postcode_in_army(self) -> int:
return self.pincode_in_military()
41 changes: 41 additions & 0 deletions tests/providers/test_address.py
Original file line number Diff line number Diff line change
Expand Up @@ -1865,17 +1865,58 @@ class TestEnIn:
"""Test en_IN address provider methods"""

def test_city_name(self, faker, num_samples):
"""Tests `city names` are fetched correctly"""

for _ in range(num_samples):
city_name = faker.city_name()
assert isinstance(city_name, str)
assert city_name in EnInAddressProvider.cities

def test_state(self, faker, num_samples):
"""Tests `states` are fetched correctly"""

for _ in range(num_samples):
state = faker.state()
assert isinstance(state, str)
assert state in EnInAddressProvider.states

def test_union_territories(self, faker, num_samples):
"""Tests `union_territories` are fetched correctly"""

for _ in range(num_samples):
union_territory = faker.union_territory()
assert isinstance(union_territory, str)
assert (union_territory,) in EnInAddressProvider.union_territories

@pytest.mark.parametrize("pincodes", ["pincode_in_state", "zipcode_in_state", "postcode_in_state"])
def test_pincodes_in_state(self, faker, num_samples, pincodes):
"""Test `pincodes` for state and union territories"""

for _ in range(num_samples):
include_ut = faker.random_element([True, False])
pincode = getattr(faker, pincodes)(include_union_territories=include_ut)
assert isinstance(pincode, int)
assert len(str(pincode)) == 6

@pytest.mark.parametrize(
"pincodes",
[
("pincode_in_army"),
("zipcode_in_army"),
("postcode_in_army"),
("postcode_in_military"),
("zipcode_in_military"),
("pincode_in_military"),
],
)
def test_pincodes_in_military(self, faker, num_samples, pincodes):
"""Test `pincodes` for Army"""

for _ in range(num_samples):
pincode = getattr(faker, pincodes)()
assert isinstance(pincode, int)
assert len(str(pincode)) == 6


class TestSkSk:
"""Test sk_SK address provider methods"""
Expand Down