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>
118 lines
4.6 KiB
Python
118 lines
4.6 KiB
Python
#!/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("&", "&").replace("<", "<").replace(">", ">")
|
|
.replace('"', """))
|
|
|
|
|
|
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()
|