diff --git a/faker/providers/passport/it_IT/__init__.py b/faker/providers/passport/it_IT/__init__.py new file mode 100644 index 0000000000..c6bca7813a --- /dev/null +++ b/faker/providers/passport/it_IT/__init__.py @@ -0,0 +1,30 @@ +from .. import ElementsType +from .. import Provider as PassportProvider + + +class Provider(PassportProvider): + """Implement passport provider for ``it_IT``. + + Sources: + + - https://www.poliziadistato.it/articolo/10301 + - https://www.poliziadistato.it/statics/32/note_tecniche.pdf + """ + + electronic_passport_number_formats: ElementsType[str] = ( + # standard passaporto elettronico (elettronic passport) + # Format: 2 letters, 7 digits (e.g., YA1234567), used from 2010 on + "??#######", + ) + + def passport_number(self) -> str: + """ + Generate a valid Italian passport number + + The format consist in 2 uppercase letters followed by 7 digits. + """ + + # select the passport number format + format = self.random_element(self.electronic_passport_number_formats) + + return self.bothify(format).upper() diff --git a/faker/providers/ssn/it_IT/__init__.py b/faker/providers/ssn/it_IT/__init__.py index aefd42a09e..489095688f 100644 --- a/faker/providers/ssn/it_IT/__init__.py +++ b/faker/providers/ssn/it_IT/__init__.py @@ -5,6 +5,7 @@ from string import ascii_uppercase, digits from .. import Provider as SsnProvider +from .. import ElementsType ALPHABET = ascii_uppercase ALPHANUMERICS = sorted(digits + ascii_uppercase) @@ -8026,6 +8027,24 @@ def ssn(self) -> str: code: str = f"{surname}{name}{year}{month}{day}{municipality}" return code + checksum(code) + cie_format: ElementsType[str] = ( + # standard carta identitá elettronica (elettronic identity card ) + # Format: 2 letters, 5 digits, 2 letters + "??#####??", + ) + + def cie(self) -> str: + """ + Generate a valid Italian Electronic Identity Card (CIE) number. + Format: 2 uppercase letters, 5 numbers, 2 uppercase letters + + sources: + - https://www.cartaidentita.interno.gov.it/cose-la-carta/caratteristiche-del-documento/ + """ + + format = self.random_element(self.cie_format) + return self.bothify(format).upper() + vat_id_formats = ("IT###########",) def vat_id(self) -> str: diff --git a/tests/providers/test_passport.py b/tests/providers/test_passport.py index 002e102826..dc9a49f769 100644 --- a/tests/providers/test_passport.py +++ b/tests/providers/test_passport.py @@ -1,4 +1,6 @@ import re +import pytest +from faker.providers.passport.it_IT import Provider as ItPassportProvider from typing import Pattern @@ -21,3 +23,17 @@ def test_passport_number(self, faker, num_samples): pattern: Pattern = re.compile(r"[A-Z]{1,2}\d{7}") passport_number = faker.passport_number() assert pattern.fullmatch(passport_number) + + +@pytest.mark.parametrize("faker", ["it_IT"], indirect=True) +class TestItIT: + """Test it_IT passport provider methods""" + + def test_passport_number(self, faker, num_samples): + faker.add_provider(ItPassportProvider) + + pattern = re.compile(r"^[A-Z]{2}\d{7}$") + + for _ in range(num_samples): + passport_number = faker.passport_number() + assert pattern.fullmatch(passport_number) diff --git a/tests/providers/test_ssn.py b/tests/providers/test_ssn.py index 85b47b0d37..c9d4ad7544 100644 --- a/tests/providers/test_ssn.py +++ b/tests/providers/test_ssn.py @@ -981,6 +981,13 @@ def setUp(self): self.fake = Faker("it_IT") Faker.seed(0) + def test_cie(self): + pattern = re.compile(r"^[A-Z]{2}\d{5}[A-Z]{2}$") + + for _ in range(100): + cie_code = self.fake.cie() + assert pattern.fullmatch(cie_code) + def test_vat_id(self): for _ in range(100): assert re.search(r"^IT\d{11}$", self.fake.vat_id())