Skip to content

Commit

Permalink
Take into account area codes for French phone numbers
Browse files Browse the repository at this point in the history
French landline numbers (starting with 01, 02, 03, 04, 05) are limited to well-known area codes. This is taken into account when generating the phone numbers.

Mobile phone numbers starting with 07 are also added.

Fixes: #1516
  • Loading branch information
nicarl committed Oct 22, 2021
1 parent 787c6b2 commit 2512e97
Show file tree
Hide file tree
Showing 2 changed files with 274 additions and 32 deletions.
283 changes: 251 additions & 32 deletions faker/providers/phone_number/fr_FR/__init__.py
Expand Up @@ -3,36 +3,255 @@

class Provider(PhoneNumberProvider):
formats = (
'+33 (0)1 ## ## ## ##',
'+33 (0)1 ## ## ## ##',
'+33 (0)2 ## ## ## ##',
'+33 (0)3 ## ## ## ##',
'+33 (0)4 ## ## ## ##',
'+33 (0)5 ## ## ## ##',
'+33 (0)6 ## ## ## ##',
'+33 (0)8 0# ## ## ##',
'+33 1 ## ## ## ##',
'+33 1 ## ## ## ##',
'+33 2 ## ## ## ##',
'+33 3 ## ## ## ##',
'+33 4 ## ## ## ##',
'+33 5 ## ## ## ##',
'+33 6 ## ## ## ##',
'+33 8 0# ## ## ##',
'01########',
'01########',
'02########',
'03########',
'04########',
'05########',
'06########',
'080#######',
'01 ## ## ## ##',
'01 ## ## ## ##',
'02 ## ## ## ##',
'03 ## ## ## ##',
'04 ## ## ## ##',
'05 ## ## ## ##',
'06 ## ## ## ##',
'08 0# ## ## ##',
'+33 (0){{area_code_with_separator}} ## ## ##',
'+33 {{area_code_with_separator}} ## ## ##',
'0{{area_code_without_separator}}######',
'0{{area_code_with_separator}} ## ## ##',
)

# https://fr.wikipedia.org/wiki/Liste_des_indicatifs_t%C3%A9l%C3%A9phoniques_en_France#Liste_des_indicatifs_d%C3%A9partementaux_fran%C3%A7ais_class%C3%A9s_par_indicatif
area_codes = (
# landlines
"130",
"134",
"139",
"140",
"141",
"142",
"143",
"144",
"145",
"146",
"147",
"148",
"149",
"153",
"155",
"156",
"158",
"160",
"164",
"169",
"170",
"172",
"173",
"174",
"175",
"176",
"177",
"178",
"179",
"180",
"181",
"182",
"183",
"188",
"214",
"218",
"219",
"221",
"222",
"223",
"228",
"229",
"230",
"231",
"232",
"233",
"234",
"235",
"236",
"237",
"238",
"240",
"241",
"243",
"244",
"245",
"246",
"247",
"248",
"249",
"250",
"251",
"252",
"253",
"254",
"255",
"256",
"257",
"258",
"261",
"262",
"269",
"272",
"276",
"277",
"278",
"279",
"285",
"290",
"296",
"297",
"298",
"299",
"310",
"320",
"321",
"322",
"323",
"324",
"325",
"326",
"327",
"328",
"329",
"339",
"344",
"345",
"351",
"352",
"353",
"354",
"355",
"356",
"357",
"358",
"359",
"360",
"361",
"362",
"363",
"364",
"365",
"366",
"367",
"368",
"369",
"370",
"371",
"372",
"373",
"375",
"376",
"379",
"380",
"381",
"382",
"383",
"384",
"385",
"386",
"387",
"388",
"389",
"390",
"411",
"413",
"415",
"420",
"422",
"423",
"426",
"427",
"430",
"432",
"434",
"437",
"438",
"442",
"443",
"444",
"449",
"450",
"456",
"457",
"458",
"463",
"465",
"466",
"467",
"468",
"469",
"470",
"471",
"472",
"473",
"474",
"475",
"476",
"477",
"478",
"479",
"480",
"481",
"482",
"483",
"484",
"485",
"486",
"487",
"488",
"489",
"490",
"491",
"492",
"493",
"494",
"495",
"497",
"498",
"499",
"58 ",
"516",
"517",
"518",
"519",
"524",
"531",
"532",
"533",
"534",
"535",
"536",
"540",
"545",
"546",
"547",
"549",
"553",
"554",
"555",
"556",
"557",
"558",
"559",
"561",
"562",
"563",
"564",
"565",
"567",
"579",
"581",
"582",
"586",
"587",
"590",
"594",
"596",
# mobile numbers
"6##",
"7##",
)

def area_code_without_separator(self) -> str:
return self.numerify(self.random_element(self.area_codes))

def area_code_with_separator(self) -> str:
area_code: str = self.random_element(self.area_codes)
return self.numerify(f"{area_code[0]} {area_code[1:]}")

def phone_number(self) -> str:
pattern: str = self.random_element(self.formats)
return self.numerify(self.generator.parse(pattern))
23 changes: 23 additions & 0 deletions tests/providers/test_phone_number.py
Expand Up @@ -311,3 +311,26 @@ def test_phone_number(self, faker, num_samples):
for _ in range(num_samples):
phone = faker.phone_number()
assert pattern.fullmatch(phone)


class TestFrFr:
def test_phone_number(self, faker, num_samples):
pattern_no_whitespaces: Pattern = re.compile(
r'^0\d{9}$',
)
pattern_no_country_prefix: Pattern = re.compile(
r'^0\d \d{2} \d{2} \d{2} \d{2}$',
)
pattern_country_prefix_1: Pattern = re.compile(
r'^\+33 \(0\)\d \d{2} \d{2} \d{2} \d{2}$',
)
pattern_country_prefix_2: Pattern = re.compile(
r'^\+33 \d \d{2} \d{2} \d{2} \d{2}$',
)
patterns = [pattern_no_whitespaces,
pattern_no_country_prefix,
pattern_country_prefix_1,
pattern_country_prefix_2]
for _ in range(num_samples):
phone_number = faker.phone_number()
assert any([re.match(pattern, phone_number) for pattern in patterns])

0 comments on commit 2512e97

Please sign in to comment.