Compare commits

..
Author SHA1 Message Date
release-bot 3b47e41bbe Release 26.5.3-unstable 2026-05-06 10:17:14 +00:00
Daniel 1a9595598e Merge pull request 'grenzpunkttolerant auf 1mm gesetzt' (#17) from feature/grenzpunkte_laden into unstable
Release Plugin / release (push) Successful in 4s
Reviewed-on: #17
2026-05-06 12:16:47 +02:00
Daniel 4bbdb96bcd grenzpunkttolerant auf 1mm gesetzt 2026-05-06 11:57:50 +02:00
release-bot aa6166e652 Release 26.5.2-unstable 2026-05-06 09:50:27 +00:00
Daniel 12b52d0468 Merge pull request 'proxy-fix' (#16) from feature/grenzpunkte_laden into unstable
Release Plugin / release (push) Successful in 4s
Reviewed-on: #16
2026-05-06 11:49:45 +02:00
Daniel cbd7b84889 Merge branch 'unstable' of https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_SN_Verfahrensgebiet into feature/grenzpunkte_laden 2026-05-06 11:45:50 +02:00
DanielandCopilot 28cfc75121 proxy-fix
Co-authored-by: Copilot <copilot@github.com>
2026-05-06 11:43:44 +02:00
release-bot cee02ae935 Release 26.5.1-unstable 2026-05-06 08:39:31 +00:00
6 changed files with 97 additions and 59 deletions
+6
View File
@@ -1,4 +1,10 @@
---
Version 26.5.3-unstable:
---
Version 26.5.2-unstable:
---
Version 26.5.1-unstable:
---
Version 26.4.6-unstable:
---
Version 26.4.5-unstable:
+66 -54
View File
@@ -146,6 +146,9 @@ def _wfs_get_gml(url: str, typename: str, extra_params: dict) -> Optional[bytes]
GET-Requests mit ``BBOX=``-KVP-Parameter oder ResourceId-``FILTER`` (nur
``xmlns:fes``, kein GML) werden dagegen akzeptiert.
**Proxy-Unterstützung:** Verwendet ``QgsBlockingNetworkRequest``, das automatisch
die in QGIS konfigurierten Proxy-Einstellungen berücksichtigt.
Parameters
----------
url :
@@ -161,10 +164,10 @@ def _wfs_get_gml(url: str, typename: str, extra_params: dict) -> Optional[bytes]
bytes | None
Rohe GML-Antwort oder ``None`` bei Fehler.
"""
import urllib.request
import urllib.parse
import urllib.error
from qgis.core import QgsMessageLog, Qgis
from qgis.core import QgsMessageLog, Qgis, QgsBlockingNetworkRequest
from qgis.PyQt.QtNetwork import QNetworkRequest
from qgis.PyQt.QtCore import QUrl
params = {
'SERVICE': 'WFS',
@@ -177,26 +180,34 @@ def _wfs_get_gml(url: str, typename: str, extra_params: dict) -> Optional[bytes]
full_url = url + '?' + urllib.parse.urlencode(params)
try:
with urllib.request.urlopen(full_url, timeout=120) as resp:
gml_bytes = resp.read()
except urllib.error.HTTPError as exc:
body_preview = exc.read(200).decode('utf-8', errors='replace')
req = QNetworkRequest(QUrl(full_url))
req.setTransferTimeout(120_000)
blocker = QgsBlockingNetworkRequest()
err = blocker.get(req)
if err != QgsBlockingNetworkRequest.ErrorCode.NoError:
msg = blocker.errorMessage()
QgsMessageLog.logMessage(
f"WFS GET HTTP {exc.code} ({typename}): {exc.reason}\n"
f"WFS GET fehlgeschlagen ({typename}): {msg}\nURL: {full_url[:300]}",
"sn_verfahrensgebiet",
Qgis.MessageLevel.Critical,
)
warning("WFS GET", f"Netzwerk-/Proxy-Fehler: {msg}", duration=10)
return None
reply = blocker.reply()
http_status = reply.attribute(QNetworkRequest.Attribute.HttpStatusCodeAttribute)
gml_bytes = bytes(reply.content())
if http_status is not None and http_status >= 400:
body_preview = gml_bytes[:200].decode('utf-8', errors='replace')
QgsMessageLog.logMessage(
f"WFS GET HTTP {http_status} ({typename})\n"
f"URL: {full_url[:300]}\nAntwort: {body_preview}",
"sn_verfahrensgebiet",
Qgis.MessageLevel.Critical,
)
warning("WFS GET", f"HTTP {exc.code}: {exc.reason}", duration=10)
return None
except Exception as exc:
QgsMessageLog.logMessage(
f"WFS GET fehlgeschlagen ({typename}): {exc}\nURL: {full_url[:300]}",
"sn_verfahrensgebiet",
Qgis.MessageLevel.Critical,
)
warning("WFS GET", f"Netzwerkfehler: {exc}", duration=10)
warning("WFS GET", f"HTTP {http_status}", duration=10)
return None
if not gml_bytes:
@@ -477,11 +488,7 @@ def _lade_grenzpunkte_als_dict(
)
_gml_bytes = _wfs_get_gml(ALKIS_SF_URL, GRENZPUNKT_TYPENAME, {'FILTER': filter_xml})
if not _gml_bytes:
warning(
"Grenzpunkte (Diagnose)",
f"Batch {i + 1}/{anzahl_batches}: GET-Anfrage fehlgeschlagen – Batch wird übersprungen.",
duration=4,
)
return {}, []
else:
tmp = _parse_alkis_gml_memory_layer(_gml_bytes, "AX_Grenzpunkt", "_TmpGP", geom_prop=None)
if not tmp:
@@ -704,9 +711,12 @@ def _lade_gemarkung_extents_mit_puffer(
return extents
def _wfs_hits_count(url: str, typename: str, extra_params: dict) -> int:
def _wfs_hits_count(url: str, typename: str, extra_params: dict) -> Optional[int]:
"""Fragt die Anzahl der Features per ``resultType=hits`` ab.
**Proxy-Unterstützung:** Verwendet ``QgsBlockingNetworkRequest``, das automatisch
die in QGIS konfigurierten Proxy-Einstellungen berücksichtigt.
Parameters
----------
url :
@@ -714,17 +724,21 @@ def _wfs_hits_count(url: str, typename: str, extra_params: dict) -> int:
typename :
Vollqualifizierter Feature-Typ.
extra_params :
Zus\u00e4tzliche KVP-Parameter (z.B. ``{'BBOX': '...'}``).
Zusätzliche KVP-Parameter (z.B. ``{'BBOX': '...'}``).
Returns
-------
int
Anzahl der Features oder ``-1`` wenn nicht ermittelbar.
Optional[int]
Anzahl der Features,
``-1`` wenn der Server antwortete aber ``numberMatched='unknown'`` lieferte
(gültiger WFS-Fallback, kein Fehler), oder
``None`` bei Netzwerk-/Proxy-Fehler (Aufrufer soll abbrechen).
"""
import urllib.request
import urllib.parse
import urllib.error
import xml.etree.ElementTree as ET
from qgis.core import QgsMessageLog, Qgis, QgsBlockingNetworkRequest
from qgis.PyQt.QtNetwork import QNetworkRequest
from qgis.PyQt.QtCore import QUrl
params = {
'SERVICE': 'WFS',
@@ -736,11 +750,22 @@ def _wfs_hits_count(url: str, typename: str, extra_params: dict) -> int:
params.update(extra_params)
full_url = url + '?' + urllib.parse.urlencode(params)
try:
with urllib.request.urlopen(full_url, timeout=30) as resp:
gml_bytes = resp.read()
except Exception:
return -1
req = QNetworkRequest(QUrl(full_url))
req.setTransferTimeout(30_000)
blocker = QgsBlockingNetworkRequest()
err = blocker.get(req)
if err != QgsBlockingNetworkRequest.ErrorCode.NoError:
msg = blocker.errorMessage()
QgsMessageLog.logMessage(
f"WFS Hits-Abfrage fehlgeschlagen ({typename}): {msg}\nURL: {full_url[:300]}",
"sn_verfahrensgebiet",
Qgis.MessageLevel.Critical,
)
return None
gml_bytes = bytes(blocker.reply().content())
try:
root = ET.fromstring(gml_bytes)
@@ -796,12 +821,7 @@ def _lade_punktort_ta_batches_per_gemarkung(
)
_gml_bytes = _wfs_get_gml(ALKIS_SF_URL, PUNKTORT_TA_TYPENAME, {'BBOX': _punktort_ta_bbox_param(bbox)})
if not _gml_bytes:
warning(
"Grenzpunkte (Diagnose)",
f"Gemarkung {_gemarkungsnummer}: GET-Anfrage fehlgeschlagen – wird übersprungen.",
duration=4,
)
continue
return None
tmp = _parse_alkis_gml_memory_layer(_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position", extract_qualitaet=True)
if not tmp:
warning(
@@ -997,6 +1017,8 @@ def lade_punktort_ta(
bbox_param = _punktort_ta_bbox_param(bbox)
n_hits = _wfs_hits_count(ALKIS_SF_URL, PUNKTORT_TA_TYPENAME, {'BBOX': bbox_param})
if n_hits is None:
return None
n_batches = max(1, math.ceil(n_hits / _BBOX_BATCH)) if n_hits > 0 else 1
info(
@@ -1022,13 +1044,7 @@ def lade_punktort_ta(
_gml_bytes = _wfs_get_gml(ALKIS_SF_URL, PUNKTORT_TA_TYPENAME, extra)
if not _gml_bytes:
warning(
"Grenzpunkte (Diagnose)",
f"Gemarkung {gemarkungsnummer} Batch {b_idx + 1}: "
f"GET-Anfrage fehlgeschlagen – übersprungen.",
duration=4,
)
continue
return None
tmp = _parse_alkis_gml_memory_layer(
_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position", extract_qualitaet=True
@@ -1343,6 +1359,8 @@ def grenzpunkte_gemarkungsweise(
for gemarkungsnummer, bbox in extents.items():
bbox_param = _punktort_ta_bbox_param(bbox)
n_hits = _wfs_hits_count(ALKIS_SF_URL, PUNKTORT_TA_TYPENAME, {'BBOX': bbox_param})
if n_hits is None:
return None
hits_pro_gemarkung[gemarkungsnummer] = n_hits
batches = max(1, math.ceil(n_hits / _BBOX_BATCH)) if n_hits > 0 else 1
n_pta_batches_gesamt += batches
@@ -1413,13 +1431,7 @@ def grenzpunkte_gemarkungsweise(
_gml_bytes = _wfs_get_gml(ALKIS_SF_URL, PUNKTORT_TA_TYPENAME, extra)
if not _gml_bytes:
warning(
"Grenzpunkte (Diagnose)",
f"Gemarkung {gemarkungsnummer} Batch {b_idx + 1}: "
f"GET-Anfrage fehlgeschlagen – Batch wird übersprungen.",
duration=6,
)
continue
return None
tmp = _parse_alkis_gml_memory_layer(
_gml_bytes, "AX_PunktortTA", "_TmpPTA", geom_prop="position", extract_qualitaet=True
+1 -1
View File
@@ -61,7 +61,7 @@ KATEGORIE_GROSS = ">3cm"
KATEGORIE_UNBEKANNT = "unbekannt"
#: Maximaler Abstand (m) eines Punktes vom Umring, um als „auf dem Umring" zu gelten.
UMRING_TOLERANZ_M: float = 0.1
UMRING_TOLERANZ_M: float = 0.01
#: Grenzwert für ``qualitaetsangaben_ax_dqpunktort_genauigkeitsstufe`` (3-cm-Schwelle).
GENAUIGKEIT_GRENZWERT: int = 2100
@@ -488,6 +488,17 @@ def verfahrensgebiet_alkis_komplett(
if punktort_layer is None:
detail_progress.close()
abgeschlossen = True
if not detail_progress.is_canceled():
QMessageBox.critical(
tab_widget,
"WFS-Fehler",
"Die Grenzpunktdaten (PunktortTA) konnten nicht geladen werden.\n\n"
"Mögliche Ursache: Netzwerk- oder Proxy-Fehler.\n"
"Bitte prüfen Sie die QGIS-Proxy-Einstellungen "
"(Einstellungen -> Optionen -> Netzwerk) und den Log-Eintrag "
"unter Ansicht -> Bedienfelder -> Protokollnachrichten "
"(Kategorie 'sn_verfahrensgebiet').",
)
return enriched_layer, flst_layer, alkis_vg_layer, vg_status
# Schritte 2…Ende: Knickpunktprüfung
+1 -1
View File
@@ -1,5 +1,5 @@
[general]
version=26.4.6-unstable
version=26.5.3-unstable
name=LNO Sachsen | Verfahrensgebiet
description=Plugin zum Erzeugen eines Objektes "Verfahrensgebiet"
author=Daniel Helbig, Michael Otto
+12 -3
View File
@@ -487,10 +487,19 @@ class WorkingTab(QWidget):
if joined_layer and joined_layer.isValid():
iface.mapCanvas().refresh()
self.setze_haken(self.haken_grenz, True)
success(
"Grenzpunkte",
QMessageBox.information(
self,
"Grenzpunkte geladen",
f"Grenzpunkte erfolgreich geladen ({joined_layer.featureCount()} Objekte).",
duration=5,
)
elif joined_layer is None:
error(
"Grenzpunkte",
"Laden fehlgeschlagen – WFS- oder Netzwerkfehler. "
"Details unter Ansicht -> Bedienfelder -> Protokollnachrichten "
"(Kategorie 'sn_verfahrensgebiet'). "
"Bitte prüfen Sie ggf. die Proxy-Einstellungen.",
duration=0,
)
finally:
self._set_busy(self.btn_grenz_alkis, False, "Grenzpunkte aus ALKIS laden")