"""Résolution du dictionnaires.yml externe éditable (P1-4). Pur : on simule frozen via monkeypatch (sys.frozen / sys.executable / _MEIPASS), aucun display, aucun modèle. """ from __future__ import annotations from pathlib import Path import gui_v6.config_paths as cp def _make_bundle(tmp_path: Path) -> Path: bundle = tmp_path / "bundle" (bundle / "config").mkdir(parents=True) (bundle / "config" / "dictionnaires.yml").write_text("whitelist_phrases: []\n", encoding="utf-8") return bundle def test_dev_returns_repo_config_when_present(monkeypatch): # En dev (non frozen) : pointe la config embarquée si elle existe. monkeypatch.setattr(cp.sys, "frozen", False, raising=False) path = cp.resolve_user_config_path() assert path is not None assert path.name == "dictionnaires.yml" assert path.exists() def test_frozen_copies_bundle_on_first_launch(tmp_path, monkeypatch): bundle = _make_bundle(tmp_path) exe_dir = tmp_path / "exe" exe_dir.mkdir() monkeypatch.setattr(cp.sys, "frozen", True, raising=False) monkeypatch.setattr(cp.sys, "_MEIPASS", str(bundle), raising=False) monkeypatch.setattr(cp.sys, "executable", str(exe_dir / "Anonymisation.exe"), raising=False) out = cp.resolve_user_config_path() expected = exe_dir / "config" / "dictionnaires.yml" assert out == expected assert expected.exists() # copié depuis le bundle au 1er lancement assert expected.read_text(encoding="utf-8") == "whitelist_phrases: []\n" def test_frozen_keeps_existing_user_config(tmp_path, monkeypatch): bundle = _make_bundle(tmp_path) exe_dir = tmp_path / "exe" (exe_dir / "config").mkdir(parents=True) user_cfg = exe_dir / "config" / "dictionnaires.yml" user_cfg.write_text("whitelist_phrases: [HOPITAL_LOCAL]\n", encoding="utf-8") monkeypatch.setattr(cp.sys, "frozen", True, raising=False) monkeypatch.setattr(cp.sys, "_MEIPASS", str(bundle), raising=False) monkeypatch.setattr(cp.sys, "executable", str(exe_dir / "Anonymisation.exe"), raising=False) out = cp.resolve_user_config_path() assert out == user_cfg # Ne JAMAIS écraser la perso établissement existante. assert "HOPITAL_LOCAL" in out.read_text(encoding="utf-8") def test_dev_returns_none_when_config_missing(tmp_path, monkeypatch): # En dev, si la config embarquée est absente : on renvoie None (pas de création). monkeypatch.setattr(cp.sys, "frozen", False, raising=False) monkeypatch.setattr(cp, "_bundled_config", lambda: tmp_path / "absent" / "dictionnaires.yml") assert cp.resolve_user_config_path() is None def test_frozen_copy_failure_falls_back(tmp_path, monkeypatch): # En frozen, si la copie échoue (ex. droits) : fallback sur la config embarquée, sans crash. bundle = _make_bundle(tmp_path) exe_dir = tmp_path / "exe" exe_dir.mkdir() monkeypatch.setattr(cp.sys, "frozen", True, raising=False) monkeypatch.setattr(cp.sys, "_MEIPASS", str(bundle), raising=False) monkeypatch.setattr(cp.sys, "executable", str(exe_dir / "Anonymisation.exe"), raising=False) def _boom(*_args, **_kwargs): raise PermissionError("accès refusé") monkeypatch.setattr(cp.shutil, "copyfile", _boom) out = cp.resolve_user_config_path() assert out == cp._bundled_config()