fix(qr): reportlab renderPM-Backend fehlte auf CI-Runner
CI / backend-tests (push) Successful in 3m17s
CI / frontend-build (push) Successful in 20s

Erster echter Test für services/qr_png.py (bisher nie getestet, auch
nicht in ASSET-010) deckte auf: reportlab.graphics.renderPM braucht
einen nativen Rendering-Backend, der auf Python 3.13 nicht lauffähig
installiert war. Hätte auch die ASSET-010-QR-Anzeige im Ausgabe-
Dialog treffen können, war nur nie bemerkt worden. Auf qrcode[pil]
(reiner Python-Encoder, kein natives Backend nötig) umgestellt.
label.py (PDF-Vektor-Labels) ist unverändert, nicht betroffen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
patrickandClaude Sonnet 5 committed 2026-09-10 20:57:56 +02:00
1 parent 777bf5eaa5
commit f93798e3f3
3 files changed
+28 -17

No files matched your search

+12
View File
@@ -102,6 +102,18 @@ Build-Host, kein Dauerbetrieb der App dort (App läuft auf Endgeräten).
Hinweis in `AdminPage.tsx` verlinkt jetzt auf `/app` statt Version/URL
zu duplizieren. Tests: `test_app_download.py` (404 ohne version.json,
volle URL korrekt zusammengesetzt, PNG-Response, kein Auth-Zwang).
- **CI-Fund 2026-09-10 (echter Bug, nicht nur Testartefakt):** der erste
QR-PNG-Test deckte auf, dass `services/qr_png.py` (bisher NIE getestet,
auch nicht in ASSET-010) über `reportlab.graphics.renderPM` einen
nativen Rendering-Backend braucht, der auf dem CI-Runner (Python 3.13)
nicht lauffähig installiert war ("cannot import desired renderPM backend
rlPyCairo") — hätte auch in Produktion die ASSET-010-QR-Anzeige im
Ausgabe-Dialog treffen können, war nur nie bemerkt worden, weil dafür
bislang kein Test existierte. Behoben durch Wechsel auf `qrcode[pil]`
(reiner Python-QR-Encoder + Pillow, kein natives Backend nötig) statt
`reportlab.graphics.renderPM` — betrifft nur die PNG-Ausgabe, die
PDF-Vektor-Labels (`label.py`, `generiere_qr_label_pdf`) sind unverändert
und nicht betroffen (`renderPDF.draw`, keine `renderPM`-Abhängigkeit).
- **Bugfix 2026-09-10:** Portal-Link war fest auf `v0.5.apk` verlinkt,
dadurch nach dem v0.6.0-Build stale (zeigte auf eine ältere Version, ohne
dass ein Frontend-Deploy das automatisch mitbekommen hätte).
+15 -17
View File
@@ -1,27 +1,25 @@
import io
from reportlab.graphics import renderPM
from reportlab.graphics.barcode import qr
from reportlab.graphics.shapes import Drawing
import qrcode
# CI-Fund 2026-09-10: reportlab.graphics.renderPM braucht einen nativen
# Backend (_rl_renderPM-Extension oder rlPyCairo) - auf dem CI-Runner (Python
# 3.13) war keins davon lauffähig installiert ("cannot import desired
# renderPM backend rlPyCairo"), reine PDF-Vektorausgabe (label.py) war davon
# NICHT betroffen, nur die reine PNG-Ausgabe hier. Reiner Python-QR-Encoder
# (qrcode + Pillow, ohnehin schon transitive Abhängigkeit über
# python-barcode[images]/label.py) umgeht das nativ kompilierte Backend
# komplett - robuster über Python-Versionen/Plattformen hinweg.
_ZIELGROESSE = 220
def generiere_qr_png(inhalt: str) -> bytes:
"""ASSET-010: rendert einen beliebigen Text (hier: Signier-Seiten-URL) als
PNG - reine Bild-Ausgabe statt PDF-Label (label.py), fürs direkte Anzeigen
im Ausgabe-Dialog des Portals."""
qr_code = qr.QrCodeWidget(inhalt)
bounds = qr_code.getBounds()
breite = bounds[2] - bounds[0]
hoehe = bounds[3] - bounds[1]
skalierung = _ZIELGROESSE / max(breite, hoehe)
zeichnung = Drawing(
_ZIELGROESSE, _ZIELGROESSE, transform=[skalierung, 0, 0, skalierung, -bounds[0] * skalierung, -bounds[1] * skalierung]
)
zeichnung.add(qr_code)
"""ASSET-010/FLUT-001: rendert einen beliebigen Text als PNG - reine
Bild-Ausgabe (kein PDF-Label wie label.py), fürs direkte Anzeigen im
Portal oder Einbetten in eine Download-Seite."""
bild = qrcode.make(inhalt, border=2)
bild = bild.resize((_ZIELGROESSE, _ZIELGROESSE))
puffer = io.BytesIO()
renderPM.drawToFile(zeichnung, puffer, fmt="PNG")
bild.save(puffer, format="PNG")
return puffer.getvalue()
+1
View File
@@ -20,6 +20,7 @@ dependencies = [
"aiosmtplib>=3.0,<3.1",
"python-barcode[images]>=0.15,<0.16",
"reportlab>=4.2,<4.3",
"qrcode[pil]>=7.4,<7.5",
"slowapi>=0.1.9,<0.2",
"sentry-sdk[fastapi]>=2.17,<2.18",
]