# -*- mode: python ; coding: utf-8 -*- """Spec PyInstaller pour Plesna Gérance (application de bureau autonome). À lancer depuis la racine du projet : pyinstaller packaging/plesna_gerance.spec Produit un exécutable unique (onefile, sans console) qui embarque : - le code Python et ses dépendances (FastAPI, uvicorn, pdfplumber, pywebview) ; - le frontend déjà buildé (``frontend/dist``). Le frontend doit être buildé AVANT (``cd frontend && npm run build``). """ from pathlib import Path from PyInstaller.utils.hooks import collect_all, collect_submodules # Racine du projet (le .spec est dans packaging/). ROOT = Path(SPECPATH).resolve().parent # --- Ressources embarquées ------------------------------------------------ datas = [ # Frontend buildé -> extrait dans _MEIPASS/frontend/dist (cf. paths.resource_path) (str(ROOT / "frontend" / "dist"), "frontend/dist"), ] binaries = [] hiddenimports = [] # Dépendances à embarquer en totalité (modules dynamiques mal détectés). for pkg in ("uvicorn", "pdfplumber", "pdfminer", "pypdfium2"): pkg_datas, pkg_binaries, pkg_hidden = collect_all(pkg) datas += pkg_datas binaries += pkg_binaries hiddenimports += pkg_hidden # uvicorn charge ses protocoles/boucles par import dynamique. hiddenimports += collect_submodules("uvicorn") block_cipher = None a = Analysis( [str(ROOT / "packaging" / "app_entry.py")], pathex=[str(ROOT / "src")], binaries=binaries, datas=datas, hiddenimports=hiddenimports, hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=["tkinter"], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name="PlesnaGerance", debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=False, # application fenêtrée, pas de console disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, icon=str(ROOT / "packaging" / "icon.ico") if (ROOT / "packaging" / "icon.ico").exists() else None, )