Files
Plugin_SN_Basis/modules/Dateipruefer.py

209 lines
8.1 KiB
Python

"""
sn_basis/modules/Dateipruefer.py
Erweiterter Dateiprüfer für Verfahrens-DB-Workflows mit vollständiger Unterstützung
der Anforderungen 1-2.e (leerer Pfad, fehlende Datei, bestehende Datei).
"""
from pathlib import Path
from typing import Optional
from sn_basis.functions.sys_wrapper import join_path, file_exists
from sn_basis.modules.pruef_ergebnis import pruef_ergebnis, PruefAktion
class Dateipruefer:
"""
Prüft Dateieingaben für Verfahrens-DB-Workflows und liefert :class:`pruef_ergebnis`.
**Funktionsweise (deine Anforderungen 1-2.e):**
+---------------------+------------------------------------------+---------------+
| **Fall** | **Ergebnis** | **ok** |
+=====================+==========================================+===============+
| 1. Leerer Pfad | ``temporaer_erlaubt`` | False |
+---------------------+------------------------------------------+---------------+
| 2.a Leerer Pfad | Pruefmanager fragt → ``temporaer_erzeugen`` | True |
+---------------------+------------------------------------------+---------------+
| 2.b Datei existiert | ``ok`` | True |
+---------------------+------------------------------------------+---------------+
| 2.c Ungültiger Pfad | ``datei_nicht_gefunden`` | False |
+---------------------+------------------------------------------+---------------+
| **2.d Datei fehlt** | **``datei_wird_erzeugt``** | **True** |
+---------------------+------------------------------------------+---------------+
| **2.e Datei da** | **``datei_existiert``** | **False** |
+---------------------+------------------------------------------+---------------+
Der Dateiprüfer führt **keine UI-Interaktion** durch.
Entscheidungen werden ausschließlich vom :class:`Pruefmanager` getroffen.
"""
def __init__(
self,
pfad: Optional[str],
basis_pfad: str = "",
leereingabe_erlaubt: bool = False,
standarddatei: Optional[str] = None,
temporaer_erlaubt: bool = False,
*,
verfahrens_db_modus: bool = True, # 🆕 Verfahrens-DB-spezifische Logik
) -> None:
"""
Parameters
----------
pfad : Optional[str]
Vom UI gelieferter Dateipfad (kann leer oder Whitespace sein).
basis_pfad : str, optional
Basisverzeichnis für relative Pfade (default: "").
leereingabe_erlaubt : bool, optional
Ob leere Eingabe grundsätzlich erlaubt ist (default: False).
standarddatei : Optional[str], optional
Optionaler Standardpfad (default: None).
temporaer_erlaubt : bool, optional
Ob bei leerer Eingabe temporäre Layer erlaubt sind (default: False).
verfahrens_db_modus : bool, optional
Aktiviert Verfahrens-DB-spezifische Logik (2.d, 2.e) (default: True).
"""
self.pfad = pfad
self.basis_pfad = basis_pfad
self.leereingabe_erlaubt = leereingabe_erlaubt
self.standarddatei = standarddatei
self.temporaer_erlaubt = temporaer_erlaubt
self.verfahrens_db_modus = verfahrens_db_modus
# ------------------------------------------------------------------
# Hilfsfunktionen
# ------------------------------------------------------------------
def _pfad(self, relativer_pfad: str) -> Path:
"""Erzeugt OS-unabhängigen Pfad relativ zum Basisverzeichnis."""
return join_path(self.basis_pfad, relativer_pfad)
def _ist_leer(self) -> bool:
"""
Prüft robust, ob Eingabe als „leer" zu behandeln ist.
Returns
-------
bool
True bei None, leerem String oder reinem Whitespace.
"""
if self.pfad is None:
return True
if not isinstance(self.pfad, str):
return True
return not self.pfad.strip()
def _ist_gueltiger_gpkg_pfad(self, pfad: Path) -> bool:
"""
Prüft, ob Pfad für GPKG geeignet ist (Endung + Schreibrechte).
Returns
-------
bool
True wenn `.gpkg`-Endung und Verzeichnis beschreibbar.
"""
if not str(pfad).lower().endswith('.gpkg'):
return False
# Verzeichnis muss beschreibbar sein
return pfad.parent.exists() and pfad.parent.is_dir()
# ------------------------------------------------------------------
# Hauptlogik: deine Anforderungen 1-2.e
# ------------------------------------------------------------------
def pruefe(self) -> pruef_ergebnis:
"""
🆕 Prüft Dateieingabe gemäß Anforderungen 1-2.e.
**Workflow:**
1. **Leere Eingabe** → ``temporaer_erlaubt`` (Pruefmanager fragt)
2. **Pfad prüfen**:
- **Ungültig** → 2.c ``datei_nicht_gefunden``
- **Gültig, fehlt** → **2.d** ``datei_wird_erzeugt`` (ok=True!)
- **Gültig, existiert** → **2.e** ``datei_existiert`` (Pruefmanager fragt)
3. **Datei OK** → 2.b ``ok``
Returns
-------
pruef_ergebnis
Mit korrekter Aktion für jeden Fall.
"""
# 1. 🎯 ANFORDERUNG 1: Leere Eingabe
if self._ist_leer():
return self._handle_leere_eingabe()
# 2. Pfad normalisieren
pfad = self._pfad(self.pfad.strip())
# 🆕 2.c: Ungültiger GPKG-Pfad?
if not self.verfahrens_db_modus or not self._ist_gueltiger_gpkg_pfad(pfad):
return pruef_ergebnis(
ok=False,
meldung=f"Der Pfad '{self.pfad}' ist kein gültiger GPKG-Pfad.",
aktion="datei_nicht_gefunden",
kontext=pfad,
)
# 🆕 2.d: Gültiger Pfad, Datei fehlt → DIREKT WEITER (ok=True!)
if not file_exists(pfad):
return pruef_ergebnis(
ok=True, # 🎯 WICHTIG: Pipeline fortsetzen!
meldung=f"Datei '{self.pfad}' wird erzeugt.",
aktion="datei_wird_erzeugt",
kontext=pfad,
)
# 🆕 2.e: Datei existiert → Pruefmanager fragt Überschreiben/etc.
return pruef_ergebnis(
ok=False, # 🎯 Pruefmanager soll 4-Optionen-Dialog zeigen
meldung=f"Datei '{self.pfad}' existiert bereits.",
aktion="datei_existiert",
kontext=pfad,
)
# 2.b: Wird nicht erreicht (durch 2.e abgefangen)
# ------------------------------------------------------------------
# Leere Eingabe (ANFORDERUNG 1, 2.a)
# ------------------------------------------------------------------
def _handle_leere_eingabe(self) -> pruef_ergebnis:
"""
Behandelt leere Eingaben (Priorität: leereingabe → Standard → temporär → Fehler).
"""
if self.leereingabe_erlaubt:
return pruef_ergebnis(
ok=False,
meldung="Das Dateifeld ist leer. Soll ohne Datei fortgefahren werden?",
aktion="leereingabe_erlaubt",
kontext=None,
)
if self.standarddatei:
return pruef_ergebnis(
ok=False,
meldung=(
"Es wurde keine Datei angegeben. "
f"Soll die Standarddatei '{self.standarddatei}' verwendet werden?"
),
aktion="standarddatei_vorschlagen",
kontext=self._pfad(self.standarddatei),
)
if self.temporaer_erlaubt:
return pruef_ergebnis(
ok=False,
meldung=(
"Es wurde keine Datei angegeben. "
"Sollen temporäre Layer erzeugt werden?"
),
aktion="temporaer_erlaubt",
kontext=None,
)
return pruef_ergebnis(
ok=False,
meldung="Es wurde keine Datei angegeben.",
aktion="leereingabe_nicht_erlaubt",
kontext=None,
)