Fassung 0.6.0 und ein Bauskript fuer das Plugin-Paket

tools/baue_paket.py schnuert aus dem Arbeitsstand das ZIP (genau ein Ordner vln_karten/,
ohne __pycache__) und schreibt die passende plugins.xml. Beides gehoert danach in den
Manager nach api/qgis/; von dort liefert der Server es unter /v2/qgis/ aus, und QGIS bietet
neue Fassungen von selbst an.

metadata.txt: Fassung 0.6.0, Beschreibung und Changelog auf den heutigen Stand (Widmungen
und Verkehrszeichen, Palette, Werkzeuge, Rollbalken). dist/ bleibt aus dem Git heraus.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
KAI
2026-09-21 11:40:23 +02:00
co-authored by Claude Opus 5
parent 9c2c1c57af
commit 7dd3b9a0a2
3 changed files with 123 additions and 3 deletions
+1
View File
@@ -1,3 +1,4 @@
__pycache__/
*.pyc
.DS_Store
dist/
+117
View File
@@ -0,0 +1,117 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Aus dem Arbeitsstand ein QGIS-Plugin-Paket bauen (ZIP + plugins.xml).
QGIS installiert Erweiterungen aus einem ZIP, das genau einen Ordner enthält — hier
``vln_karten/``. Ein eigenes Plugin-Verzeichnis ist nichts weiter als eine ``plugins.xml``
neben diesen ZIPs; trägt man ihre Adresse in QGIS ein (Erweiterungen → Einstellungen →
Hinzufügen), bietet QGIS Aktualisierungen von selbst an.
Aufruf::
python3 tools/baue_paket.py [Zielordner]
Ohne Zielordner landet alles unter ``dist/``. Die beiden Dateien gehören danach in den
Manager (``api/qgis/``); von dort liefert der Server sie unter ``/v2/qgis/`` aus.
Nichts an QGIS gebunden — läuft mit jedem Python 3.
"""
import os
import sys
import zipfile
WURZEL = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PAKET = "vln_karten"
#: Was nicht ins Paket gehört (Laufzeitkram und Eigenes der Arbeitskopie).
AUS = (".pyc", ".pyo", ".DS_Store")
AUS_ORDNER = ("__pycache__", ".git")
#: Adresse, unter der der Manager die Pakete ausliefert.
BASIS = "https://api.flurneuordnung-sachsen.de/v2/qgis"
def metadaten():
"""``metadata.txt`` als dict (nur ``[general]``, mehrzeilige Werte zusammengefasst)."""
pfad = os.path.join(WURZEL, PAKET, "metadata.txt")
daten, schluessel = {}, None
with open(pfad, "r", encoding="utf-8") as fh:
for zeile in fh:
if zeile.startswith("[") or not zeile.strip():
continue
if "=" in zeile and not zeile.startswith((" ", "\t")):
schluessel, wert = zeile.split("=", 1)
schluessel = schluessel.strip()
daten[schluessel] = wert.strip()
elif schluessel:
daten[schluessel] += " " + zeile.strip()
return daten
def baue_zip(ziel, version):
"""Das Paket schreiben und seinen Pfad zurückgeben."""
name = "%s-%s.zip" % (PAKET, version)
pfad = os.path.join(ziel, name)
mit = 0
with zipfile.ZipFile(pfad, "w", zipfile.ZIP_DEFLATED) as z:
for ordner, unter, dateien in os.walk(os.path.join(WURZEL, PAKET)):
unter[:] = [u for u in unter if u not in AUS_ORDNER]
for datei in sorted(dateien):
if datei.endswith(AUS) or datei in AUS:
continue
voll = os.path.join(ordner, datei)
z.write(voll, os.path.relpath(voll, WURZEL))
mit += 1
return pfad, mit
def _xml(text):
return (str(text).replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
.replace('"', "&quot;"))
def baue_xml(ziel, daten, zipname):
"""``plugins.xml`` schreiben — das Verzeichnis, das QGIS abfragt."""
pfad = os.path.join(ziel, "plugins.xml")
inhalt = (
'<?xml version="1.0"?>\n<plugins>\n'
' <pyqgis_plugin name="%s" version="%s">\n'
' <description>%s</description>\n'
' <about>%s</about>\n'
' <version>%s</version>\n'
' <qgis_minimum_version>%s</qgis_minimum_version>\n'
' <qgis_maximum_version>%s</qgis_maximum_version>\n'
' <homepage>%s</homepage>\n'
' <file_name>%s</file_name>\n'
' <download_url>%s/%s</download_url>\n'
' <author_name>%s</author_name>\n'
' <tracker>%s</tracker>\n'
' <repository>%s</repository>\n'
' <tags>%s</tags>\n'
' <experimental>%s</experimental>\n'
' <deprecated>False</deprecated>\n'
' </pyqgis_plugin>\n</plugins>\n'
% (_xml(daten.get("name")), _xml(daten.get("version")),
_xml(daten.get("description")), _xml(daten.get("about")),
_xml(daten.get("version")), _xml(daten.get("qgisMinimumVersion", "3.22")),
_xml(daten.get("qgisMaximumVersion", "3.99")), _xml(daten.get("repository", "")),
_xml(zipname), BASIS, _xml(zipname), _xml(daten.get("author", "")),
_xml(daten.get("tracker", "")), _xml(daten.get("repository", "")),
_xml(daten.get("tags", "")), _xml(daten.get("experimental", "False"))))
with open(pfad, "w", encoding="utf-8") as fh:
fh.write(inhalt)
return pfad
def main():
ziel = sys.argv[1] if len(sys.argv) > 1 else os.path.join(WURZEL, "dist")
os.makedirs(ziel, exist_ok=True)
daten = metadaten()
zippfad, anzahl = baue_zip(ziel, daten["version"])
xmlpfad = baue_xml(ziel, daten, os.path.basename(zippfad))
print("Paket: %s (%d Dateien, %.0f KB)"
% (zippfad, anzahl, os.path.getsize(zippfad) / 1024))
print("Katalog: %s" % xmlpfad)
print("Beides nach VLNManager/api/qgis/ kopieren; der Server liefert es unter %s/" % BASIS)
if __name__ == "__main__":
main()
+5 -3
View File
@@ -3,9 +3,9 @@ name=VLN Karten
qgisMinimumVersion=3.22
qgisMaximumVersion=4.99
supportsQt6=True
description=Beispiel: Karten-API des VLN Managers aus QGIS ansteuern — OGC API Features, alle Layer editierbar, von der Vorerhebung bis zum Maßnahmenblatt.
about=Referenz-Implementierung für die VLN-Manager-Karten-API: Login (mail/password -> userauth-API-Key), vollständiges Laden je VKZ mit Paging (EPSG:25833), Splitten gemischter Geometrietypen in Memory-Layer und vereintes Zurückschreiben per PUT.
version=0.5.0
description=Karten des VLN Managers in QGIS: OGC API Features, alle Layer editierbar — von der Vorerhebung über das Maßnahmenblatt bis zu Widmungen und Verkehrszeichen.
about=Anmeldung mit der Manager-Kennung (der API-Key wird gemerkt), Verfahrenslayer über die OGC API laden und bearbeiten (jede Änderung geht einzeln zurück), Geodienste aus der Linkliste, Stile vom Server. Verkehrszeichen und Widmungen lassen sich wie im Web setzen: Schild aus der Palette wählen, erster Klick Standort, zweiter Klick Blickrichtung; die Schildgrafiken kommen von der API und liegen danach lokal.
version=0.6.0
author=Erik
email=phpwelt@gmail.com
tracker=https://entwicklung.flurneuordnung-sachsen.de/VLN_SN/API_Karte_QGISDemo/issues
@@ -15,3 +15,5 @@ category=Web
icon=
experimental=True
deprecated=False
changelog=0.6.0 Widmungen und Verkehrszeichen: eigene Layergruppe, Schildgrafiken vom Server (lokal abgelegt), Palette mit Suche, Werkzeuge „Schild setzen" und „Zusatzzeichen"; Seitenleiste rollt statt das QGIS-Fenster zu strecken (Issue #1).
0.5.0 Geodienste aus der Linkliste, Stile speichern, Seitenleiste statt Werkzeugleiste.