"""Shared tiny registry for eval-layer plugins (mirrors data registry semantics).""" import difflib from typing import Callable, Dict, List class EvalRegistry: """Dict registry: decorator registration, duplicate guard, suggestions.""" def __init__(self, kind: str): self.kind = kind self._items: Dict[str, Callable] = {} def register(self, name: str, fn: Callable) -> Callable: if name in self._items: raise ValueError(f'{self.kind} {name!r} is already registered') self._items[name] = fn return fn def get(self, name: str) -> Callable: if name not in self._items: near = difflib.get_close_matches(name, self._items, n=3) hint = f" Did you mean: {', '.join(near)}?" if near else '' raise KeyError(f'unknown {self.kind} {name!r}.{hint}') return self._items[name] def names(self) -> List[str]: return sorted(self._items) def __contains__(self, name: str) -> bool: return name in self._items def __len__(self) -> int: return len(self._items)