Phase 7: sync_shared.py - Mojibake-fail-safe + Doku
- has_mojibake_markers Heuristik: erkennt Doppel/Triple-Encoded UTF-8 (typische Latin-1-Sicht-Sequenzen wie ä ö ¤ Æ). - fix_mojibake raises RuntimeError wenn ftfy fehlt UND Mojibake erkannt ist - verhindert Mojibake-Reimport durch Sync. - main() faengt RuntimeError und exit 2 mit klarer Fehlermeldung. - CLAUDE.md: Voraussetzung ftfy + fail-safe-Erklaerung erganzt.
Dieser Commit ist enthalten in:
@@ -51,11 +51,31 @@ DEFAULT_MONITOR = Path("/home/claude-dev/AegisSight-Monitor")
|
||||
DEFAULT_VERWALTUNG = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def has_mojibake_markers(text: str) -> bool:
|
||||
"""Heuristik: Doppel/Triple-Encoded UTF-8 erkennen.
|
||||
|
||||
Echte deutsche Umlaute kommen als "ü" / "ä" / "ö" / "ß" - Single-Byte-Zeichen
|
||||
aus latin-1-Sicht ("Ã", "Â", "Æ") sind ein starkes Mojibake-Indiz.
|
||||
"""
|
||||
return any(seq in text for seq in ("ä", "ö", "ü", "ß", "Ä", "Ö", "Ü", "¤", "Æ"))
|
||||
|
||||
|
||||
def fix_mojibake(text: str) -> tuple[str, bool]:
|
||||
"""Repariert Doppel-Encoded UTF-8 falls vorhanden. Gibt (text, fixed?) zurück."""
|
||||
"""Repariert Doppel-Encoded UTF-8 falls vorhanden. Gibt (text, fixed?) zurück.
|
||||
|
||||
Raises RuntimeError wenn Mojibake erkannt wird aber ftfy nicht installiert ist
|
||||
(dann würde ein Sync den Mojibake unrepariert ins Verwaltungs-Repo schreiben -
|
||||
dagegen schützt fail-fast).
|
||||
"""
|
||||
try:
|
||||
import ftfy # type: ignore
|
||||
except ImportError:
|
||||
if has_mojibake_markers(text):
|
||||
raise RuntimeError(
|
||||
"Monitor-Source enthält Mojibake (Doppel-Encoded UTF-8) und ftfy "
|
||||
"ist nicht installiert. Sync würde Mojibake ins Verwaltungs-Repo "
|
||||
"schreiben.\n Lösung: pip install ftfy (im venv des Repos)"
|
||||
)
|
||||
return text, False
|
||||
fixed = ftfy.fix_text(text)
|
||||
return fixed, fixed != text
|
||||
@@ -126,7 +146,11 @@ def main() -> int:
|
||||
return 2
|
||||
|
||||
src_text = src_path.read_text(encoding="utf-8")
|
||||
src_text, fixed_mojibake = fix_mojibake(src_text)
|
||||
try:
|
||||
src_text, fixed_mojibake = fix_mojibake(src_text)
|
||||
except RuntimeError as e:
|
||||
print(f"FEHLER beim Verarbeiten von {monitor_rel}:\n {e}", file=sys.stderr)
|
||||
return 2
|
||||
src_text = patch_imports_for_shared(src_text)
|
||||
|
||||
existing = dst_path.read_text(encoding="utf-8") if dst_path.exists() else ""
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren