Python Data Validation for Humans™ - comprehensive validation library for various data types without schema definitions
Validators for country-specific personal and business identifiers. These validators implement local validation rules, check digits, and format requirements for national identification systems.
Validators for Spanish national identification documents and tax codes.
def es_cif(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate Spanish CIF (Código de Identificación Fiscal) - company tax ID.
Parameters:
- value: CIF string to validate
Returns:
True if valid CIF, ValidationError otherwise
Format: 8 characters + 1 check digit
- First character: Letter indicating organization type (A-N, P, Q, R, S, W)
- Next 7 characters: Numbers
- Last character: Check digit (letter or number)
Used for companies, associations, and other entities in Spain.
"""
def es_nif(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate Spanish NIF (Número de Identificación Fiscal) - personal tax ID.
Parameters:
- value: NIF string to validate
Returns:
True if valid NIF, ValidationError otherwise
Format: 8 digits + 1 check letter
- 8 digits: Personal identification number
- 1 letter: Check letter calculated from the digits
Used for Spanish nationals and residents.
"""
def es_nie(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate Spanish NIE (Número de Identidad de Extranjero) - foreigner ID.
Parameters:
- value: NIE string to validate
Returns:
True if valid NIE, ValidationError otherwise
Format: 1 letter + 7 digits + 1 check letter
- First letter: X, Y, or Z
- 7 digits: Sequential number
- Check letter: Calculated from the number
Used for foreigners with legal residence in Spain.
"""
def es_doi(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate Spanish DOI (Documento de Identidad) - any Spanish digital identity.
Parameters:
- value: DOI string to validate
Returns:
True if valid DOI, ValidationError otherwise
Validates any of: NIF, NIE, or CIF
Used as a general validator for Spanish identification documents.
"""Validators for Finnish national identification and business codes.
def fi_business_id(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate Finnish business ID (Y-tunnus).
Parameters:
- value: Finnish business ID string to validate
Returns:
True if valid business ID, ValidationError otherwise
Format: 7 digits + hyphen + 1 check digit
- Example: 1234567-8
- Check digit calculated using modulo 11 algorithm
Used for all Finnish companies and organizations.
"""
def fi_ssn(value: str, /, *, allow_temporal_ssn: bool = True) -> Union[Literal[True], ValidationError]:
"""
Validate Finnish Social Security Number (Henkilötunnus).
Parameters:
- value: Finnish SSN string to validate
- allow_temporal_ssn: Allow temporal SSNs (900-999 birth numbers)
Returns:
True if valid SSN, ValidationError otherwise
Format: DDMMYY-NNNC or DDMMYY+NNNC or DDMMYYANNC
- DDMMYY: Birth date
- Separator: - (1900s), + (1800s), A (2000s)
- NNN: Individual number (002-899 normal, 900-999 temporal)
- C: Check character
Used for all Finnish residents.
"""Validators for French national codes and administrative identifiers.
def fr_department(value: Union[str, int], /) -> Union[Literal[True], ValidationError]:
"""
Validate French department numbers.
Parameters:
- value: Department number (string or integer)
Returns:
True if valid department number, ValidationError otherwise
Validates French administrative department codes:
- Metropolitan France: 01-95 (excluding 20)
- Corsica: 2A, 2B (or 201, 202)
- Overseas departments: 971, 972, 973, 974, 976
- Overseas collectivities: 975, 977, 978, 984-988
"""
def fr_ssn(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate French Social Security Number (Numéro de Sécurité Sociale).
Parameters:
- value: French SSN string to validate
Returns:
True if valid SSN, ValidationError otherwise
Format: 15 digits (often displayed with spaces as groups)
- 1 digit: Gender (1=male, 2=female, 7-8=temporary)
- 2 digits: Birth year (last 2 digits)
- 2 digits: Birth month (01-12)
- 2 digits: Birth department
- 3 digits: Birth commune
- 3 digits: Birth order number
- 2 digits: Check digits (97 - (first 13 digits mod 97))
Also known as INSEE number.
"""Validators for Indian national identification documents.
def ind_aadhar(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate Indian Aadhar card numbers.
Parameters:
- value: Aadhar number string to validate
Returns:
True if valid Aadhar number, ValidationError otherwise
Format: 12 digits
- No leading zeros in first digit
- Uses Verhoeff check digit algorithm
- Example: 1234 5678 9012
Unique identification number for Indian residents.
"""
def ind_pan(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate Indian PAN (Permanent Account Number) card numbers.
Parameters:
- value: PAN string to validate
Returns:
True if valid PAN, ValidationError otherwise
Format: 10 characters (AAAAA9999A)
- First 5: Letters
- Next 4: Digits
- Last 1: Letter (check character)
- Example: ABCDE1234F
Used for tax identification in India.
"""Validators for Russian tax and business identifiers.
def ru_inn(value: str, /) -> Union[Literal[True], ValidationError]:
"""
Validate Russian INN (Individual Taxpayer Number).
Parameters:
- value: INN string to validate
Returns:
True if valid INN, ValidationError otherwise
Formats:
- 10 digits: Legal entities (companies)
- 12 digits: Individual taxpayers
Uses specific check digit algorithms for validation.
Required for all Russian taxpayers.
"""import validators
# Spanish identifiers
validators.es_nif('12345678Z') # True (personal tax ID)
validators.es_nie('X1234567L') # True (foreigner ID)
validators.es_cif('A12345674') # True (company tax ID)
validators.es_doi('12345678Z') # True (validates any Spanish ID)
# Finnish identifiers
validators.fi_business_id('1234567-8') # True
validators.fi_ssn('311280-999J') # True
validators.fi_ssn('311280-999J', allow_temporal_ssn=False) # May be False if temporal
# French identifiers
validators.fr_department('75') # True (Paris)
validators.fr_department(75) # True (accepts int)
validators.fr_department('2A') # True (Corsica)
validators.fr_ssn('123456789012345') # True (if valid checksum)
# Indian identifiers
validators.ind_aadhar('123456789012') # True (if valid Verhoeff check)
validators.ind_pan('ABCDE1234F') # True
# Russian identifiers
validators.ru_inn('1234567890') # True (10-digit legal entity)
validators.ru_inn('123456789012') # True (12-digit individual)import validators
def validate_national_id(country: str, id_value: str) -> dict:
"""Validate national ID based on country."""
country_validators = {
'ES': {
'nif': validators.es_nif,
'nie': validators.es_nie,
'cif': validators.es_cif,
'any': validators.es_doi
},
'FI': {
'ssn': validators.fi_ssn,
'business': validators.fi_business_id
},
'FR': {
'ssn': validators.fr_ssn,
},
'IN': {
'aadhar': validators.ind_aadhar,
'pan': validators.ind_pan
},
'RU': {
'inn': validators.ru_inn
}
}
if country not in country_validators:
return {'supported': False, 'results': {}}
results = {}
for id_type, validator in country_validators[country].items():
results[id_type] = bool(validator(id_value))
return {
'supported': True,
'results': results,
'any_valid': any(results.values())
}
# Usage
result = validate_national_id('ES', '12345678Z')
print(f"Spanish ID validation: {result}")import validators
def detect_id_format(id_value: str) -> list:
"""Detect possible ID formats for a given value."""
possible_formats = []
# Test against all available validators
validators_to_test = [
('Spanish NIF', validators.es_nif),
('Spanish NIE', validators.es_nie),
('Spanish CIF', validators.es_cif),
('Finnish SSN', validators.fi_ssn),
('Finnish Business', validators.fi_business_id),
('French SSN', validators.fr_ssn),
('Indian Aadhar', validators.ind_aadhar),
('Indian PAN', validators.ind_pan),
('Russian INN', validators.ru_inn),
]
for format_name, validator in validators_to_test:
if validator(id_value):
possible_formats.append(format_name)
return possible_formats
# Usage
test_ids = [
'12345678Z', # Spanish NIF format
'X1234567L', # Spanish NIE format
'1234567-8', # Finnish business ID format
'ABCDE1234F', # Indian PAN format
]
for test_id in test_ids:
formats = detect_id_format(test_id)
print(f"{test_id}: {formats}")import validators
# Batch validation example
identifiers = [
('ES', 'NIF', '12345678Z'),
('FI', 'SSN', '311280-999J'),
('IN', 'PAN', 'ABCDE1234F'),
('RU', 'INN', '1234567890'),
]
for country, type_name, id_value in identifiers:
# Try to validate based on country and type
is_valid = False
if country == 'ES' and type_name == 'NIF':
is_valid = bool(validators.es_nif(id_value))
elif country == 'FI' and type_name == 'SSN':
is_valid = bool(validators.fi_ssn(id_value))
elif country == 'IN' and type_name == 'PAN':
is_valid = bool(validators.ind_pan(id_value))
elif country == 'RU' and type_name == 'INN':
is_valid = bool(validators.ru_inn(id_value))
print(f"{country} {type_name} {id_value}: {'✓' if is_valid else '✗'}")Install with Tessl CLI
npx tessl i tessl/pypi-validators