"""Numeral-script normalization without value repair.""" from .contracts import SourceScript WESTERN = "0123456789" ARABIC_INDIC = "٠١٢٣٤٥٦٧٨٩" EXTENDED_ARABIC_INDIC = "۰۱۲۳۴۵۶۷۸۹" TRANSLATION = str.maketrans( ARABIC_INDIC + EXTENDED_ARABIC_INDIC + "٬٫،", WESTERN + WESTERN + ",.,", ) ALLOWED = frozenset(WESTERN + "/-.,:% ") def _source_script(text: str) -> SourceScript: scripts = set() if any(char in WESTERN for char in text): scripts.add("western") if any(char in ARABIC_INDIC for char in text): scripts.add("arabic_indic") if any(char in EXTENDED_ARABIC_INDIC for char in text): scripts.add("extended_arabic_indic") if len(scripts) > 1: return "mixed" return next(iter(scripts), "western") # type: ignore[return-value] def normalize_numeric_text(text: str) -> tuple[str, SourceScript]: stripped = text.strip() script = _source_script(stripped) normalized = stripped.translate(TRANSLATION) unsupported = next((char for char in normalized if char not in ALLOWED), None) if unsupported is not None: raise ValueError("unsupported character in numeric evidence") if not any(char.isdigit() for char in normalized): raise ValueError("numeric evidence contains no digits") return normalized, script