from __future__ import annotations from typing import Optional, Any from sn_basis.functions import ( ask_yes_no, info, warning, error, set_layer_visible, ) from sn_basis.modules.pruef_ergebnis import pruef_ergebnis, PruefAktion class Pruefmanager: """ Zentrale Verarbeitung von pruef_ergebnis-Objekten. Erwartete öffentliche API (verwendet von Core-Komponenten wie DataGrabber): - report_error(thema, meldung, *, aktion: Optional[PruefAktion]=None, kontext=None) -> None - request_decision(pruef_res) -> str - report_summary(summary: dict) -> None - verarbeite(ergebnis: pruef_ergebnis) -> pruef_ergebnis """ def __init__(self, ui_modus: str = "qgis", parent: Optional[Any] = None): self.ui_modus = ui_modus self.parent = parent # --------------------------------------------------------------------- # Basis-API: Meldungen / Zusammenfassungen # --------------------------------------------------------------------- def report_error(self, thema: str, meldung: str, *, aktion: Optional[PruefAktion] = None, kontext: Optional[Any] = None) -> None: """ Einheitliche Meldung für Fehler/Warnungen aus dem Core. Keine Rückgabe; dient als zentraler Hook für Logging/UI. """ critical_actions = { "netzwerkfehler", "pruefe_exception", "save_exception", "layer_create_failed", "read_error", "open_error", } warn_actions = { "datei_nicht_gefunden", "pfad_nicht_gefunden", "url_nicht_erreichbar", "falsche_endung", "kein_header", "kein_arbeitsblatt", } if aktion in critical_actions: error(thema, meldung) return if aktion in warn_actions: warning(thema, meldung) return # Default: informative Warnung warning(thema, meldung) def report_summary(self, summary: dict) -> None: geladen = summary.get("geladen", []) fehler = summary.get("fehler", {}) ausserhalb = summary.get("ausserhalb", []) relevant = summary.get("relevant", []) message = ( f"Geladene Dienste: {len(geladen)}\n" f"Relevante Dienste: {len(relevant)}\n" f"Dienste ausserhalb: {len(ausserhalb)}\n" f"Fehler: {len(fehler)}" ) info("DataGrabber Zusammenfassung", message) # --------------------------------------------------------------------- # Entscheidungs-API # --------------------------------------------------------------------- def request_decision(self, pruef_res: Any) -> str: """ Synchronously request a decision from the user (or return a default in headless mode). Returns one of: - "abort" - "continue" - "temporaer_erzeugen" - "ignore" """ aktion = getattr(pruef_res, "aktion", None) meldung = getattr(pruef_res, "meldung", str(pruef_res)) interactive_actions = { "leereingabe_erlaubt", "standarddatei_vorschlagen", "temporaer_erlaubt", "layer_unsichtbar", } if aktion in interactive_actions: if self.ui_modus == "qgis": title_map = { "leereingabe_erlaubt": "Ohne Eingabe fortfahren", "standarddatei_vorschlagen": "Standarddatei verwenden", "temporaer_erlaubt": "Temporäre Datei erzeugen", "layer_unsichtbar": "Layer einblenden", } title = title_map.get(aktion, "Entscheidung erforderlich") try: yes = ask_yes_no(title, meldung, default=False, parent=self.parent) except Exception: return "abort" if yes: if aktion == "temporaer_erlaubt": return "temporaer_erzeugen" return "continue" return "abort" if self.ui_modus == "headless": return "abort" informational_actions = { "leer", "datei_nicht_gefunden", "pfad_nicht_gefunden", "url_nicht_erreichbar", "netzwerkfehler", "falscher_geotyp", "layer_leer", "falscher_layertyp", "falsches_crs", "felder_fehlen", "datenquelle_unerwartet", "layer_nicht_editierbar", "kein_header", "kein_arbeitsblatt", "read_error", "open_error", } if aktion in informational_actions: return "abort" return "abort" # --------------------------------------------------------------------- # Höhere Abstraktion: verarbeite # --------------------------------------------------------------------- def verarbeite(self, ergebnis: pruef_ergebnis) -> pruef_ergebnis: """ Verarbeitet ein pruef_ergebnis-Objekt und führt ggf. Nutzerinteraktion durch. Liefert ein ggf. modifiziertes pruef_ergebnis zurück. """ if ergebnis.ok: return ergebnis aktion = ergebnis.aktion kontext = ergebnis.kontext meldung = ergebnis.meldung # Zentrale Meldung self.report_error(aktion or "pruefung", meldung or "", aktion=aktion, kontext=kontext) # Interaktive Entscheidungen if aktion in ("leereingabe_erlaubt", "standarddatei_vorschlagen", "temporaer_erlaubt", "layer_unsichtbar"): decision = self.request_decision(ergebnis) if decision == "temporaer_erzeugen": return pruef_ergebnis(ok=True, meldung="Temporäre Datei soll erzeugt werden.", aktion="temporaer_erzeugen", kontext=None) if decision == "continue": return pruef_ergebnis(ok=True, meldung="Fortgefahren.", aktion="ok", kontext=kontext) return ergebnis # abort / unverändert # Spezielle Excel/Importer-Fälle: klare Meldungen, keine interaktive Entscheidung if aktion == "kein_header": warning("Excel-Import", meldung or "") return ergebnis if aktion == "kein_arbeitsblatt": warning("Excel-Import", meldung or "") return ergebnis if aktion in ("read_error", "open_error"): error("Excel-Import", meldung or "") return ergebnis if aktion == "datei_nicht_gefunden": warning("Datei nicht gefunden", meldung or "") return ergebnis # Spezieller Fall: layer_unsichtbar (falls nicht interaktiv behandelt) if aktion == "layer_unsichtbar": if kontext is not None: try: set_layer_visible(kontext, True) return pruef_ergebnis(ok=True, meldung="Layer wurde eingeblendet.", aktion="ok", kontext=kontext) except Exception: return ergebnis return ergebnis # Standard: keine Änderung return ergebnis