Neu in embeddings.PROGRAMME (typ=parteiprogramm mit gueltig_ab): - csu-grundsatz: CSU "Für ein neues Miteinander" (2023-05-06, 125 chunks) ersetzt das bisher indizierte CSU 2016-Programm logisch - cdu-grundsatz-nrw: CDU NRW "Aufstieg, Sicherheit, Perspektive" (2015-06-13, Landesgrundsatzprogramm, 127 chunks) - cdu-grundsatz-sn: CDU Sachsen "Zukunftsplan für Sachsen" (2023-11-20, Landesgrundsatzprogramm, 52 chunks) - cdu-grundsatz-lsa: CDU Sachsen-Anhalt "Unsere Verantwortung. Unsere Zukunft." (2023-09-30, Landesgrundsatzprogramm, 74 chunks) - ssw-grundsatz: SSW Rahmenprogramm (2016-04-16, Landesgrundsatzprogramm für Schleswig-Holstein, 65 chunks) - fw-grundsatz: FREIE WAEHLER Bundesgrundsatzprogramm (Stand 09/2025; FW nicht im Bundestag, gilt fuer FW Bayern + FW RLP, 43 chunks) programme.py: - _migrate_from_legacy() unterscheidet jetzt grundsatzprogramm-bund (bundesland=None) und grundsatzprogramm-land (bundesland gesetzt). - _ADDITIONAL_PROGRAMME-Slot vereinfacht — alle Daten leben in embeddings.PROGRAMME. Auf gwoe-antragspruefer-dev indiziert (text-embedding-v4): 486 neue Chunks, 0 failed. wahlprogramm-shas.lock.json + -links.yaml gepinnt mit allen 6 SHA-256-Hashes. Test-Suite: 88 grün (test_legislaturen + test_wahlprogramme + test_embeddings). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
496 lines
21 KiB
Python
496 lines
21 KiB
Python
"""Zentrale Programm-Registry — alle politischen Programm-Dokumente
|
|
(Wahlprogramme, Bundes-Grundsatzprogramme, Landes-Grundsatzprogramme),
|
|
historisch und aktuell.
|
|
|
|
Single Source of Truth für:
|
|
- ``embeddings.py`` (Indexer liest die PDFs aus dieser Liste)
|
|
- ``wahlprogramme.py`` (Compat-Shim, leitet die alte BL/Partei-API hierher)
|
|
- ``analyzer.py`` (sucht das zum Antrag passende Wahlprogramm)
|
|
- UI (zeigt Geltungszeitraum + zugeordnete Regierung pro Programm)
|
|
|
|
Siehe ``app/legislaturen.py`` für Wahlperioden + Regierungen.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from typing import Literal, Optional, TypedDict
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Typ
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
ProgrammTyp = Literal[
|
|
"wahlprogramm", # zur Wahl beschlossen, gilt für 1 Legislatur
|
|
"grundsatzprogramm-bund", # bundesweites Grundsatzprogramm
|
|
"grundsatzprogramm-land", # landesspezifisches Grundsatzprogramm
|
|
]
|
|
|
|
|
|
class Programm(TypedDict, total=False):
|
|
"""Single source of truth für ein politisches Programm-Dokument.
|
|
|
|
Pflichtfelder: id, titel, name, typ, partei, gueltig_ab, pdf, seiten.
|
|
Optional: bundesland, beschluss, wahl, wp, gueltig_bis, hinweis.
|
|
"""
|
|
id: str # eindeutiger Schlüssel, z.B. "cdu-nrw-2022"
|
|
titel: str # offizieller Titel ("Machen, worauf es ankommt")
|
|
name: str # voll-qualifiziert für Citation (z.B. "CDU NRW Wahlprogramm 2022")
|
|
typ: ProgrammTyp
|
|
partei: str # normalisierter Schlüssel (CDU, GRÜNE, FREIE WÄHLER, BSW, …)
|
|
bundesland: Optional[str] # BL-Code; None nur bei reinen Bundesgrundsatzprogrammen
|
|
beschluss: Optional[str] # ISO YYYY-MM-DD; bei grundsatz: Parteitags-Beschluss
|
|
wahl: Optional[str] # ISO YYYY-MM-DD; nur typ=wahlprogramm: Wahltag
|
|
wp: Optional[int] # Legislatur-Nummer; nur typ=wahlprogramm
|
|
gueltig_ab: str # ISO; bei wahl: regierungsbildung; bei grundsatz: beschluss
|
|
gueltig_bis: Optional[str] # ISO; None = Programm ist aktuell gültig
|
|
pdf: str # Dateiname in static/referenzen/
|
|
seiten: int
|
|
hinweis: Optional[str] # freier Text, z.B. "BSW hat kein Grundsatzprogramm — Wahlprogramm dient als Hauptquelle"
|
|
|
|
|
|
REFERENZEN_PATH = Path(__file__).parent / "static" / "referenzen"
|
|
KONTEXT_PATH = Path(__file__).parent / "kontext"
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Programm-Registry
|
|
# Die Daten werden aus der bisherigen ``embeddings.PROGRAMME`` und
|
|
# ``wahlprogramme.WAHLPROGRAMME`` migriert. Historische Wahlprogramme +
|
|
# Landesgrundsatzprogramme werden ergänzt sobald die Recherche fertig ist.
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
# Aktuelle Programme — gefüllt durch ``_register_initial_data()`` weiter unten,
|
|
# damit der Migrations-Pfad an einer Stelle zu sehen ist.
|
|
PROGRAMME: dict[str, Programm] = {}
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Helper-API
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
def _date_in_range(datum: str, ab: str, bis: Optional[str]) -> bool:
|
|
"""Liefert True, wenn ``datum`` (ISO) in [ab, bis) liegt."""
|
|
if datum < ab:
|
|
return False
|
|
if bis is None:
|
|
return True
|
|
return datum < bis
|
|
|
|
|
|
def get_programm(programm_id: str) -> Optional[Programm]:
|
|
"""Lookup nach ID."""
|
|
return PROGRAMME.get(programm_id)
|
|
|
|
|
|
def aktuelles_wahlprogramm(bundesland: str, partei: str) -> Optional[Programm]:
|
|
"""Aktuell gültiges Wahlprogramm einer Partei in einem Bundesland.
|
|
|
|
Es kann nur eines aktuell sein (gueltig_bis=None und typ=wahlprogramm).
|
|
"""
|
|
for prog in PROGRAMME.values():
|
|
if (
|
|
prog.get("typ") == "wahlprogramm"
|
|
and prog.get("bundesland") == bundesland
|
|
and prog.get("partei") == partei
|
|
and prog.get("gueltig_bis") is None
|
|
):
|
|
return prog
|
|
return None
|
|
|
|
|
|
def wahlprogramm_zum_zeitpunkt(
|
|
bundesland: str, partei: str, datum: str,
|
|
) -> Optional[Programm]:
|
|
"""Welches Wahlprogramm dieser Partei galt im Bundesland am gegebenen Datum?
|
|
|
|
``datum`` ist ISO-Datum. Es wird das Programm zurückgegeben, dessen
|
|
Geltungszeitraum [gueltig_ab, gueltig_bis) das Datum enthält.
|
|
|
|
Rückgabe ``None``, wenn die Partei zu dem Zeitpunkt nicht im Schema
|
|
erfasst ist (oder das Bundesland nicht).
|
|
"""
|
|
for prog in PROGRAMME.values():
|
|
if (
|
|
prog.get("typ") == "wahlprogramm"
|
|
and prog.get("bundesland") == bundesland
|
|
and prog.get("partei") == partei
|
|
and _date_in_range(datum, prog["gueltig_ab"], prog.get("gueltig_bis"))
|
|
):
|
|
return prog
|
|
return None
|
|
|
|
|
|
def grundsatzprogramm_zum_zeitpunkt(
|
|
partei: str,
|
|
datum: str,
|
|
bundesland: Optional[str] = None,
|
|
) -> Optional[Programm]:
|
|
"""Welches Grundsatzprogramm der Partei galt am gegebenen Datum?
|
|
|
|
Wenn ``bundesland`` gesetzt ist, wird zuerst nach einem
|
|
Landes-Grundsatzprogramm gesucht; falls keines existiert, fällt die
|
|
Suche auf das Bundes-Grundsatzprogramm zurück.
|
|
|
|
Wenn ``bundesland`` ``None`` ist, wird nur nach Bundes-Grundsatz gesucht.
|
|
"""
|
|
if bundesland is not None:
|
|
# Erst Land suchen
|
|
for prog in PROGRAMME.values():
|
|
if (
|
|
prog.get("typ") == "grundsatzprogramm-land"
|
|
and prog.get("partei") == partei
|
|
and prog.get("bundesland") == bundesland
|
|
and _date_in_range(datum, prog["gueltig_ab"], prog.get("gueltig_bis"))
|
|
):
|
|
return prog
|
|
# Bund als Fallback / oder primär
|
|
for prog in PROGRAMME.values():
|
|
if (
|
|
prog.get("typ") == "grundsatzprogramm-bund"
|
|
and prog.get("partei") == partei
|
|
and _date_in_range(datum, prog["gueltig_ab"], prog.get("gueltig_bis"))
|
|
):
|
|
return prog
|
|
return None
|
|
|
|
|
|
def parteien_mit_wahlprogramm(bundesland: str) -> list[str]:
|
|
"""Parteien mit einem aktuell gültigen Wahlprogramm in dem Bundesland.
|
|
|
|
Reihenfolge: nach Eintrags-Reihenfolge in PROGRAMME (deterministic).
|
|
"""
|
|
seen: list[str] = []
|
|
for prog in PROGRAMME.values():
|
|
if (
|
|
prog.get("typ") == "wahlprogramm"
|
|
and prog.get("bundesland") == bundesland
|
|
and prog.get("gueltig_bis") is None
|
|
):
|
|
partei = prog["partei"]
|
|
if partei not in seen:
|
|
seen.append(partei)
|
|
return seen
|
|
|
|
|
|
def alle_versionen(bundesland: str, partei: str) -> list[Programm]:
|
|
"""Alle Wahlprogramm-Versionen dieser Partei im Bundesland, sortiert
|
|
nach ``gueltig_ab`` aufsteigend."""
|
|
versions = [
|
|
prog for prog in PROGRAMME.values()
|
|
if prog.get("typ") == "wahlprogramm"
|
|
and prog.get("bundesland") == bundesland
|
|
and prog.get("partei") == partei
|
|
]
|
|
versions.sort(key=lambda p: p["gueltig_ab"])
|
|
return versions
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Initiale Daten — wird über separate Daten-Datei eingespielt.
|
|
# Während des Migrationsfensters wird ``embeddings.PROGRAMME`` und
|
|
# ``wahlprogramme.WAHLPROGRAMME`` automatisch in PROGRAMME überführt.
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
def _register(prog: Programm) -> None:
|
|
"""Add a Programm to the registry, validating uniqueness of id."""
|
|
if prog["id"] in PROGRAMME:
|
|
raise ValueError(f"Programm-id collision: {prog['id']}")
|
|
PROGRAMME[prog["id"]] = prog
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Zusätzliche Programme — Reserve für Programme, die NICHT aus
|
|
# embeddings.PROGRAMME oder WAHLPROGRAMME migriert werden können (z.B.
|
|
# zukünftig: historische Vorgänger-Wahlprogramme aus früheren Legislaturen,
|
|
# falls deren PDFs eingebunden werden ohne dass embeddings.PROGRAMME sie
|
|
# kennt).
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
_ADDITIONAL_PROGRAMME: list[Programm] = []
|
|
|
|
|
|
# Historische Skelett-Einträge (PDFs jetzt in embeddings.PROGRAMME) —
|
|
# wurden in einer früheren Iteration manuell als pdf-pending markiert,
|
|
# bevor die Beschaffung lief. Aktuelle Daten leben in embeddings.PROGRAMME
|
|
# und werden über _migrate_from_legacy() automatisch übernommen.
|
|
_ARCHIVED_SKELETONS: list[Programm] = [
|
|
# ─── CSU Bayern: aktualisiertes Grundsatzprogramm 2023 ───────────────
|
|
# "Die Ordnung 2016" (in embeddings.PROGRAMME als Bundes-Grundsatz)
|
|
# wird durch das 2023er ersetzt — wir tragen 2023 als aktuelles ein und
|
|
# setzen das 2016er auf gueltig_bis. Funktionell ist es ein Landes-
|
|
# grundsatzprogramm, weil CSU nur in Bayern existiert.
|
|
{
|
|
"id": "csu-grundsatz-2023",
|
|
"titel": "Für ein neues Miteinander — Grundsatzprogramm der CSU",
|
|
"name": "CSU Grundsatzprogramm 2023",
|
|
"typ": "grundsatzprogramm-land",
|
|
"partei": "CSU",
|
|
"bundesland": "BY",
|
|
"beschluss": "2023-05-06",
|
|
"wahl": None,
|
|
"wp": None,
|
|
"gueltig_ab": "2023-05-06",
|
|
"gueltig_bis": None,
|
|
"pdf": "csu-grundsatz-2023.pdf",
|
|
"seiten": 0, # nach Download via PyMuPDF setzen
|
|
"hinweis": "pdf-pending",
|
|
},
|
|
# ─── CDU NRW Landesgrundsatzprogramm 2015 ─────────────────────────────
|
|
{
|
|
"id": "cdu-grundsatz-nrw-2015",
|
|
"titel": "Aufstieg, Sicherheit, Perspektive — Das Nordrhein-Westfalen-Programm",
|
|
"name": "CDU NRW Grundsatzprogramm 2015",
|
|
"typ": "grundsatzprogramm-land",
|
|
"partei": "CDU",
|
|
"bundesland": "NRW",
|
|
"beschluss": "2015-06-13",
|
|
"wahl": None,
|
|
"wp": None,
|
|
"gueltig_ab": "2015-06-13",
|
|
"gueltig_bis": None,
|
|
"pdf": "cdu-grundsatz-nrw-2015.pdf",
|
|
"seiten": 0,
|
|
"hinweis": "pdf-pending",
|
|
},
|
|
# ─── CDU Sachsen Landesgrundsatzprogramm 2023 ─────────────────────────
|
|
{
|
|
"id": "cdu-grundsatz-sn-2023",
|
|
"titel": "Zukunftsplan für Sachsen",
|
|
"name": "CDU Sachsen Grundsatzprogramm 2023",
|
|
"typ": "grundsatzprogramm-land",
|
|
"partei": "CDU",
|
|
"bundesland": "SN",
|
|
"beschluss": "2023-11-20",
|
|
"wahl": None,
|
|
"wp": None,
|
|
"gueltig_ab": "2023-11-20",
|
|
"gueltig_bis": None,
|
|
"pdf": "cdu-grundsatz-sn-2023.pdf",
|
|
"seiten": 0,
|
|
"hinweis": "pdf-pending",
|
|
},
|
|
# ─── CDU Sachsen-Anhalt Landesgrundsatzprogramm 2023 ──────────────────
|
|
{
|
|
"id": "cdu-grundsatz-lsa-2023",
|
|
"titel": "Sachsen-Anhalt. Unsere Verantwortung. Unsere Zukunft.",
|
|
"name": "CDU Sachsen-Anhalt Grundsatzprogramm 2023",
|
|
"typ": "grundsatzprogramm-land",
|
|
"partei": "CDU",
|
|
"bundesland": "LSA",
|
|
"beschluss": "2023-09-30",
|
|
"wahl": None,
|
|
"wp": None,
|
|
"gueltig_ab": "2023-09-30",
|
|
"gueltig_bis": None,
|
|
"pdf": "cdu-grundsatz-lsa-2023.pdf",
|
|
"seiten": 0,
|
|
"hinweis": "pdf-pending",
|
|
},
|
|
# ─── SSW Schleswig-Holstein Rahmenprogramm 2016 ────────────────────────
|
|
# SSW ist ausschließlich in SH aktiv (Minderheitenpartei der dänisch-
|
|
# friesischen Volksgruppe). Das Rahmenprogramm tritt funktional an die
|
|
# Stelle eines Grundsatzprogramms.
|
|
{
|
|
"id": "ssw-grundsatz-sh-2016",
|
|
"titel": "SSW Rahmenprogramm",
|
|
"name": "SSW Rahmenprogramm 2016",
|
|
"typ": "grundsatzprogramm-land",
|
|
"partei": "SSW",
|
|
"bundesland": "SH",
|
|
"beschluss": "2016-04-16",
|
|
"wahl": None,
|
|
"wp": None,
|
|
"gueltig_ab": "2016-04-16",
|
|
"gueltig_bis": None,
|
|
"pdf": "ssw-grundsatz-sh-2016.pdf",
|
|
"seiten": 0,
|
|
"hinweis": "pdf-pending",
|
|
},
|
|
# ─── FREIE WÄHLER Bundesvereinigung Grundsatzprogramm ─────────────────
|
|
# FW sind nicht im Bundestag (BTW 2025 unter 5%), aber im Landtag in
|
|
# Bayern (Regierung) und Rheinland-Pfalz (Opposition). Bundesgrundsatz-
|
|
# programm gilt als bundesweite Referenz für alle Landesverbände.
|
|
{
|
|
"id": "fw-grundsatz-2012",
|
|
"titel": "FREIE WÄHLER Bundesgrundsatzprogramm",
|
|
"name": "FREIE WÄHLER Bundesgrundsatzprogramm",
|
|
"typ": "grundsatzprogramm-bund",
|
|
"partei": "FREIE WÄHLER",
|
|
"bundesland": None,
|
|
"beschluss": "2012-02-25", # erstes Bundesgrundsatzprogramm; mehrfach fortgeschrieben
|
|
"wahl": None,
|
|
"wp": None,
|
|
"gueltig_ab": "2012-02-25",
|
|
"gueltig_bis": None,
|
|
"pdf": "fw-grundsatz.pdf",
|
|
"seiten": 0,
|
|
"hinweis": "pdf-pending — FREIE WÄHLER sind nicht im Bundestag, "
|
|
"Programm gilt als bundesweite Referenz für FW Bayern + FW Rheinland-Pfalz",
|
|
},
|
|
]
|
|
|
|
|
|
def _migrate_from_legacy() -> None:
|
|
"""Migriere bestehende Daten aus ``wahlprogramme.WAHLPROGRAMME`` und
|
|
``embeddings.PROGRAMME`` in die neue Registry. Wird einmal beim
|
|
Modul-Import aufgerufen.
|
|
|
|
Reihenfolge:
|
|
1. Wahlprogramme aus WAHLPROGRAMME (autoritative Quelle für regierungs-
|
|
gebundene Geltungsdaten).
|
|
2. Grundsatzprogramme aus embeddings.PROGRAMME (typ=parteiprogramm).
|
|
3. _ADDITIONAL_PROGRAMME (neue Daten — Landesgrundsatz, ggf. Updates).
|
|
|
|
Update-Logik: Wenn ein _ADDITIONAL Programm denselben ``partei``,
|
|
``bundesland`` und Typ wie ein bestehendes hat und neueres
|
|
``gueltig_ab`` besitzt, wird das Vorgänger-``gueltig_bis`` rückwirkend
|
|
auf das ``gueltig_ab`` des neuen gesetzt.
|
|
"""
|
|
# Zirkuläre Imports vermeiden — lazy import beim Migrationszeitpunkt.
|
|
from .wahlprogramme import WAHLPROGRAMME
|
|
from .embeddings import PROGRAMME as _EMB_PROGRAMME
|
|
|
|
# Schritt 1: Wahlprogramme aus WAHLPROGRAMME
|
|
for bundesland, parteien in WAHLPROGRAMME.items():
|
|
for partei, info in parteien.items():
|
|
# ID ableiten aus PDF-Stem
|
|
pid = info["file"].rsplit(".", 1)[0]
|
|
|
|
if info.get("ist_grundsatz"):
|
|
# Bundes-Grundsatzprogramm; Eintrag erfolgt in Schritt 2.
|
|
continue
|
|
|
|
prog: Programm = {
|
|
"id": pid,
|
|
"titel": info.get("titel", ""),
|
|
"name": f"{info.get('partei', partei)} Wahlprogramm {info.get('jahr', '')}".strip(),
|
|
"typ": "wahlprogramm",
|
|
"partei": partei,
|
|
"bundesland": bundesland,
|
|
"beschluss": None,
|
|
"wahl": None,
|
|
"wp": None,
|
|
"gueltig_ab": info.get("regierungsbildung") or "1900-01-01",
|
|
"gueltig_bis": info.get("regierungsende"),
|
|
"pdf": info["file"],
|
|
"seiten": int(info.get("seiten", 0)),
|
|
"hinweis": None,
|
|
}
|
|
if pid not in PROGRAMME:
|
|
PROGRAMME[pid] = prog
|
|
|
|
# Schritt 2: Grundsatzprogramme aus embeddings.PROGRAMME.
|
|
# typ=parteiprogramm: ohne ``bundesland`` → Bundes-Grundsatz, mit
|
|
# ``bundesland`` → Landes-Grundsatzprogramm. Beide funktional gleich,
|
|
# nur unterscheidet sich der Geltungsbereich.
|
|
for pid, info in _EMB_PROGRAMME.items():
|
|
if info.get("typ") != "parteiprogramm":
|
|
continue # Wahlprogramme schon in Schritt 1
|
|
if pid in PROGRAMME:
|
|
continue
|
|
bl = info.get("bundesland")
|
|
prog2: Programm = {
|
|
"id": pid,
|
|
"titel": info.get("name", ""),
|
|
"name": info.get("name", ""),
|
|
"typ": "grundsatzprogramm-land" if bl else "grundsatzprogramm-bund",
|
|
"partei": info.get("partei", ""),
|
|
"bundesland": bl,
|
|
"beschluss": info.get("gueltig_ab"),
|
|
"wahl": None,
|
|
"wp": None,
|
|
"gueltig_ab": info.get("gueltig_ab") or "1900-01-01",
|
|
"gueltig_bis": info.get("gueltig_bis"),
|
|
"pdf": info.get("pdf", ""),
|
|
"seiten": 0,
|
|
"hinweis": None,
|
|
}
|
|
PROGRAMME[pid] = prog2
|
|
|
|
# Schritt 3: _ADDITIONAL_PROGRAMME — mit Vorgänger-bis-Update
|
|
for prog3 in _ADDITIONAL_PROGRAMME:
|
|
# Setze gueltig_bis von Vorgänger-Programmen rückwirkend.
|
|
for existing in list(PROGRAMME.values()):
|
|
if (
|
|
existing.get("typ") in ("grundsatzprogramm-bund",
|
|
"grundsatzprogramm-land")
|
|
and existing.get("partei") == prog3.get("partei")
|
|
and existing.get("bundesland") == prog3.get("bundesland")
|
|
and existing.get("gueltig_bis") is None
|
|
and existing.get("gueltig_ab", "9999-99-99") < prog3["gueltig_ab"]
|
|
):
|
|
# Wir mutieren ein TypedDict in der Registry — das ist OK,
|
|
# weil _migrate_from_legacy() einmal beim Import läuft.
|
|
existing["gueltig_bis"] = prog3["gueltig_ab"] # type: ignore[typeddict-item]
|
|
if prog3["id"] not in PROGRAMME:
|
|
PROGRAMME[prog3["id"]] = prog3
|
|
|
|
|
|
# Lazy initialisierung — erst beim ersten echten Zugriff. Dadurch vermeidet
|
|
# das Modul Import-Reihenfolge-Probleme mit ``embeddings.py`` (das viel mehr
|
|
# Initialisierung braucht: openai, fitz, etc.).
|
|
_INITIALIZED = False
|
|
|
|
|
|
def _ensure_initialized() -> None:
|
|
global _INITIALIZED
|
|
if _INITIALIZED:
|
|
return
|
|
_migrate_from_legacy()
|
|
_INITIALIZED = True
|
|
|
|
|
|
# Patch helper-API to ensure init runs on first call.
|
|
_get_programm = get_programm
|
|
_aktuelles_wahlprogramm = aktuelles_wahlprogramm
|
|
_wahlprogramm_zum_zeitpunkt = wahlprogramm_zum_zeitpunkt
|
|
_grundsatzprogramm_zum_zeitpunkt = grundsatzprogramm_zum_zeitpunkt
|
|
_parteien_mit_wahlprogramm = parteien_mit_wahlprogramm
|
|
_alle_versionen = alle_versionen
|
|
|
|
|
|
def get_programm(programm_id: str) -> Optional[Programm]: # type: ignore[no-redef]
|
|
_ensure_initialized()
|
|
return _get_programm(programm_id)
|
|
|
|
|
|
def aktuelles_wahlprogramm(bundesland: str, partei: str) -> Optional[Programm]: # type: ignore[no-redef]
|
|
_ensure_initialized()
|
|
return _aktuelles_wahlprogramm(bundesland, partei)
|
|
|
|
|
|
def wahlprogramm_zum_zeitpunkt( # type: ignore[no-redef]
|
|
bundesland: str, partei: str, datum: str,
|
|
) -> Optional[Programm]:
|
|
_ensure_initialized()
|
|
return _wahlprogramm_zum_zeitpunkt(bundesland, partei, datum)
|
|
|
|
|
|
def grundsatzprogramm_zum_zeitpunkt( # type: ignore[no-redef]
|
|
partei: str, datum: str, bundesland: Optional[str] = None,
|
|
) -> Optional[Programm]:
|
|
_ensure_initialized()
|
|
return _grundsatzprogramm_zum_zeitpunkt(partei, datum, bundesland)
|
|
|
|
|
|
def parteien_mit_wahlprogramm(bundesland: str) -> list[str]: # type: ignore[no-redef]
|
|
_ensure_initialized()
|
|
return _parteien_mit_wahlprogramm(bundesland)
|
|
|
|
|
|
def alle_versionen(bundesland: str, partei: str) -> list[Programm]: # type: ignore[no-redef]
|
|
_ensure_initialized()
|
|
return _alle_versionen(bundesland, partei)
|
|
|
|
|
|
def all_programme() -> list[Programm]:
|
|
"""Alle eingetragenen Programme (initialisiert, falls nötig)."""
|
|
_ensure_initialized()
|
|
return list(PROGRAMME.values())
|