81 lines
2.0 KiB
Python
81 lines
2.0 KiB
Python
"""Registro de reglas de limpieza.
|
|
|
|
Para agregar una regla nueva:
|
|
1. Implementa ``fn(series: pd.Series) -> pd.Series`` (o passthrough si es especial).
|
|
2. Llama a ``register_rule(...)`` en ``rules/builtins.py``.
|
|
3. Si la regla es especial (añade columnas, usa config), maneja el id en ``apply.py``.
|
|
4. Incluye el id en ``_applicable_rules_for_type`` (type_inference.py) si debe sugerirse.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Any, Callable, Optional
|
|
|
|
import pandas as pd
|
|
|
|
RuleFn = Callable[[pd.Series], pd.Series]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class RuleSpec:
|
|
id: str
|
|
name: str
|
|
description: str
|
|
fn: RuleFn
|
|
|
|
def as_dict(self) -> dict[str, Any]:
|
|
return {
|
|
"id": self.id,
|
|
"name": self.name,
|
|
"description": self.description,
|
|
"fn": self.fn,
|
|
}
|
|
|
|
|
|
_REGISTRY: dict[str, RuleSpec] = {}
|
|
_ORDER: list[str] = []
|
|
|
|
|
|
def register_rule(
|
|
rule_id: str,
|
|
*,
|
|
name: str,
|
|
description: str,
|
|
fn: RuleFn,
|
|
) -> RuleSpec:
|
|
"""Registra una regla. Si el id ya existe, lo reemplaza manteniendo el orden."""
|
|
spec = RuleSpec(id=rule_id, name=name, description=description, fn=fn)
|
|
if rule_id not in _REGISTRY:
|
|
_ORDER.append(rule_id)
|
|
_REGISTRY[rule_id] = spec
|
|
return spec
|
|
|
|
|
|
def get_rule(rule_id: str) -> Optional[dict[str, Any]]:
|
|
spec = _REGISTRY.get(rule_id)
|
|
return spec.as_dict() if spec else None
|
|
|
|
|
|
def get_rule_fn(rule_id: str) -> Optional[RuleFn]:
|
|
spec = _REGISTRY.get(rule_id)
|
|
return spec.fn if spec else None
|
|
|
|
|
|
def get_rule_name(rule_id: str) -> str:
|
|
spec = _REGISTRY.get(rule_id)
|
|
return spec.name if spec else rule_id
|
|
|
|
|
|
def list_rules() -> list[dict[str, Any]]:
|
|
return [_REGISTRY[rid].as_dict() for rid in _ORDER if rid in _REGISTRY]
|
|
|
|
|
|
# Compat: lista mutable usada por la API (se rellena al importar builtins).
|
|
CLEANING_RULES: list[dict[str, Any]] = []
|
|
|
|
|
|
def rebuild_cleaning_rules() -> list[dict[str, Any]]:
|
|
CLEANING_RULES.clear()
|
|
CLEANING_RULES.extend(list_rules())
|
|
return CLEANING_RULES
|