forked from AG_QGIS/Plugin_SN_Basis
209 lines
8.1 KiB
Python
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,
|
|
)
|