"""Résolution centralisée des chemins (données utilisateur et ressources). Gère trois contextes d'exécution : - **Développement** : lancé depuis les sources. Les données vivent dans ``/data`` et les ressources (frontend buildé) dans ``/frontend/dist``. - **Exécutable empaqueté** (PyInstaller, ex. ``.exe`` Windows) : les données doivent aller dans un dossier utilisateur inscriptible (``%APPDATA%`` sous Windows) — l'exécutable lui-même est souvent en lecture seule (``Program Files``). Les ressources sont extraites dans ``sys._MEIPASS``. - **Surcharge explicite** via variables d'environnement (tests, Docker). """ import os import sys from pathlib import Path APP_NAME = "PlesnaGerance" def is_frozen() -> bool: """Vrai si on tourne depuis un exécutable PyInstaller.""" return getattr(sys, "frozen", False) def get_bundle_dir() -> Path: """Répertoire racine des ressources embarquées (lecture seule). - Empaqueté : ``sys._MEIPASS`` (dossier d'extraction PyInstaller), avec repli sur le dossier de l'exécutable. - Développement : racine du projet (``src/plesna_gerance/paths.py`` -> 3 crans). """ if is_frozen(): meipass = getattr(sys, "_MEIPASS", None) if meipass: return Path(meipass) return Path(sys.executable).resolve().parent return Path(__file__).resolve().parent.parent.parent def resource_path(*parts: str) -> Path: """Chemin d'une ressource embarquée (ex. ``resource_path('frontend', 'dist')``).""" return get_bundle_dir().joinpath(*parts) def get_data_dir() -> Path: """Répertoire inscriptible des données utilisateur (DB, documents). Priorité : 1. ``PLESNA_DATA_DIR`` si défini ; 2. dossier applicatif utilisateur si empaqueté ; 3. ``/data`` en développement (comportement historique). """ env = os.environ.get("PLESNA_DATA_DIR") if env: return Path(env) if is_frozen(): if sys.platform == "win32": base = Path(os.environ.get("APPDATA") or Path.home()) elif sys.platform == "darwin": base = Path.home() / "Library" / "Application Support" else: base = Path( os.environ.get("XDG_DATA_HOME") or (Path.home() / ".local" / "share") ) return base / APP_NAME return get_bundle_dir() / "data"