update bots
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
"""
|
||||
SSN provider for es_MX.
|
||||
|
||||
This module adds a provider for mexican SSN, along with Unique Population
|
||||
Registry Code (CURP) and Federal Taxpayer Registry ID (RFC).
|
||||
"""
|
||||
|
||||
import random
|
||||
import string
|
||||
|
||||
from typing import Literal, Optional
|
||||
|
||||
from .. import Provider as BaseProvider
|
||||
|
||||
ALPHABET = string.ascii_uppercase
|
||||
ALPHANUMERIC = string.digits + ALPHABET
|
||||
VOWELS = "AEIOU"
|
||||
CONSONANTS = [letter for letter in ALPHABET if letter not in VOWELS]
|
||||
|
||||
# https://es.wikipedia.org/wiki/Plantilla:Abreviaciones_de_los_estados_de_M%C3%A9xico
|
||||
STATES_RENAPO = [
|
||||
"AS",
|
||||
"BC",
|
||||
"BS",
|
||||
"CC",
|
||||
"CS",
|
||||
"CH",
|
||||
"DF",
|
||||
"CL",
|
||||
"CM",
|
||||
"DG",
|
||||
"GT",
|
||||
"GR",
|
||||
"HG",
|
||||
"JC",
|
||||
"MC",
|
||||
"MN",
|
||||
"MS",
|
||||
"NT",
|
||||
"NL",
|
||||
"OC",
|
||||
"PL",
|
||||
"QO",
|
||||
"QR",
|
||||
"SP",
|
||||
"SL",
|
||||
"SR",
|
||||
"TC",
|
||||
"TS",
|
||||
"TL",
|
||||
"VZ",
|
||||
"YN",
|
||||
"ZS",
|
||||
"NE", # Foreign Born
|
||||
]
|
||||
|
||||
FORBIDDEN_WORDS = {
|
||||
"BUEI": "BUEX",
|
||||
"BUEY": "BUEX",
|
||||
"CACA": "CACX",
|
||||
"CACO": "CACX",
|
||||
"CAGA": "CAGX",
|
||||
"CAGO": "CAGX",
|
||||
"CAKA": "CAKX",
|
||||
"CAKO": "CAKX",
|
||||
"COGE": "COGX",
|
||||
"COJA": "COJX",
|
||||
"COJE": "COJX",
|
||||
"COJI": "COJX",
|
||||
"COJO": "COJX",
|
||||
"CULO": "CULX",
|
||||
"FETO": "FETX",
|
||||
"GUEY": "GUEX",
|
||||
"JOTO": "JOTX",
|
||||
"KACA": "KACX",
|
||||
"KACO": "KACX",
|
||||
"KAGA": "KAGX",
|
||||
"KAGO": "KAGX",
|
||||
"KOGE": "KOGX",
|
||||
"KOJO": "KOJX",
|
||||
"KAKA": "KAKX",
|
||||
"KULO": "KULX",
|
||||
"MAME": "MAMX",
|
||||
"MAMO": "MAMX",
|
||||
"MEAR": "MEAX",
|
||||
"MEAS": "MEAX",
|
||||
"MEON": "MEOX",
|
||||
"MION": "MIOX",
|
||||
"MOCO": "MOCX",
|
||||
"MULA": "MULX",
|
||||
"PEDA": "PEDX",
|
||||
"PEDO": "PEDX",
|
||||
"PENE": "PENX",
|
||||
"PUTA": "PUTX",
|
||||
"PUTO": "PUTX",
|
||||
"QULO": "QULX",
|
||||
"RATA": "RATX",
|
||||
"RUIN": "RUIN",
|
||||
}
|
||||
|
||||
CURP_CHARACTERS = "0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"
|
||||
|
||||
|
||||
def _reduce_digits(number: int) -> int:
|
||||
"""
|
||||
Sum of digits of a number until sum becomes single digit.
|
||||
|
||||
Example:
|
||||
658 => 6 + 5 + 8 = 19 => 1 + 9 = 10 => 1
|
||||
"""
|
||||
if number == 0:
|
||||
return 0
|
||||
if number % 9 == 0:
|
||||
return 9
|
||||
|
||||
return number % 9
|
||||
|
||||
|
||||
def ssn_checksum(digits: map) -> int:
|
||||
"""
|
||||
Calculate the checksum for the mexican SSN (IMSS).
|
||||
"""
|
||||
return -sum(_reduce_digits(n * (i % 2 + 1)) for i, n in enumerate(digits)) % 10
|
||||
|
||||
|
||||
def curp_checksum(characters: str) -> int:
|
||||
"""
|
||||
Calculate the checksum for the mexican CURP.
|
||||
"""
|
||||
start = 18
|
||||
return -sum((start - i) * CURP_CHARACTERS.index(n) for i, n in enumerate(characters)) % 10
|
||||
|
||||
|
||||
class Provider(BaseProvider):
|
||||
"""
|
||||
A Faker provider for the Mexican SSN, RFC and CURP
|
||||
"""
|
||||
|
||||
ssn_formats = ("###########",)
|
||||
|
||||
def ssn(self) -> str:
|
||||
"""
|
||||
Mexican Social Security Number, as given by IMSS.
|
||||
|
||||
:return: a random Mexican SSN
|
||||
"""
|
||||
office = self.random_int(min=1, max=99)
|
||||
birth_year = self.random_int(min=0, max=99)
|
||||
start_year = self.random_int(min=0, max=99)
|
||||
serial = self.random_int(min=1, max=9999)
|
||||
|
||||
num = f"{office:02d}{start_year:02d}{birth_year:02d}{serial:04d}"
|
||||
|
||||
check = ssn_checksum(map(int, num))
|
||||
num += str(check)
|
||||
|
||||
return num
|
||||
|
||||
def curp(self) -> str:
|
||||
"""
|
||||
See https://es.wikipedia.org/wiki/Clave_%C3%9Anica_de_Registro_de_Poblaci%C3%B3n.
|
||||
|
||||
:return: a random Mexican CURP (Unique Population Registry Code)
|
||||
"""
|
||||
birthday = self.generator.date_of_birth()
|
||||
|
||||
first_surname = random.choice(ALPHABET) + random.choice(VOWELS)
|
||||
second_surname = random.choice(ALPHABET)
|
||||
given_name = random.choice(ALPHABET)
|
||||
name_initials = first_surname + second_surname + given_name
|
||||
|
||||
birth_date = birthday.strftime("%y%m%d")
|
||||
gender = random.choice("HM")
|
||||
state = random.choice(STATES_RENAPO)
|
||||
first_surname_inside = random.choice(CONSONANTS)
|
||||
second_surname_inside = random.choice(CONSONANTS)
|
||||
given_name_inside = random.choice(ALPHABET)
|
||||
|
||||
# This character is assigned to avoid duplicity
|
||||
# It's normally '0' for those born < 2000
|
||||
# and 'A' for those born >= 2000
|
||||
assigned_character = "0" if birthday.year < 2000 else "A"
|
||||
|
||||
name_initials = FORBIDDEN_WORDS.get(name_initials, name_initials)
|
||||
|
||||
random_curp = (
|
||||
name_initials
|
||||
+ birth_date
|
||||
+ gender
|
||||
+ state
|
||||
+ first_surname_inside
|
||||
+ second_surname_inside
|
||||
+ given_name_inside
|
||||
+ assigned_character
|
||||
)
|
||||
|
||||
random_curp += str(curp_checksum(random_curp))
|
||||
|
||||
return random_curp
|
||||
|
||||
def rfc(self, natural: bool = True) -> str:
|
||||
"""
|
||||
See https://es.wikipedia.org/wiki/Registro_Federal_de_Contribuyentes
|
||||
|
||||
:param natural: Whether to return the RFC of a natural person.
|
||||
Otherwise return the RFC of a legal person.
|
||||
:type natural: bool
|
||||
:return: a random Mexican RFC
|
||||
"""
|
||||
birthday = self.generator.date_of_birth()
|
||||
|
||||
if natural:
|
||||
first_surname = random.choice(ALPHABET) + random.choice(VOWELS)
|
||||
second_surname = random.choice(ALPHABET)
|
||||
given_name = random.choice(ALPHABET)
|
||||
name_initials = first_surname + second_surname + given_name
|
||||
name_initials = FORBIDDEN_WORDS.get(name_initials, name_initials)
|
||||
else:
|
||||
name_initials = (
|
||||
self.random_uppercase_letter() + self.random_uppercase_letter() + self.random_uppercase_letter()
|
||||
)
|
||||
|
||||
birth_date = birthday.strftime("%y%m%d")
|
||||
disambiguation_code = random.choice(ALPHANUMERIC) + random.choice(ALPHANUMERIC) + random.choice(ALPHANUMERIC)
|
||||
|
||||
random_rfc = name_initials + birth_date + disambiguation_code
|
||||
|
||||
return random_rfc
|
||||
|
||||
def elector_code(self, gender: Optional[Literal["H", "M"]] = None) -> str:
|
||||
"""
|
||||
Unique elector code issued by INE (Instituto Nacional Electoral) in Mexico.
|
||||
|
||||
:param gender: Gender for which to generate the code. Will be randomly
|
||||
selected if not provided.
|
||||
:type gender: str
|
||||
:return: a random INE elector code
|
||||
|
||||
:sample:
|
||||
:sample: gender='M'
|
||||
"""
|
||||
if gender and gender not in ("H", "M"):
|
||||
raise ValueError("Gender must be 'H' or 'M'")
|
||||
|
||||
gender = gender or random.choice(["H", "M"])
|
||||
|
||||
consonants = "".join(random.choices(CONSONANTS, k=6))
|
||||
|
||||
birthday = self.generator.date_of_birth()
|
||||
birth_date = birthday.strftime("%y%m%d")
|
||||
|
||||
entity = random.randint(1, 33)
|
||||
disambiguation_code = "".join(random.choices(string.digits, k=3))
|
||||
|
||||
return f"{consonants}{birth_date}{entity:02d}{gender}{disambiguation_code}"
|
||||
Binary file not shown.
Reference in New Issue
Block a user