Skip to content

Commit c8ef499

Browse files
committed
"Updated version number to 0.2.24, removed RutValidador class, and refactored Rut class to validate format and digit verifier internally."
1 parent d17b343 commit c8ef499

File tree

3 files changed

+59
-58
lines changed

3 files changed

+59
-58
lines changed

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "rutificador"
3-
version = "0.2.23"
3+
version = "0.2.24"
44
description = "Esta librería proporciona una implementación en Python para validar y formatear el Rol Único Tributario (RUT) utilizado en Chile."
55
authors = ["Carlos Ortega González <[email protected]>"]
66
license = "MIT"

rutificador/__init__.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@
88
Rut: Representa un RUT chileno, con métodos para validación y formateo.
99
RutDigitoVerificador: Calcula y representa el dígito verificador de un RUT chileno.
1010
RutInvalidoError: Excepción personalizada para errores de RUT inválido.
11-
RutValidador: Valida un RUT chileno.
1211
"""
1312

1413
from typing import List
1514

16-
__version__ = "0.2.23"
15+
__version__ = "0.2.24"
1716
__author__ = "Carlos Ortega González"
1817
__license__ = "MIT"
1918

20-
from .main import Rut, RutDigitoVerificador, RutInvalidoError, RutValidador
19+
from .main import Rut, RutDigitoVerificador, RutInvalidoError
2120

22-
__all__: List[str] = ["Rut", "RutDigitoVerificador", "RutInvalidoError", "RutValidador"]
21+
__all__: List[str] = ["Rut", "RutDigitoVerificador", "RutInvalidoError"]

rutificador/main.py

+55-53
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
# pylint: disable=missing-module-docstring
22

33
import re
4-
from typing import List, Tuple, Dict, Union
5-
from collections import deque
4+
from typing import List, Dict, Tuple, Union
65

76
FACTORES_DIGITO_VERIFICADOR: List[int] = [2, 3, 4, 5, 6, 7]
87
MODULO_DIGITO_VERIFICADOR: int = 11
@@ -18,9 +17,9 @@ class RutBase:
1817

1918
def __init__(self, base: str):
2019
self.rut_original: str = base
21-
self.base: str = self._validar_y_normalizar_base(base)
20+
self.base: str = self.validar_y_normalizar_base(base)
2221

23-
def _validar_y_normalizar_base(self, base: str) -> str:
22+
def validar_y_normalizar_base(self, base: str) -> str:
2423
"""
2524
Valida y normaliza el número base.
2625
@@ -53,20 +52,19 @@ class RutDigitoVerificador(RutBase):
5352

5453
def __init__(self, base: str):
5554
super().__init__(base)
56-
self.digito_verificador: str = self._calcular_digito_verificador()
55+
self.digito_verificador: str = self.calcular_digito_verificador()
5756

58-
def _calcular_digito_verificador(self) -> str:
57+
def calcular_digito_verificador(self) -> str:
5958
"""
6059
Calcula el dígito verificador del RUT.
6160
6261
Returns:
6362
str: El dígito verificador del RUT.
6463
"""
65-
factores = deque(FACTORES_DIGITO_VERIFICADOR)
6664
suma_parcial: int = sum(
67-
int(digito) * factores[0] for digito in reversed(str(self.base))
65+
int(digito) * FACTORES_DIGITO_VERIFICADOR[i % 6]
66+
for i, digito in enumerate(reversed(str(self.base)))
6867
)
69-
factores.rotate(-1)
7068
digito_verificador: int = (
7169
MODULO_DIGITO_VERIFICADOR - suma_parcial % MODULO_DIGITO_VERIFICADOR
7270
) % MODULO_DIGITO_VERIFICADOR
@@ -76,24 +74,6 @@ def __str__(self) -> str:
7674
return self.digito_verificador
7775

7876

79-
class RutValidador:
80-
"""Valida un RUT chileno."""
81-
82-
@staticmethod
83-
def validar_formato(rut: str) -> Tuple[bool, str]:
84-
"""Valida el formato del RUT."""
85-
match = re.fullmatch(RUT_REGEX, rut)
86-
if not match:
87-
return False, f"El formato del RUT '{rut}' es inválido."
88-
return True, match.group(1)
89-
90-
@staticmethod
91-
def validar_digito_verificador(base: str, digito: str) -> bool:
92-
"""Valida el dígito verificador del RUT."""
93-
digito_calculado = RutDigitoVerificador(base).digito_verificador
94-
return digito.lower() == digito_calculado
95-
96-
9777
class Rut:
9878
"""
9979
Representa un RUT chileno.
@@ -108,26 +88,37 @@ class Rut:
10888
formatear_lista_ruts: Formatea una lista de RUTs según las opciones especificadas.
10989
"""
11090

91+
PATRON_RUT = re.compile(RUT_REGEX)
92+
11193
def __init__(self, rut: str):
11294
self.rut_string: str = str(rut).strip()
113-
self._validar_rut()
95+
self._validar_formato_rut()
96+
self._validar_digito_verificador()
11497
self.base = RutBase(self.base_string)
11598
self.digito_verificador = RutDigitoVerificador(self.base_string)
11699

117-
def _validar_rut(self) -> None:
118-
"""Valida el formato y el dígito verificador del RUT."""
119-
es_valido, resultado = RutValidador.validar_formato(self.rut_string)
120-
if not es_valido:
121-
raise RutInvalidoError(resultado)
122-
123-
self.base_string = resultado
124-
match = re.fullmatch(RUT_REGEX, self.rut_string)
100+
def _validar_formato_rut(self) -> None:
101+
match = Rut.PATRON_RUT.fullmatch(self.rut_string)
102+
if not match:
103+
raise RutInvalidoError(
104+
f"El formato del RUT '{self.rut_string}' es inválido."
105+
)
106+
self.base_string: str = match.group(1)
107+
108+
def _validar_digito_verificador(self) -> None:
109+
match = Rut.PATRON_RUT.fullmatch(self.rut_string)
125110
digito_verificador_input = match.group(3).lower() if match.group(3) else None
126-
127-
if digito_verificador_input and not RutValidador.validar_digito_verificador(self.base_string, digito_verificador_input):
111+
digito_verificador_calculado = RutDigitoVerificador(
112+
self.base_string
113+
).digito_verificador
114+
115+
if (
116+
digito_verificador_input
117+
and digito_verificador_input != digito_verificador_calculado
118+
):
128119
raise RutInvalidoError(
129120
f"El dígito verificador '{digito_verificador_input}' no coincide con "
130-
f"el dígito verificador calculado '{self.digito_verificador}'."
121+
f"el dígito verificador calculado '{digito_verificador_calculado}'."
131122
)
132123

133124
def __str__(self) -> str:
@@ -152,7 +143,10 @@ def formatear(self, separador_miles: bool = False, mayusculas: bool = False) ->
152143
+ rut.split("-")[1]
153144
)
154145

155-
return rut.upper() if mayusculas else rut
146+
if mayusculas:
147+
rut = rut.upper()
148+
149+
return rut
156150

157151
@staticmethod
158152
def _agregar_separador_miles(numero: str) -> str:
@@ -172,22 +166,28 @@ def _validar_lista_ruts(ruts: List[str]) -> Dict[str, List[Union[str, Tuple[str,
172166

173167
@staticmethod
174168
def _formatear_csv(ruts_formateados: List[str]) -> str:
175-
return f"rut\n{chr(10).join(ruts_formateados)}"
169+
cadena_ruts: str = "\n".join(ruts_formateados)
170+
return f"rut\n{cadena_ruts}"
176171

177172
@staticmethod
178173
def _formatear_xml(ruts_formateados: List[str]) -> str:
179-
return "\n".join(["<root>"] + [f" <rut>{rut}</rut>" for rut in ruts_formateados] + ["</root>"])
174+
xml_lines: List[str] = ["<root>"]
175+
for rut in ruts_formateados:
176+
xml_lines.append(f" <rut>{rut}</rut>")
177+
xml_lines.append("</root>")
178+
return "\n".join(xml_lines)
180179

181180
@staticmethod
182181
def _formatear_json(ruts_formateados: List[str]) -> str:
183-
return str([{"rut": rut} for rut in ruts_formateados])
182+
ruts_json: List[Dict[str, str]] = [{"rut": rut} for rut in ruts_formateados]
183+
return str(ruts_json)
184184

185185
@staticmethod
186186
def formatear_lista_ruts(
187187
ruts: List[str],
188188
separador_miles: bool = False,
189189
mayusculas: bool = False,
190-
formato: Union[str, None] = None,
190+
formato=None,
191191
) -> str:
192192
"""
193193
Formatea una lista de RUTs según las opciones especificadas.
@@ -207,23 +207,25 @@ def formatear_lista_ruts(
207207
"xml": Rut._formatear_xml,
208208
"json": Rut._formatear_json,
209209
}
210-
ruts_validos_invalidos: Dict[str, List[Union[str, Tuple[str, str]]]] = Rut._validar_lista_ruts(ruts)
210+
ruts_validos_invalidos: Dict[str, List[str]] = Rut._validar_lista_ruts(ruts)
211211
ruts_validos: List[str] = ruts_validos_invalidos["validos"]
212212
ruts_invalidos: List[Tuple[str, str]] = ruts_validos_invalidos["invalidos"]
213213

214-
resultado: List[str] = []
214+
resultado: str = ""
215215
if ruts_validos:
216216
ruts_validos_formateados: List[str] = [
217217
Rut(rut).formatear(separador_miles, mayusculas) for rut in ruts_validos
218218
]
219-
resultado.append("RUTs válidos:")
220-
if formato in formato_salida:
221-
resultado.append(formato_salida[formato](ruts_validos_formateados))
219+
resultado += "RUTs válidos:\n"
220+
if formato in ("csv", "xml", "json"):
221+
resultado += formato_salida[formato](ruts_validos_formateados)
222222
else:
223-
resultado.extend(ruts_validos_formateados)
223+
resultado += "\n".join(ruts_validos_formateados)
224+
resultado += "\n\n"
224225

225226
if ruts_invalidos:
226-
resultado.append("\nRUTs inválidos:")
227-
resultado.extend(f"{rut} - {error}" for rut, error in ruts_invalidos)
227+
resultado += "RUTs inválidos:\n"
228+
for rut, error in ruts_invalidos:
229+
resultado += f"{rut} - {error}\n"
228230

229-
return "\n".join(resultado)
231+
return resultado

0 commit comments

Comments
 (0)