Herramientas para validar, calcular y formatear el Rol Único Tributario (RUT) en Chile, con procesamiento por lotes y salida en múltiples formatos.
Project description
Rutificador
Biblioteca Python para validar, calcular y formatear el Rol Unico Tributario (RUT) chileno. Sin dependencias externas, tipado estatico completo, y soporte para procesamiento por lotes, streaming, CLI, e integraciones opcionales con Pydantic v2, FastAPI, pandas y polars.
from rutificador import Rut
rut = Rut("12.345.678-5")
print(rut.formatear(separador_miles=True)) # 12.345.678-5
resultado = Rut.parse("12.345.678-9")
print(resultado.estado, resultado.codigo_error) # invalido DV_DISCORDANTE
Tabla de Contenidos
- Caracteristicas
- Instalacion
- Uso basico
- Linea de comandos
- Procesamiento por lotes
- Integraciones
- Validacion avanzada
- Referencia de errores
- Registro y depuracion
- API de referencia
- Desarrollo
- Licencia
Caracteristicas
- Cero dependencias base — solo estandar de Python. Instalacion liviana y segura.
- Validacion completa — formato, digito verificador, longitud configurable, modos de rigor.
- Formateo flexible — separador de miles, mayusculas en DV, separador personalizado.
- Streaming y lotes — archivos de millones de lineas sin cargar todo en memoria.
- Procesamiento en paralelo — motor por procesos (CPU-bound) o hilos (I/O-bound).
- Parseo seguro —
Rut.parse()nunca lanza excepcion, siempre retorna resultado estructurado. - Enmascaramiento y tokenizacion — protege datos sensibles en logs, exports o pantallas.
- Motor de sugerencias — correccion fuzzy de errores tipograficos comunes.
- Integraciones opcionales — Pydantic v2, FastAPI, pandas, polars.
- Tipado estatico —
py.typed(PEP 561), cobertura mypy completa. - CLI profesional — salida en text, JSON, JSONL, CSV y XML.
Instalacion
pip install rutificador
Con extras:
pip install rutificador[pydantic] # Pydantic v2
pip install rutificador[fastapi] # FastAPI + Pydantic
pip install rutificador[pandas] # pandas accessor
pip install rutificador[polars] # polars namespace
pip install rutificador[full] # todo lo anterior
Uso basico
Validacion y parseo
from rutificador import Rut
# Creacion directa — valida en el constructor (lanza excepcion si es invalido)
rut = Rut("12.345.678-5")
# Parseo seguro — nunca lanza excepcion, siempre retorna resultado estructurado
resultado = Rut.parse("12.345.678-5")
print(resultado.estado) # valido
print(resultado.normalizado) # 12345678-5
resultado = Rut.parse("12.345.678-9")
print(resultado.estado) # invalido
print(resultado.codigo_error) # DV_DISCORDANTE
# Capturar error en validacion directa
from rutificador.exceptions import ErrorValidacionRut
try:
Rut("12.345.678-9")
except ErrorValidacionRut as e:
print(e.codigo_error) # DV_DISCORDANTE
Formateo
rut = Rut("12345678-5")
print(rut.formatear()) # 12345678-5
print(rut.formatear(separador_miles=True)) # 12.345.678-5
print(rut.formatear(mayusculas=True)) # 12345678-5
print(rut.formatear(separador_miles=True, mayusculas=True)) # 12.345.678-5
# Con DV en 'k'
rut_k = Rut("12345670-k")
print(rut_k.formatear(separador_miles=True, mayusculas=True)) # 12.345.670-K
Calculo del digito verificador
from rutificador import calcular_digito_verificador
dv = calcular_digito_verificador("12345678")
print(dv) # 5
Enmascaramiento
from rutificador import Rut
# Ofuscar parcialmente
print(Rut.enmascarar("12.345.678-5", mantener=3, caracter="X")) # XXXXX678-5
print(Rut.enmascarar("12.345.678-5", mantener=4)) # ****5678-5
# Tokenizacion
print(Rut.enmascarar("12.345.678-5", modo="token", clave="mi-clave")) # tok_abc123...
Sugerencias y autocorreccion
from rutificador import Rut
# Sugerir correcciones para un RUT con error tipografico
sugerencias = Rut.sugerir("12.345.687-5")
print(sugerencias) # ['12345678-5', ...]
# Autocorreccion inteligente
mejor_opcion = Rut.mejorar("12a345678-k")
print(mejor_opcion) # 12345678-5
Linea de comandos
# Validar desde un archivo
rutificador validar ruts.txt
# Validar desde stdin
cat ruts.txt | rutificador validar
# Formatear con separador de miles
rutificador formatear ruts.txt --separador-miles --mayusculas
# Enmascarar datos sensibles
rutificador enmascarar ruts.txt --mantener 3
# Salida estructurada
rutificador validar ruts.txt --format jsonl > resultados.jsonl
# Procesamiento paralelo
rutificador validar ruts_pesados.txt --paralelo --format csv
# Autocorreccion + sugerencias
rutificador validar sucia_db.txt --mejorar --sugerir
# Informacion del sistema
rutificador info
Comandos
| Comando | Descripcion |
|---|---|
validar |
Valida RUTs desde archivo o stdin |
formatear |
Valida y formatea RUTs con opciones de salida |
enmascarar |
Ofusca/tokeniza RUTs para proteger datos sensibles |
info |
Muestra version, entorno y funcionalidades |
Formatos de salida
| Formato | Descripcion |
|---|---|
text |
Legible por humanos con resumen de auditoria en stderr |
json |
Array JSON estandar (OOM-Safe via streaming) |
jsonl |
Una linea por registro — ideal para Big Data |
csv |
Hoja de calculo con cabecera |
xml |
Estructura incremental para integraciones legacy |
Procesamiento por lotes
from rutificador import ProcesadorLotesRut
ruts = ['12.345.678-5', '98.765.432-1', '1-9']
procesador = ProcesadorLotesRut()
resultado = procesador.validar_lista_ruts(ruts)
print(len(resultado.detalles_validos)) # 2
print(len(resultado.detalles_invalidos)) # 1
# Formatear a JSON, CSV o XML
csv = procesador.formatear_lista_ruts(ruts, formato="csv")
print(csv)
# rut
# 12345678-5
# ...
# Paralelismo explicito
procesador = ProcesadorLotesRut(motor_paralelo="process")
resultado = procesador.validar_lista_ruts(ruts, paralelo=True)
Streaming (archivos grandes)
from rutificador import validar_flujo_ruts, formatear_flujo_ruts
# Validar millones de RUTs sin cargar todo en memoria
ruts = (linea.strip() for linea in open("muy_grande.txt"))
for es_valido, resultado in validar_flujo_ruts(ruts):
if es_valido:
print(resultado.valor)
Integraciones
Pydantic v2
pip install rutificador[pydantic]
from pydantic import BaseModel
from rutificador.contrib.pydantic import RutStr, rut_str_annotated
class Usuario(BaseModel):
rut: RutStr
u = Usuario(rut="12.345.678-5")
print(u.rut) # 12345678-5
# Formato especifico
RutConPuntos = rut_str_annotated(formato="miles-con-guion")
class UsuarioV2(BaseModel):
rut: RutConPuntos
u2 = UsuarioV2(rut="12.345.678-5")
print(u2.rut) # 12.345.678-5
FastAPI
pip install rutificador[fastapi]
from fastapi import FastAPI, Depends
from rutificador import Rut
from rutificador.contrib.fastapi import parametro_rut
app = FastAPI()
@app.get("/usuario/{rut}")
def obtener_usuario(rut: Rut = Depends(parametro_rut)):
return {"rut_normalizado": str(rut), "dv": rut.digito_verificador}
Los errores de validacion retornan 422 Unprocessable Entity con codigo estructurado (DV_DISCORDANTE, CARACTERES_INVALIDOS, etc.).
pandas
pip install rutificador[pandas]
import pandas as pd
import rutificador.pandas # activa el accessor .rut
s = pd.Series(["12.345.678-5", "12.345.678-9", "invalid"])
print(s.rut.es_valido())
# 0 True
# 1 False
# 2 False
print(s.rut.formatear(formato="miles"))
# 0 12.345.678-5
# 1 None
# 2 None
polars
pip install rutificador[polars]
import polars as pl
import rutificador.polars # activa el namespace .rut
df = pl.DataFrame({"rut": ["12.345.678-5", "12.345.678-9", "invalid"]})
print(df.with_columns(pl.col("rut").rut.es_valido()))
Validacion avanzada
from rutificador import Rut, ValidadorRut
from rutificador.config import RigorValidacion, ConfiguracionRut
# Modo flexible: tolera espacios, guiones extra, etc.
validador = ValidadorRut(modo=RigorValidacion.FLEXIBLE)
rut = Rut('12 345 678-5', validador=validador)
# Configuracion avanzada
config = ConfiguracionRut(max_digitos=10)
validador = ValidadorRut(configuracion=config)
# Normalizacion con rigor flexible
normalizado, errores, advertencias = Rut.normalizar(
"12 345 678-5", modo=RigorValidacion.FLEXIBLE
)
print(normalizado) # 12345678-5
Referencia de errores
Todos los errores tienen codigos estables y severidad explicita:
from rutificador import Rut
res = Rut.parse("12..345")
for err in res.errores:
print(err.codigo, err.severidad, err.hint)
Errores
| Codigo | Descripcion |
|---|---|
ERROR_TIPO |
Tipo invalido |
RUT_VACIO |
Entrada vacia |
CARACTERES_INVALIDOS |
Caracteres no permitidos |
FORMATO_PUNTOS |
Separadores de miles invalidos |
FORMATO_GUION |
Guion invalido |
LONGITUD_MINIMA |
Longitud minima no alcanzada |
LONGITUD_MAXIMA |
Longitud maxima excedida |
DV_INVALIDO |
Digito verificador invalido |
DV_DISCORDANTE |
DV no coincide |
ESTADO_ENMASCARADO |
Enmascarado en estado no valido |
CLAVE_TOKEN_REQUERIDA |
Falta clave de tokenizacion |
Advertencias
| Codigo | Descripcion |
|---|---|
NORMALIZACION_ESPACIOS |
Espacios eliminados |
NORMALIZACION_GUION |
Guion normalizado |
NORMALIZACION_PUNTOS |
Puntos eliminados |
NORMALIZACION_DV |
DV en minuscula |
CEROS_IZQUIERDA |
Ceros a la izquierda eliminados |
Registro y depuracion
import logging
from rutificador import configurar_registro
configurar_registro(level=logging.DEBUG)
Con handler personalizado:
import logging
import json
from rutificador import configurar_registro
class JsonFormatter(logging.Formatter):
def format(self, record):
return json.dumps({"nivel": record.levelname, "mensaje": record.getMessage()})
handler = logging.StreamHandler()
handler.setFormatter(JsonFormatter())
configurar_registro(level=logging.INFO, handler=handler)
API de referencia
Metadatos de validacion
from rutificador import ProcesadorLotesRut
procesador = ProcesadorLotesRut()
resultado = procesador.validar_lista_ruts(["12.345.678-5"], paralelo=False)
detalle = resultado.detalles_validos[0]
print(detalle.valor) # 12345678-5
print(detalle.validador_modo) # estricto/flexible
print(detalle.duracion) # segundos consumidos en la validacion
# Errores con codigo estructurado
resultado_error = procesador.validar_lista_ruts(["12345678-9"])
problema = resultado_error.ruts_invalidos[0]
print(problema.rut, problema.codigo, problema.mensaje)
Evaluar rendimiento
from rutificador import evaluar_rendimiento
resultados = evaluar_rendimiento(num_ruts=1000)
print(resultados['tasa_exito'])
Formateador personalizado
from rutificador.formatter import FormateadorRut, FabricaFormateadorRut
class FormateadorLista(FormateadorRut):
def formatear(self, ruts):
return ','.join(ruts)
FabricaFormateadorRut.registrar_formateador('lista', FormateadorLista)
Desarrollo
Entorno
git clone https://github.com/cortega26/rutificador.git
cd rutificador
python -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt
pip install -e .
pre-commit install
Calidad
pytest -W error::DeprecationWarning # Tests sin deprecaciones
mypy rutificador/ # Tipado estatico
ruff check . # Lint
ruff format . --check # Formato
bandit -r rutificador/ # Seguridad
Las contribuciones son bienvenidas. Revisa CONTRIBUTING.md para las directrices completas.
Alcance
Rutificador no verifica la existencia del RUT en registros oficiales ni realiza enriquecimiento de identidad. Su alcance es la validacion sintactica, normalizacion y formateo segun las reglas locales del RUT chileno.
Licencia
MIT © Carlos Ortega Gonzalez. Ver LICENSE.
Creditos
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rutificador-1.5.8.tar.gz.
File metadata
- Download URL: rutificador-1.5.8.tar.gz
- Upload date:
- Size: 38.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e98f3fad2a216a5462ee09d1f8bdfcbdf91f2effa6f97643b84165920c9fb9f3
|
|
| MD5 |
b51fbe3e6c088d70d67b30785f3aff51
|
|
| BLAKE2b-256 |
6573c14330d8fed28c6f71134b5f435518fe4ded25fd2b6a136b587bf2e25150
|
Provenance
The following attestation bundles were made for rutificador-1.5.8.tar.gz:
Publisher:
publish-package.yml on cortega26/rutificador
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rutificador-1.5.8.tar.gz -
Subject digest:
e98f3fad2a216a5462ee09d1f8bdfcbdf91f2effa6f97643b84165920c9fb9f3 - Sigstore transparency entry: 1542991565
- Sigstore integration time:
-
Permalink:
cortega26/rutificador@a6765ddda4ccfab5321b3a056a15701624e682c3 -
Branch / Tag:
refs/tags/v1.5.8 - Owner: https://github.com/cortega26
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-package.yml@a6765ddda4ccfab5321b3a056a15701624e682c3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rutificador-1.5.8-py3-none-any.whl.
File metadata
- Download URL: rutificador-1.5.8-py3-none-any.whl
- Upload date:
- Size: 44.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c700022dedc41cc12edd46b5797d7462b725da58f193ea92b20e3f14f8141438
|
|
| MD5 |
a662cc894d7f5b606f1fa6a9f1564e21
|
|
| BLAKE2b-256 |
33044c1362d457e81a6bf1fcb415ac2e3d6499b0e10daf14e866173761681856
|
Provenance
The following attestation bundles were made for rutificador-1.5.8-py3-none-any.whl:
Publisher:
publish-package.yml on cortega26/rutificador
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rutificador-1.5.8-py3-none-any.whl -
Subject digest:
c700022dedc41cc12edd46b5797d7462b725da58f193ea92b20e3f14f8141438 - Sigstore transparency entry: 1542991988
- Sigstore integration time:
-
Permalink:
cortega26/rutificador@a6765ddda4ccfab5321b3a056a15701624e682c3 -
Branch / Tag:
refs/tags/v1.5.8 - Owner: https://github.com/cortega26
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-package.yml@a6765ddda4ccfab5321b3a056a15701624e682c3 -
Trigger Event:
push
-
Statement type: