Skip to content

i18n

validators.i18n.es_cif(value)

Validate a Spanish CIF.

Each company in Spain prior to 2008 had a distinct CIF and has been discontinued. For more information see wikipedia.org/cif.

The new replacement is to use NIF for absolutely everything. The issue is that there are "types" of NIFs now: company, person [citizen or resident] all distinguished by the first character of the DOI. For this reason we will continue to call CIFs NIFs, that are used for companies.

This validator is based on generadordni.es.

Examples:

>>> es_cif('B25162520')
# Output: True
>>> es_cif('B25162529')
# Output: ValidationError(func=es_cif, args=...)

Parameters:

Name Type Description Default
value str

DOI string which is to be validated.

required

Returns:

Type Description
Literal[True]

If value is a valid DOI string.

ValidationError

If value is an invalid DOI string.

Source code in src/validators/i18n/es.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@validator
def es_cif(value: str, /):
    """Validate a Spanish CIF.

    Each company in Spain prior to 2008 had a distinct CIF and has been
    discontinued. For more information see [wikipedia.org/cif][1].

    The new replacement is to use NIF for absolutely everything. The issue is
    that there are "types" of NIFs now: company, person [citizen or resident]
    all distinguished by the first character of the DOI. For this reason we
    will continue to call CIFs NIFs, that are used for companies.

    This validator is based on [generadordni.es][2].

    [1]: https://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
    [2]: https://generadordni.es/

    Examples:
        >>> es_cif('B25162520')
        # Output: True
        >>> es_cif('B25162529')
        # Output: ValidationError(func=es_cif, args=...)

    Args:
        value:
            DOI string which is to be validated.

    Returns:
        (Literal[True]): If `value` is a valid DOI string.
        (ValidationError): If `value` is an invalid DOI string.
    """
    if not value or len(value) != 9:
        return False
    value = value.upper()
    table = "JABCDEFGHI"
    first_chr = value[0]
    doi_body = value[1:8]
    control = value[8]
    if not doi_body.isdigit():
        return False
    res = (
        10
        - sum(
            # Multiply each positionally even doi
            # digit by 2 and sum it all together
            sum(map(int, str(int(char) * 2))) if index % 2 == 0 else int(char)
            for index, char in enumerate(doi_body)
        )
        % 10
    ) % 10
    if first_chr in "ABEH":  # Number type
        return str(res) == control
    if first_chr in "PSQW":  # Letter type
        return table[res] == control
    return control in {str(res), table[res]} if first_chr in "CDFGJNRUV" else False

validators.i18n.es_doi(value)

Validate a Spanish DOI.

A DOI in spain is all NIF / CIF / NIE / DNI -- a digital ID. For more information see wikipedia.org/doi. This validator is based on generadordni.es.

Examples:

>>> es_doi('X0095892M')
# Output: True
>>> es_doi('X0095892X')
# Output: ValidationError(func=es_doi, args=...)

Parameters:

Name Type Description Default
value str

DOI string which is to be validated.

required

Returns:

Type Description
Literal[True]

If value is a valid DOI string.

ValidationError

If value is an invalid DOI string.

Source code in src/validators/i18n/es.py
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
@validator
def es_doi(value: str, /):
    """Validate a Spanish DOI.

    A DOI in spain is all NIF / CIF / NIE / DNI -- a digital ID.
    For more information see [wikipedia.org/doi][1]. This validator
    is based on [generadordni.es][2].

    [1]: https://es.wikipedia.org/wiki/Identificador_de_objeto_digital
    [2]: https://generadordni.es/

    Examples:
        >>> es_doi('X0095892M')
        # Output: True
        >>> es_doi('X0095892X')
        # Output: ValidationError(func=es_doi, args=...)

    Args:
        value:
            DOI string which is to be validated.

    Returns:
        (Literal[True]): If `value` is a valid DOI string.
        (ValidationError): If `value` is an invalid DOI string.
    """
    return es_nie(value) or es_nif(value) or es_cif(value)

validators.i18n.es_nie(value)

Validate a Spanish NIE.

The NIE is a tax identification number in Spain, known in Spanish as the NIE, or more formally the Número de identidad de extranjero. For more information see wikipedia.org/nie. This validator is based on generadordni.es.

Examples:

>>> es_nie('X0095892M')
# Output: True
>>> es_nie('X0095892X')
# Output: ValidationError(func=es_nie, args=...)

Parameters:

Name Type Description Default
value str

DOI string which is to be validated.

required

Returns:

Type Description
Literal[True]

If value is a valid DOI string.

ValidationError

If value is an invalid DOI string.

Source code in src/validators/i18n/es.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
@validator
def es_nie(value: str, /):
    """Validate a Spanish NIE.

    The NIE is a tax identification number in Spain, known in Spanish
    as the NIE, or more formally the Número de identidad de extranjero.
    For more information see [wikipedia.org/nie][1]. This validator
    is based on [generadordni.es][2].

    [1]: https://es.wikipedia.org/wiki/N%C3%BAmero_de_identidad_de_extranjero
    [2]: https://generadordni.es/

    Examples:
        >>> es_nie('X0095892M')
        # Output: True
        >>> es_nie('X0095892X')
        # Output: ValidationError(func=es_nie, args=...)

    Args:
        value:
            DOI string which is to be validated.

    Returns:
        (Literal[True]): If `value` is a valid DOI string.
        (ValidationError): If `value` is an invalid DOI string.
    """
    number_by_letter = {"X": "0", "Y": "1", "Z": "2"}
    # NIE must must start with X Y or Z
    if value and value[0] in number_by_letter:
        return _nif_nie_validation(value, number_by_letter, {"X0000000T"})
    return False

validators.i18n.es_nif(value)

Validate a Spanish NIF.

Each entity, be it person or company in Spain has a distinct NIF. Since we've designated CIF to be a company NIF, this NIF is only for person. For more information see wikipedia.org/nif. This validator is based on generadordni.es.

Examples:

>>> es_nif('26643189N')
# Output: True
>>> es_nif('26643189X')
# Output: ValidationError(func=es_nif, args=...)

Parameters:

Name Type Description Default
value str

DOI string which is to be validated.

required

Returns:

Type Description
Literal[True]

If value is a valid DOI string.

ValidationError

If value is an invalid DOI string.

Source code in src/validators/i18n/es.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
@validator
def es_nif(value: str, /):
    """Validate a Spanish NIF.

    Each entity, be it person or company in Spain has a distinct NIF. Since
    we've designated CIF to be a company NIF, this NIF is only for person.
    For more information see [wikipedia.org/nif][1]. This validator
    is based on [generadordni.es][2].

    [1]: https://es.wikipedia.org/wiki/N%C3%BAmero_de_identificaci%C3%B3n_fiscal
    [2]: https://generadordni.es/

    Examples:
        >>> es_nif('26643189N')
        # Output: True
        >>> es_nif('26643189X')
        # Output: ValidationError(func=es_nif, args=...)

    Args:
        value:
            DOI string which is to be validated.

    Returns:
        (Literal[True]): If `value` is a valid DOI string.
        (ValidationError): If `value` is an invalid DOI string.
    """
    number_by_letter = {"L": "0", "M": "0", "K": "0"}
    special_cases = {"X0000000T", "00000000T", "00000001R"}
    return _nif_nie_validation(value, number_by_letter, special_cases)

validators.i18n.fi_business_id(value)

Validate a Finnish Business ID.

Each company in Finland has a distinct business id. For more information see Finnish Trade Register

Examples:

>>> fi_business_id('0112038-9')  # Fast Monkeys Ltd
# Output: True
>>> fi_business_id('1234567-8')  # Bogus ID
# Output: ValidationError(func=fi_business_id, ...)

Parameters:

Name Type Description Default
value str

Business ID string to be validated.

required

Returns:

Type Description
Literal[True]

If value is a valid finnish business id.

ValidationError

If value is an invalid finnish business id.

Source code in src/validators/i18n/fi.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@validator
def fi_business_id(value: str, /):
    """Validate a Finnish Business ID.

    Each company in Finland has a distinct business id. For more
    information see [Finnish Trade Register][1]

    [1]: http://en.wikipedia.org/wiki/Finnish_Trade_Register

    Examples:
        >>> fi_business_id('0112038-9')  # Fast Monkeys Ltd
        # Output: True
        >>> fi_business_id('1234567-8')  # Bogus ID
        # Output: ValidationError(func=fi_business_id, ...)

    Args:
        value:
            Business ID string to be validated.

    Returns:
        (Literal[True]): If `value` is a valid finnish business id.
        (ValidationError): If `value` is an invalid finnish business id.
    """
    if not value:
        return False
    if not re.match(_business_id_pattern(), value):
        return False
    factors = [7, 9, 10, 5, 8, 4, 2]
    numbers = map(int, value[:7])
    checksum = int(value[8])
    modulo = sum(f * n for f, n in zip(factors, numbers)) % 11
    return (11 - modulo == checksum) or (modulo == checksum == 0)

validators.i18n.fi_ssn(value, /, *, allow_temporal_ssn=True)

Validate a Finnish Social Security Number.

This validator is based on django-localflavor-fi.

Examples:

>>> fi_ssn('010101-0101')
# Output: True
>>> fi_ssn('101010-0102')
# Output: ValidationError(func=fi_ssn, args=...)

Parameters:

Name Type Description Default
value str

Social Security Number to be validated.

required
allow_temporal_ssn bool

Whether to accept temporal SSN numbers. Temporal SSN numbers are the ones where the serial is in the range [900-999]. By default temporal SSN numbers are valid.

True

Returns:

Type Description
Literal[True]

If value is a valid finnish SSN.

ValidationError

If value is an invalid finnish SSN.

Source code in src/validators/i18n/fi.py
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
@validator
def fi_ssn(value: str, /, *, allow_temporal_ssn: bool = True):
    """Validate a Finnish Social Security Number.

    This validator is based on [django-localflavor-fi][1].

    [1]: https://github.com/django/django-localflavor-fi/

    Examples:
        >>> fi_ssn('010101-0101')
        # Output: True
        >>> fi_ssn('101010-0102')
        # Output: ValidationError(func=fi_ssn, args=...)

    Args:
        value:
            Social Security Number to be validated.
        allow_temporal_ssn:
            Whether to accept temporal SSN numbers. Temporal SSN numbers are the
            ones where the serial is in the range [900-999]. By default temporal
            SSN numbers are valid.

    Returns:
        (Literal[True]): If `value` is a valid finnish SSN.
        (ValidationError): If `value` is an invalid finnish SSN.
    """
    if not value:
        return False
    ssn_check_marks = "0123456789ABCDEFHJKLMNPRSTUVWXY"
    if not (result := re.match(_ssn_pattern(ssn_check_marks), value)):
        return False
    gd = result.groupdict()
    checksum = int(gd["date"] + gd["serial"])
    return (
        int(gd["serial"]) >= 2
        and (allow_temporal_ssn or int(gd["serial"]) <= 899)
        and ssn_check_marks[checksum % len(ssn_check_marks)] == gd["checksum"]
    )

validators.i18n.fr_department(value)

Validate a french department number.

Examples:

>>> fr_department(20)  # can be an integer
# Output: True
>>> fr_department("20")
# Output: True
>>> fr_department("971")  # Guadeloupe
# Output: True
>>> fr_department("00")
# Output: ValidationError(func=fr_department, args=...)
>>> fr_department('2A')  # Corsica
# Output: True
>>> fr_department('2B')
# Output: True
>>> fr_department('2C')
# Output: ValidationError(func=fr_department, args=...)

Parameters:

Name Type Description Default
value Union[str, int]

French department number to validate.

required

Returns:

Type Description
Literal[True]

If value is a valid french department number.

ValidationError

If value is an invalid french department number.

Source code in src/validators/i18n/fr.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@validator
def fr_department(value: typing.Union[str, int]):
    """Validate a french department number.

    Examples:
        >>> fr_department(20)  # can be an integer
        # Output: True
        >>> fr_department("20")
        # Output: True
        >>> fr_department("971")  # Guadeloupe
        # Output: True
        >>> fr_department("00")
        # Output: ValidationError(func=fr_department, args=...)
        >>> fr_department('2A')  # Corsica
        # Output: True
        >>> fr_department('2B')
        # Output: True
        >>> fr_department('2C')
        # Output: ValidationError(func=fr_department, args=...)

    Args:
        value:
            French department number to validate.

    Returns:
        (Literal[True]): If `value` is a valid french department number.
        (ValidationError): If `value` is an invalid french department number.
    """
    if not value:
        return False
    if isinstance(value, str):
        if value in ("2A", "2B"):  # Corsica
            return True
        try:
            value = int(value)
        except ValueError:
            return False
    return 1 <= value <= 19 or 21 <= value <= 95 or 971 <= value <= 976  # Overseas departments

validators.i18n.fr_ssn(value)

Validate a french Social Security Number.

Each french citizen has a distinct Social Security Number. For more information see French Social Security Number (sadly unavailable in english).

Examples:

>>> fr_ssn('1 84 12 76 451 089 46')
# Output: True
>>> fr_ssn('1 84 12 76 451 089')  # control key is optional
# Output: True
>>> fr_ssn('3 84 12 76 451 089 46')  # wrong gender number
# Output: ValidationError(func=fr_ssn, args=...)
>>> fr_ssn('1 84 12 76 451 089 47')  # wrong control key
# Output: ValidationError(func=fr_ssn, args=...)

Parameters:

Name Type Description Default
value str

French Social Security Number string to validate.

required

Returns:

Type Description
Literal[True]

If value is a valid french Social Security Number.

ValidationError

If value is an invalid french Social Security Number.

Source code in src/validators/i18n/fr.py
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
@validator
def fr_ssn(value: str):
    """Validate a french Social Security Number.

    Each french citizen has a distinct Social Security Number.
    For more information see [French Social Security Number][1] (sadly unavailable in english).

    [1]: https://fr.wikipedia.org/wiki/Num%C3%A9ro_de_s%C3%A9curit%C3%A9_sociale_en_France

    Examples:
        >>> fr_ssn('1 84 12 76 451 089 46')
        # Output: True
        >>> fr_ssn('1 84 12 76 451 089')  # control key is optional
        # Output: True
        >>> fr_ssn('3 84 12 76 451 089 46')  # wrong gender number
        # Output: ValidationError(func=fr_ssn, args=...)
        >>> fr_ssn('1 84 12 76 451 089 47')  # wrong control key
        # Output: ValidationError(func=fr_ssn, args=...)

    Args:
        value:
            French Social Security Number string to validate.

    Returns:
        (Literal[True]): If `value` is a valid french Social Security Number.
        (ValidationError): If `value` is an invalid french Social Security Number.
    """
    if not value:
        return False
    matched = re.match(_ssn_pattern(), value)
    if not matched:
        return False
    groups = list(matched.groups())
    control_key = groups[-1]
    department = groups[3]
    if department != "99" and not fr_department(department):
        # 99 stands for foreign born people
        return False
    if control_key is None:
        # no control key provided, no additional check needed
        return True
    if len(department) == len(groups[4]):
        # if the department number is 3 digits long (overseas departments),
        # the town number must be 2 digits long
        # and vice versa
        return False
    if department in ("2A", "2B"):
        # Corsica's department numbers are not in the same range as the others
        # thus 2A and 2B are replaced by 19 and 18 respectively to compute the control key
        groups[3] = "19" if department == "2A" else "18"
    # the control key is valid if it is equal to 97 - (the first 13 digits modulo 97)
    digits = int("".join(groups[:-1]))
    return int(control_key) == (97 - (digits % 97))

validators.i18n.ind_aadhar(value)

Validate an indian aadhar card number.

Examples:

>>> ind_aadhar('3675 9834 6015')
True
>>> ind_aadhar('3675 ABVC 2133')
ValidationFailure(func=aadhar, args={'value': '3675 ABVC 2133'})

Parameters:

Name Type Description Default
value str

Aadhar card number string to validate.

required

Returns:

Type Description
Literal[True]

If value is a valid aadhar card number.

ValidationError

If value is an invalid aadhar card number.

Source code in src/validators/i18n/ind.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@validator
def ind_aadhar(value: str):
    """Validate an indian aadhar card number.

    Examples:
        >>> ind_aadhar('3675 9834 6015')
        True
        >>> ind_aadhar('3675 ABVC 2133')
        ValidationFailure(func=aadhar, args={'value': '3675 ABVC 2133'})

    Args:
        value: Aadhar card number string to validate.

    Returns:
        (Literal[True]): If `value` is a valid aadhar card number.
        (ValidationError): If `value` is an invalid aadhar card number.
    """
    return re.match(r"^[2-9]{1}\d{3}\s\d{4}\s\d{4}$", value)

validators.i18n.ind_pan(value)

Validate a pan card number.

Examples:

>>> ind_pan('ABCDE9999K')
True
>>> ind_pan('ABC5d7896B')
ValidationFailure(func=pan, args={'value': 'ABC5d7896B'})

Parameters:

Name Type Description Default
value str

PAN card number string to validate.

required

Returns:

Type Description
Literal[True]

If value is a valid PAN card number.

ValidationError

If value is an invalid PAN card number.

Source code in src/validators/i18n/ind.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@validator
def ind_pan(value: str):
    """Validate a pan card number.

    Examples:
        >>> ind_pan('ABCDE9999K')
        True
        >>> ind_pan('ABC5d7896B')
        ValidationFailure(func=pan, args={'value': 'ABC5d7896B'})

    Args:
        value: PAN card number string to validate.

    Returns:
        (Literal[True]): If `value` is a valid PAN card number.
        (ValidationError): If `value` is an invalid PAN card number.
    """
    return re.match(r"[A-Z]{5}\d{4}[A-Z]{1}", value)