Skip to main content

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

PyPI version Python Downloads Licencia Estilo de código Integración continua

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

  • 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 seguroRut.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 estaticopy.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

Este proyecto se inspiro en rut-chile de gevalenz.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rutificador-1.5.8.tar.gz (38.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rutificador-1.5.8-py3-none-any.whl (44.9 kB view details)

Uploaded Python 3

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

Hashes for rutificador-1.5.8.tar.gz
Algorithm Hash digest
SHA256 e98f3fad2a216a5462ee09d1f8bdfcbdf91f2effa6f97643b84165920c9fb9f3
MD5 b51fbe3e6c088d70d67b30785f3aff51
BLAKE2b-256 6573c14330d8fed28c6f71134b5f435518fe4ded25fd2b6a136b587bf2e25150

See more details on using hashes here.

Provenance

The following attestation bundles were made for rutificador-1.5.8.tar.gz:

Publisher: publish-package.yml on cortega26/rutificador

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for rutificador-1.5.8-py3-none-any.whl
Algorithm Hash digest
SHA256 c700022dedc41cc12edd46b5797d7462b725da58f193ea92b20e3f14f8141438
MD5 a662cc894d7f5b606f1fa6a9f1564e21
BLAKE2b-256 33044c1362d457e81a6bf1fcb415ac2e3d6499b0e10daf14e866173761681856

See more details on using hashes here.

Provenance

The following attestation bundles were made for rutificador-1.5.8-py3-none-any.whl:

Publisher: publish-package.yml on cortega26/rutificador

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page