Files
takana/scripts/mudanza/formatos/__init__.py
T
SergioandClaude Opus 5 3137d47f16 traducir: CENTRO de traducción con modelo pivote y plugins — N+M en vez de N×M
Traducir de a pares no escala: con nginx, apache, caddy, haproxy y lighttpd son 20 traductores, y
cada formato nuevo agrega 2N. Con un modelo intermedio son N lectores + M escritores: un formato
nuevo cuesta uno o dos plugins y estrena todos los pares de golpe.

**Probado, no argumentado**: el lector de apache se agregó SIN TOCAR el escritor de Caddy, y con eso
`apache → caddy` funciona sin que exista ningún traductor de ese par. Las dos salidas las valida el
caddy del propio corpus: `Valid configuration` en las dos.

Los plugins se DESCUBREN (`formatos/` + `@lector` / `@escritor`): una lista mantenida a mano se
desincroniza y el formato nuevo «no existe» sin que nada falle. `--list` dice qué pares habilita.

**El acta viaja DENTRO del modelo**, y es la decisión que hace que el pivote no mienta: si fuera un
efecto de cada traductor, lo que el LECTOR no entendió se perdería antes de llegar al escritor. El
escritor además puede agregarle — Caddy no tiene equivalente de `location ~`, así que en vez de
emitir un `handle` de prefijo que SE PARECE, lo manda al acta. Parecerse es peor que faltar.

Y un bug del lector de apache, encontrado probando: `ProxyPass` tiene dos formas y dentro de
`<Location>` lleva sólo la URL. Mirar sólo la de tres tokens dejaba sin traducir la forma más común y
el acta la reportaba como «no reconocida» — un falso negativo que manda a escribir a mano algo que el
lector sí sabe hacer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x
2026-09-11 18:27:32 +00:00

38 lines
1.0 KiB
Python

"""Registro de PLUGINS de formato (SDD 29).
Un formato se agrega dejando un fichero en este directorio que decore sus funciones con `@lector` y
`@escritor`. No hay que tocar el centro ni ningún otro plugin: ése es el punto de tener un pivote.
@lector("nginx")
def leer(texto) -> Config: ...
@escritor("caddy")
def escribir(cfg) -> str: ...
"""
import importlib, pkgutil, pathlib
LECTORES, ESCRITORES = {}, {}
def lector(nombre):
def deco(f):
LECTORES[nombre] = f
return f
return deco
def escritor(nombre):
def deco(f):
ESCRITORES[nombre] = f
return f
return deco
def cargar():
"""Importa todos los plugins del directorio. Descubrimiento, no lista cableada: una lista que hay
que editar a mano se desincroniza y el formato nuevo 'no existe' sin que nada falle."""
for m in pkgutil.iter_modules([str(pathlib.Path(__file__).parent)]):
if not m.name.startswith("_"):
importlib.import_module(f"{__name__}.{m.name}")
return LECTORES, ESCRITORES