Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
8.5 KiB
Report PDF nel pacchetto Windows
Questa cartella contiene quello che serve perché i report PDF di TieMeasureFlow
(src/backend/services/report_service.py: Jinja2, Plotly con Kaleido 1.2.0, WeasyPrint 68.1)
funzionino su Windows, dentro il pacchetto, senza Internet. Riferimento: TieMeasureFlow#78
(parte del pacchetto Windows, madre #76).
Come funziona
Un report SPC passa da due componenti nativi che su Windows non arrivano con pip:
- WeasyPrint disegna il PDF e carica a runtime le DLL di Pango/GTK
(
libgobject-2.0-0,libpango-1.0-0,libharfbuzz-0,libharfbuzz-subset-0,libfontconfig-1,libpangoft2-1.0-0e le loro dipendenze). - Kaleido 1.x trasforma i grafici Plotly in SVG pilotando un browser Chromium già installato (non porta più Chromium con sé). Su ogni Windows 10/11 c'è Edge.
Le DLL: prendi-gtk.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File packaging\windows\pdf\prendi-gtk.ps1 -Destinazione <cartella>
- Scarica da
repo.msys2.org(ucrt64) 21 pacchetti pinnati con sha256 (nome file e hash stanno nello script), verifica l'hash, estrae solo le 27 DLL necessarie,etc\fontsdi fontconfig e le licenze. - Idempotente: se la cartella è già pronta (file
.gtk-pinuguale ai pin dello script) esce subito. - Se un hash non coincide fallisce e non lascia mezza cartella.
- I pacchetti scaricati stanno in
%LOCALAPPDATA%\Tielogic\tmf-gtk-cache(-Cacheper cambiarla). - Serve Internet solo alla build. Estrae
.zstcontar.exedi Windows (verificato: bsdtar 3.8.9 con zstd); setar.exenon sa di zstd ripiega suuv run --with zstandard. - Gira da utente non admin con PowerShell 5.1.
- ⚠️
repo.msys2.orgtiene solo le versioni recenti: se un file pinnato sparisce (404) vanno aggiornati nome e sha256 dal dbhttps://repo.msys2.org/mingw/ucrt64/ucrt64.dbe rifatto il test. Conservare la cache (Wasabi o NAS) evita la corsa contro il repository.
Il piano C copia <cartella> in P\gtk\ (P = cartella programma).
Variabili d'ambiente (le imposta avvio.py, piano C)
| Variabile | Valore | Perché |
|---|---|---|
WEASYPRINT_DLL_DIRECTORIES |
<P>\gtk |
WeasyPrint chiama os.add_dll_directory su ogni cartella (separatore ;) prima di caricare le DLL. Va impostata prima di importare weasyprint (lo fa report_service all'import). |
BROWSER_PATH |
msedge.exe o chrome.exe |
Choreographer (sotto Kaleido) la legge da sé e ha la precedenza su ogni ricerca (verificato: un percorso inesistente dà FileNotFoundError). Senza la variabile Kaleido cerca Edge/Chrome da solo (registro e percorsi tipici). Nessun codice in report_service.py per questo. |
Fontconfig non richiede variabili: trova etc\fonts accanto alle DLL (verificato). Se manca etc\fonts
WeasyPrint stampa "Fontconfig error: Cannot load default config file". I font dei report vengono da
C:\Windows\Fonts.
MathJax: la modifica a report_service.py
Kaleido 1.x inserisce nella pagina di render uno <script> MathJax da cdnjs.cloudflare.com anche quando i
grafici non hanno formule. Misurato su daitarn con Edge: con rete che scarta i pacchetti ogni grafico aspetta
~19 s (due grafici per report SPC); con rete che rifiuta subito ~2 s. report_service.py imposta
pio.defaults.mathjax su un file .js vuoto in %TEMP% (tmf-mathjax-vuoto.js): nessuna richiesta di rete,
report SPC in ~7 s anche a rete bloccata. Se un giorno i grafici useranno LaTeX, qui serve un MathJax locale.
plotly.min.js invece è già locale (dentro il pacchetto plotly).
Flag Nuitka e dati da includere (per build.ps1, piano C)
⚠️ Stato: ricavati leggendo i sorgenti installati (versioni del uv.lock); non provati con una build
Nuitka: la verifica è la prima build di C. I dati e i metadati sono quelli che il codice legge davvero da disco.
Dati dei pacchetti (file non .py letti a runtime):
--include-package-data=weasyprint # css/html5_ua.css, html5_ph.css, html5_ua_form.css, pdf/sRGB2014.icc
--include-package-data=pyphen # dictionaries/*.dic (84 file, sillabazione)
--include-package-data=kaleido # vendor/kaleido_scopes.js (pagina di render)
--include-package-data=plotly # package_data/plotly.min.js (Kaleido lo cerca come file accanto a plotly/__init__), templates/*.json, validators/_validators.json
--include-package-data=tzdata # zoneinfo: Windows non ha il database IANA (vedi sotto)
--include-data-dir=src/backend/templates=src/backend/templates # Jinja2: report_service legge i .html dal disco
choreographer/resources/last_known_good_chrome.json serve solo al comando che scarica Chrome: non serve.
Metadati delle distribuzioni (importlib.metadata.version al momento dell'import): senza, import plotly e
Kaleido falliscono con PackageNotFoundError:
--include-distribution-metadata=plotly
--include-distribution-metadata=kaleido
Import dinamici che l'analisi statica di Nuitka può perdere:
--include-package=fontTools # ttLib/ttFont.py importa le tabelle con __import__("fontTools.ttLib.tables." + tag)
--include-package=plotly # _plotly_utils/importers.py: importlib.import_module lazy dei moduli graph_objs
--include-package=_plotly_utils
--include-module=_cffi_backend # WeasyPrint usa cffi in modalita' ABI (dlopen), serve il modulo C di cffi
--include-package=weasyprint
--include-package=kaleido
--include-package=choreographer
Altre note per C:
- WeasyPrint salta
os.add_dll_directorysesys.frozenesiste (weasyprint/text/ffi.py). Nuitka di norma non lo imposta (PyInstaller sì): se inTieMeasureFlow.exele DLL non si trovassero, chiamareos.add_dll_directory(<P>\gtk)daavvio.pyprima dell'import. - Le DLL non vanno compilate né incluse da Nuitka: restano file in
P\gtk\. - Il controllo "nessun
.py" dibuild.ps1non deve scandiregtk\(non ci sono.py, ma è meglio saperlo) nélicenze\. tzdatamanca dapyproject.toml: su WindowsZoneInfo("Europe/Rome")(usato dasrc/backend/utils/tempo.py, quindi da ogni report) dàZoneInfoNotFoundError. Va aggiuntotzdata; sys_platform == 'win32'agli extra server e client (o al gruppowindows) e il frontend (src/frontend/flask_app/app.pyusaZoneInfo) ne ha bisogno allo stesso modo.pdfplumberè già nell'extraserver(il test lo usa per leggere i PDF).
Licenze delle DLL
Le DLL sono binari MSYS2/MinGW (ucrt64) non modificati, collegati dinamicamente. prendi-gtk.ps1 mette in
<cartella>\licenze\ i testi di licenza di ogni pacchetto più un <pacchetto>.txt con nome del file e licenza.
L'installer deve includere gtk\licenze\.
| Libreria | Licenza |
|---|---|
| Pango, GLib/GObject/GIO, fribidi, libthai, libdatrie, graphite2, libintl (gettext-runtime), libiconv | LGPL 2.1 o successive |
| FreeType | FTL oppure GPL 2+ (si sceglie FTL) |
| HarfBuzz, expat, libffi, brotli, fontconfig | MIT / permissiva |
| libpng, zlib-ng, bzip2, pcre2 | permissive (libpng, Zlib, bzip2, BSD-3) |
| libgcc, libstdc++ | GPL 3 con GCC Runtime Library Exception (ridistribuzione libera) |
| libwinpthread | MIT e BSD-3 |
Per le librerie LGPL, chi riceve il pacchetto può sostituire le DLL (sono file separati in gtk\); i sorgenti
sono pubblici su MSYS2 (https://packages.msys2.org/), e l'elenco esatto delle versioni è nello script.
Test
src/backend/tests/test_report_windows.py (saltato fuori da Windows, senza DLL, senza Edge/Chrome o senza
tzdata): in un sottoprocesso con WeasyPrint vero (il conftest.py altrimenti lo sostituisce con un
mock) genera su SQLite in memoria il report SPC (carta di controllo e istogramma) e quello a tabella, e
controlla con pdfplumber byte %PDF-, almeno una pagina, titoli dei grafici e segni vettoriali.
# DLL (una volta) e test
powershell -NoProfile -ExecutionPolicy Bypass -File packaging\windows\pdf\prendi-gtk.ps1 -Destinazione packaging\windows\pdf\gtk
uv run --python 3.13 --extra server --extra dev pytest src/backend/tests/test_report_windows.py -q
packaging/windows/pdf/gtk/ e cache/ sono in .gitignore: le DLL non si committano.
Prova a rete bloccata
HTTP_PROXY/HTTPS_PROXY non bastano: Edge e Chrome usano il proxy di sistema di Windows. Per provare davvero
il PC senza Internet: impostare temporaneamente il proxy di sistema (Impostazioni, Rete, Proxy) su un indirizzo
morto (127.0.0.1:9 rifiuta subito; 10.255.255.1:8080 scarta i pacchetti, il caso peggiore), generare i
report e ripristinare il proxy. Esito del 2026-10-17 con proxy che scarta i pacchetti: report SPC e report a
tabella completi in ~7 s.