gwoe-antragspruefer/app/bundeslaender.py
Dotty Dotter 5a30ce8bab bundeslaender.py: doku_system-Klassifikation für TH, HB, SN korrigiert (#48)
Beim Auswerten der dokukratie/*.yml-Configs (Annotationen in
Issues #19-#30) sind drei Falsch-Einträge aufgefallen, die zu
unnötigem Reverse-Engineering bei den Adapter-Implementierungen
geführt hätten:

- TH "StarWeb" → "ParlDok"
  dokukratie/th.yml zeigt parldok.thueringen.de/ParlDok/formalkriterien/
  mit ParlDok-typischen Form-Feldern (DokumententypId, LegislaturpNum).
  Live-System ggf. ParlDok 8.x SPA wie MV — dann ParLDokAdapter direkt
  wiederverwendbar (Issue #25 Annotation).

- HB "PARiS" → "StarWeb"
  PARiS ist nur eine StarWeb-Skin auf paris.bremische-buergerschaft.de
  /starweb/paris/servlet.starweb?path=paris/LISSH.web. Wiederverwendbar
  mit dem generischen StarWebAdapter aus Issue #27 (Template).

- SN "ParlDok" → "Eigensystem"
  EDAS auf edas.landtag.sachsen.de basiert auf ASP.NET-Webforms mit
  __VIEWSTATE/__CALLBACKID-Postbacks (siehe dokukratie/sn.yml). Nicht
  ParlDok-kompatibel mit MV. Eigener Adapter notwendig.

Anmerkungs-Texte erweitert mit Adapter-Wiederverwendungs-Hinweis und
Verifikations-Schritt für Live-System-Versionen.

Phase 0 aus Roadmap-Issue #49.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 23:19:41 +02:00

400 lines
16 KiB
Python

"""Zentrale Konfiguration aller 16 deutschen Bundesländer.
Dieses Modul ist die Single Source of Truth für alle bundeslandspezifischen
Daten: Parlamente, Regierungen, Wahlperioden, Doku-Systeme, etc. Andere
Module (main.py, parlamente.py, wahlprogramme.py, analyzer.py) lesen
ausschließlich von hier.
Stand: April 2026. Nach jeder Landtagswahl bzw. Regierungsbildung müssen
die betroffenen Einträge aktualisiert werden.
Datenquellen: Wikipedia, offizielle Landtagsseiten, parlamentsspiegel.de,
https://github.com/okfde/dokukratie (für Doku-System-Zuordnung).
"""
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class Bundesland:
"""Konfiguration eines deutschen Bundeslands.
Attributes:
code: Übliches Kürzel im politischen Sprachgebrauch (NRW, BY, LSA…).
Bei Mehrdeutigkeit ISO-3166-2-DE-Suffix; Sachsen-Anhalt nutzt
jedoch das politisch dominante "LSA" statt ISO "ST".
name: Vollständiger Landesname.
parlament_name: Offizieller Name des Parlaments.
wahlperiode: Aktuelle Wahlperiode als Zahl.
wahlperiode_start: Beginn der aktuellen WP (ISO-Datum).
naechste_wahl: Nächste reguläre Landtagswahl (ISO-Datum), oder None
wenn noch nicht festgesetzt.
regierungsfraktionen: Parteien der aktuellen Landesregierung in
Reihenfolge der Größe.
landtagsfraktionen: Alle aktuell im Landtag vertretenen Fraktionen.
doku_system: Verwendetes Parlamentsdokumentationssystem.
Werte: "OPAL", "StarWeb", "ParlDok", "PARDOK", "PARLIS",
"PARiS", "Eigensystem".
doku_base_url: Basis-URL der Parlamentsdokumentation.
drucksache_format: Beispielhaftes Format einer Drucksachen-ID,
z.B. "18/12345" für NRW WP18.
dokukratie_scraper: Code-Name des Dokukratie-Scrapers (falls
vorhanden), nützlich für künftige Adapter-Implementierung.
aktiv: Ob das Bundesland im Frontend auswählbar und im Analyzer
unterstützt ist. Inaktive Bundesländer werden im UI als
"(bald)" angezeigt und sind disabled.
anmerkung: Optionale Hinweise zu Sondersituationen (z.B.
Koalitionsverhandlungen, jüngste Wahl, geschätzte Termine).
"""
code: str
name: str
parlament_name: str
wahlperiode: int
wahlperiode_start: str
naechste_wahl: Optional[str]
regierungsfraktionen: list[str]
landtagsfraktionen: list[str]
doku_system: str
doku_base_url: str
drucksache_format: str
dokukratie_scraper: Optional[str]
aktiv: bool = False
anmerkung: str = ""
# Hauptregister: code -> Bundesland-Instanz.
# Reihenfolge alphabetisch nach offiziellem Namen für stabile UI-Sortierung.
BUNDESLAENDER: dict[str, Bundesland] = {
"BW": Bundesland(
code="BW",
name="Baden-Württemberg",
parlament_name="Landtag von Baden-Württemberg",
wahlperiode=17,
wahlperiode_start="2021-05-01",
naechste_wahl="2031-03-08",
regierungsfraktionen=["GRÜNE", "CDU"],
landtagsfraktionen=["GRÜNE", "CDU", "AfD", "SPD", "FDP"],
doku_system="PARLIS",
doku_base_url="https://parlis.landtag-bw.de",
drucksache_format="17/12345",
dokukratie_scraper="bw",
anmerkung=(
"Wahl zum 18. Landtag fand am 08.03.2026 statt; Koalitionsverhandlungen "
"GRÜNE+CDU laufen, Kabinett Kretschmann III geschäftsführend. Nach "
"Konstituierung des 18. LT ca. Mai 2026 müssen WP und Wahltermin aktualisiert werden."
),
),
"BY": Bundesland(
code="BY",
name="Bayern",
parlament_name="Bayerischer Landtag",
wahlperiode=19,
wahlperiode_start="2023-10-30",
naechste_wahl="2028-10-08",
regierungsfraktionen=["CSU", "FW"],
landtagsfraktionen=["CSU", "GRÜNE", "FW", "AfD", "SPD"],
doku_system="Eigensystem",
doku_base_url="https://www.bayern.landtag.de",
drucksache_format="19/1234",
dokukratie_scraper="by",
anmerkung="Wahltermin 2028 noch nicht offiziell festgesetzt; Schätzung Herbst 2028.",
),
"BE": Bundesland(
code="BE",
name="Berlin",
parlament_name="Abgeordnetenhaus von Berlin",
wahlperiode=19,
wahlperiode_start="2023-04-27",
naechste_wahl="2026-09-20",
regierungsfraktionen=["CDU", "SPD"],
landtagsfraktionen=["CDU", "SPD", "GRÜNE", "LINKE", "AfD"],
doku_system="PARDOK",
doku_base_url="https://pardok.parlament-berlin.de",
drucksache_format="19/1234",
dokukratie_scraper="be",
aktiv=True,
anmerkung=(
"PARDOK = portala/eUI-Framework (gleiche Engine wie LSA-PADOKA, "
"unter /portala/ statt /portal/). Hit list arrives as production "
"HTML cards instead of LSA-style Perl Data::Dumper blocks — "
"PortalaAdapter auto-detects both formats. document_type=None "
"for BE because Berlin's ETYPF index uses different value strings "
"than LSA. Wahlprogramme zur LTW 2023 sind noch nicht indexiert "
"(Folge-Issue) — Analyse läuft daher mit Grundsatzprogramm-"
"Zitaten als Fallback. Open-Data-XML unter "
"parlament-berlin.de/dokumente/open-data ist eine alternative "
"Datenquelle, derzeit nicht verwendet."
),
),
"BB": Bundesland(
code="BB",
name="Brandenburg",
parlament_name="Landtag Brandenburg",
wahlperiode=8,
wahlperiode_start="2024-10-23",
naechste_wahl="2029-09-23",
regierungsfraktionen=["SPD", "BSW"],
landtagsfraktionen=["SPD", "AfD", "CDU", "BSW"],
doku_system="StarWeb",
doku_base_url="https://www.parlamentsdokumentation.brandenburg.de",
drucksache_format="8/1234",
dokukratie_scraper="bb",
anmerkung="Kabinett Woidke IV (SPD-BSW) seit Dezember 2024. Knappe Mehrheit (zwei Sitze).",
),
"HB": Bundesland(
code="HB",
name="Bremen",
parlament_name="Bremische Bürgerschaft",
wahlperiode=21,
wahlperiode_start="2023-07-05",
naechste_wahl="2027-05-09",
regierungsfraktionen=["SPD", "GRÜNE", "LINKE"],
landtagsfraktionen=["SPD", "CDU", "GRÜNE", "LINKE", "AfD", "BiW"],
doku_system="StarWeb",
doku_base_url="https://paris.bremische-buergerschaft.de",
drucksache_format="21/1234",
dokukratie_scraper="hb",
anmerkung=(
"PARiS ist eine StarWeb-Skin auf bremischer Hardware — kein "
"eigenständiges System. Endpoint folgt dem Standard "
"/starweb/paris/servlet.starweb?path=paris/LISSH.web (siehe "
"dokukratie/hb.yml). Wiederverwendbar mit dem generischen "
"StarWebAdapter aus Issue #27. AfD durch Listenstreichung 2023 "
"nicht im Landtag, stattdessen Bürger in Wut (BiW). Wahltag 2027 "
"noch nicht festgesetzt."
),
),
"HH": Bundesland(
code="HH",
name="Hamburg",
parlament_name="Hamburgische Bürgerschaft",
wahlperiode=23,
wahlperiode_start="2025-03-26",
naechste_wahl="2030-03-03",
regierungsfraktionen=["SPD", "GRÜNE"],
landtagsfraktionen=["SPD", "CDU", "GRÜNE", "LINKE", "AfD"],
doku_system="ParlDok",
doku_base_url="https://www.buergerschaft-hh.de/parldok",
drucksache_format="23/1234",
dokukratie_scraper="hh",
anmerkung="Wahl am 02.03.2025; Senat Tschentscher III seit 07.05.2025 vereidigt.",
),
"HE": Bundesland(
code="HE",
name="Hessen",
parlament_name="Hessischer Landtag",
wahlperiode=21,
wahlperiode_start="2024-01-18",
naechste_wahl="2028-10-22",
regierungsfraktionen=["CDU", "SPD"],
landtagsfraktionen=["CDU", "AfD", "SPD", "GRÜNE", "FDP"],
doku_system="StarWeb",
doku_base_url="https://starweb.hessen.de/starweb/LIS",
drucksache_format="21/1234",
dokukratie_scraper="he",
anmerkung="Wahltermin 2028 ist Schätzung.",
),
"MV": Bundesland(
code="MV",
name="Mecklenburg-Vorpommern",
parlament_name="Landtag Mecklenburg-Vorpommern",
wahlperiode=8,
wahlperiode_start="2021-10-26",
naechste_wahl="2026-09-20",
regierungsfraktionen=["SPD", "LINKE"],
landtagsfraktionen=["SPD", "AfD", "CDU", "LINKE", "GRÜNE", "FDP"],
doku_system="ParlDok",
doku_base_url="https://www.dokumentation.landtag-mv.de",
drucksache_format="8/1234",
dokukratie_scraper="mv",
aktiv=True,
anmerkung=(
"ParlDok 8.3.5 (J3S GmbH) — moderne SPA, JSON-API unter "
"/parldok/Fulltext/Search. ParLDokAdapter (eigene Implementierung, "
"nicht portala-kompatibel). Die in dokukratie/mv.yml beschriebene "
"Legacy-HTML-Form (parldok/formalkriterien) ist mit dem 8.x-Upgrade "
"deprecated. Suche filtert via facet_lp=10/id=8 server-seitig auf "
"WP8, type=Antrag wird client-seitig gefiltert. Wahlprogramme zur "
"LTW 26.09.2021 sind noch nicht indexiert (Folge-Issue) — Analyse "
"läuft daher mit Grundsatzprogramm-Zitaten als Fallback. Wahltag "
"offiziell auf 20.09.2026 festgelegt."
),
),
"NI": Bundesland(
code="NI",
name="Niedersachsen",
parlament_name="Niedersächsischer Landtag",
wahlperiode=19,
wahlperiode_start="2022-11-08",
naechste_wahl="2027-10-10",
regierungsfraktionen=["SPD", "GRÜNE"],
landtagsfraktionen=["SPD", "CDU", "GRÜNE", "AfD"],
doku_system="StarWeb",
doku_base_url="https://www.landtag-niedersachsen.de",
drucksache_format="19/12345",
dokukratie_scraper="ni",
anmerkung=(
"Wahltermin Herbst 2027 (zwischen 11.07. und 03.10.2027) noch nicht festgesetzt; "
"geschätzt. Olaf Lies (SPD) seit 20.05.2025 Ministerpräsident."
),
),
"NRW": Bundesland(
code="NRW",
name="Nordrhein-Westfalen",
parlament_name="Landtag Nordrhein-Westfalen",
wahlperiode=18,
wahlperiode_start="2022-06-01",
naechste_wahl="2027-05-15",
regierungsfraktionen=["CDU", "GRÜNE"],
landtagsfraktionen=["CDU", "SPD", "GRÜNE", "FDP", "AfD"],
doku_system="OPAL",
doku_base_url="https://opal.landtag.nrw.de",
drucksache_format="18/12345",
dokukratie_scraper="nw",
aktiv=True,
anmerkung=(
"OPAL in NRW ist eine eigene Implementierung, nicht identisch mit dem "
"StarWeb-basierten OPAL in RLP. Wahltermin 2027 ist Schätzung."
),
),
"RP": Bundesland(
code="RP",
name="Rheinland-Pfalz",
parlament_name="Landtag Rheinland-Pfalz",
wahlperiode=18,
wahlperiode_start="2021-05-18",
naechste_wahl="2031-03-22",
regierungsfraktionen=["SPD", "GRÜNE", "FDP"],
landtagsfraktionen=["SPD", "CDU", "AfD", "GRÜNE", "FREIE WÄHLER", "FDP"],
doku_system="StarWeb",
doku_base_url="https://opal.rlp.de",
drucksache_format="18/12345",
dokukratie_scraper="rp",
anmerkung=(
"OPAL in RLP basiert auf StarWeb. Wahl zum 19. Landtag fand am 22.03.2026 "
"statt; Koalitionsverhandlungen CDU+SPD laufen, Kabinett Schweitzer I "
"geschäftsführend. Nach Konstituierung müssen WP und Wahltermin aktualisiert werden."
),
),
"SL": Bundesland(
code="SL",
name="Saarland",
parlament_name="Landtag des Saarlandes",
wahlperiode=17,
wahlperiode_start="2022-04-25",
naechste_wahl="2027-04-18",
regierungsfraktionen=["SPD"],
landtagsfraktionen=["SPD", "CDU", "AfD"],
doku_system="Eigensystem",
doku_base_url="https://www.landtag-saar.de",
drucksache_format="17/1234",
dokukratie_scraper="sl",
anmerkung=(
"Einzige SPD-Alleinregierung in Deutschland. AfD-Status im 17. LT vor "
"produktiver Nutzung verifizieren."
),
),
"SN": Bundesland(
code="SN",
name="Sachsen",
parlament_name="Sächsischer Landtag",
wahlperiode=8,
wahlperiode_start="2024-10-01",
naechste_wahl="2029-09-02",
regierungsfraktionen=["CDU", "SPD"],
landtagsfraktionen=["CDU", "AfD", "BSW", "SPD", "LINKE", "GRÜNE"],
doku_system="Eigensystem",
doku_base_url="https://edas.landtag.sachsen.de",
drucksache_format="8/1234",
dokukratie_scraper="sn",
anmerkung=(
"Minderheitsregierung CDU+SPD (Kabinett Kretschmer III seit "
"18.12.2024). EDAS auf edas.landtag.sachsen.de ist eine "
"ASP.NET-Webforms-Anwendung mit __VIEWSTATE/__CALLBACKID-"
"Postbacks (siehe dokukratie/sn.yml) — NICHT ParlDok-kompatibel "
"mit MV/HH trotz älterer Wikipedia-Klassifikation. Eigener "
"Adapter notwendig (Issue #26)."
),
),
"LSA": Bundesland(
code="LSA",
name="Sachsen-Anhalt",
parlament_name="Landtag von Sachsen-Anhalt",
wahlperiode=8,
wahlperiode_start="2021-07-06",
naechste_wahl="2026-09-06",
regierungsfraktionen=["CDU", "SPD", "FDP"],
landtagsfraktionen=["CDU", "AfD", "LINKE", "SPD", "GRÜNE", "FDP"],
doku_system="PARDOK",
doku_base_url="https://padoka.landtag.sachsen-anhalt.de",
drucksache_format="8/1234",
dokukratie_scraper="st",
aktiv=True,
anmerkung=(
"ISO-Code wäre ST; LSA ist im politischen Sprachgebrauch dominant. "
"Sven Schulze (CDU) seit 28.01.2026 MP nach Rücktritt Haseloff. "
"PADOKA wurde von StarWeb auf das portala/eUI-Framework migriert "
"(gleiche Engine wie Berlin/PARDOK). dokukratie's st.yml ist veraltet. "
"Suche läuft via POST /portal/browse.tt.json + report.tt.html."
),
),
"SH": Bundesland(
code="SH",
name="Schleswig-Holstein",
parlament_name="Schleswig-Holsteinischer Landtag",
wahlperiode=20,
wahlperiode_start="2022-06-07",
naechste_wahl="2027-04-18",
regierungsfraktionen=["CDU", "GRÜNE"],
landtagsfraktionen=["CDU", "GRÜNE", "SPD", "FDP", "SSW"],
doku_system="StarWeb",
doku_base_url="https://www.landtag.ltsh.de",
drucksache_format="20/1234",
dokukratie_scraper="sh",
anmerkung="SSW ist von der 5%-Hürde befreit.",
),
"TH": Bundesland(
code="TH",
name="Thüringen",
parlament_name="Thüringer Landtag",
wahlperiode=8,
wahlperiode_start="2024-10-01",
naechste_wahl="2029-09-01",
regierungsfraktionen=["CDU", "BSW", "SPD"],
landtagsfraktionen=["AfD", "CDU", "LINKE", "BSW", "SPD"],
doku_system="ParlDok",
doku_base_url="https://parldok.thueringen.de",
drucksache_format="8/1234",
dokukratie_scraper="th",
anmerkung=(
"Erste Brombeer-Koalition Deutschlands (CDU+BSW+SPD) als "
"Minderheitsregierung mit 44 von 88 Sitzen. Mario Voigt (CDU) "
"seit Dezember 2024 MP. Doku-System ist ParlDok (siehe "
"dokukratie/th.yml mit DokumententypId/LegislaturperiodenNummer-"
"Form-Feldern), nicht StarWeb wie ursprünglich klassifiziert. "
"Vor Implementierung mit `curl parldok.thueringen.de/parldok/` "
"verifizieren ob das Live-System ParlDok 8.x SPA wie MV ist — "
"dann ist der ParLDokAdapter direkt wiederverwendbar."
),
),
}
def get(code: str) -> Optional[Bundesland]:
"""Bundesland-Konfig per Code abrufen, oder None."""
return BUNDESLAENDER.get(code)
def aktive_bundeslaender() -> list[Bundesland]:
"""Alle aktuell aktiven (im Analyzer unterstützten) Bundesländer."""
return [bl for bl in BUNDESLAENDER.values() if bl.aktiv]
def alle_bundeslaender() -> list[Bundesland]:
"""Alle 16 Bundesländer (aktive zuerst, dann alphabetisch nach Name)."""
aktiv = sorted([bl for bl in BUNDESLAENDER.values() if bl.aktiv], key=lambda b: b.name)
inaktiv = sorted([bl for bl in BUNDESLAENDER.values() if not bl.aktiv], key=lambda b: b.name)
return aktiv + inaktiv