G3-A câblage moteur réel (engine_bridge.py) : EngineSettings + NerManagers à chargement paresseux (aucun manager à l'import), kwargs alignés CLI/V5 (make_vector_redaction=False, also_make_raster_burn=True, config_path, use_hf, ner/gliner/camembert_manager, ogc_label) ; make_process_fn engine injectable ; état managers not_loaded/loading/ready/unavailable, échecs optionnels tolérés. G3-B Configuration (config_state.py + tabs/tab_config.py) : ConfigState → EngineSettings, profils via profile_defaults (path injectable), options raster/NER local/profil/sortie, état managers, sections admin-only via admin_mode. G3-C Licence UI (machine_id.py + tab_about) : activation par clef (LicenseClient.activate), bouton vérifier (check), affichage statut, aucun token loggé, aucun appel réseau au démarrage (local_status seul). Intégration : tab_usage exécute via le moteur réel selon ConfigState (make_process_fn), anti double-lancement UI. app.py câble Config↔Usage↔licence. G3-D build-prep : anonymisation_gui_v6_onefile.spec (entry V6, customtkinter + modules gui_v6 en hiddenimports). Installateur Anonymisation.iss produit déjà la cible Anonymisation-Setup.exe. Aucun artefact .exe commité ; build Windows à part. Tests +14 (engine_bridge 8, config_state 6). self-test exit 0, 46 tests gui_v6, 193 tests/unit (0 régression). Moteur/V5/specs CLI intacts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""État de configuration de la GUI V6 (G3-B), testable sans display ni fichiers.
|
|
|
|
Détient les options simples exposées par l'onglet Configuration et sait produire
|
|
des :class:`EngineSettings`. La résolution des profils s'appuie sur
|
|
``profile_defaults`` (jamais modifié) avec injection possible pour les tests.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Callable, List, Optional
|
|
|
|
from gui_v6.engine_bridge import EngineSettings
|
|
|
|
|
|
@dataclass
|
|
class ConfigState:
|
|
"""Options de configuration utilisateur (réglages simples G3-B)."""
|
|
|
|
profile: Optional[str] = None
|
|
raster_burn: bool = True
|
|
use_local_ner: bool = True
|
|
enable_eds: bool = False
|
|
enable_gliner: bool = False
|
|
output_dir: Optional[Path] = None
|
|
ogc_label: Optional[str] = None
|
|
|
|
def to_engine_settings(self, config_path: Optional[Path] = None) -> EngineSettings:
|
|
return EngineSettings(
|
|
make_vector_redaction=False,
|
|
also_make_raster_burn=self.raster_burn,
|
|
config_path=config_path,
|
|
use_local_ner=self.use_local_ner,
|
|
enable_eds=self.enable_eds,
|
|
enable_gliner=self.enable_gliner,
|
|
ogc_label=self.ogc_label,
|
|
profile=self.profile,
|
|
)
|
|
|
|
|
|
def list_profile_keys(lister: Optional[Callable[[], dict]] = None) -> List[str]:
|
|
"""Liste triée des clés de profils. Best-effort : [] si indisponible."""
|
|
if lister is None:
|
|
from profile_defaults import list_effective_profiles
|
|
|
|
lister = list_effective_profiles
|
|
try:
|
|
return sorted(lister().keys())
|
|
except Exception:
|
|
return []
|
|
|
|
|
|
def default_profile_key(getter: Optional[Callable[[], str]] = None) -> Optional[str]:
|
|
"""Clé du profil par défaut, ou None si indisponible."""
|
|
if getter is None:
|
|
from profile_defaults import get_default_profile_key
|
|
|
|
getter = get_default_profile_key
|
|
try:
|
|
return getter()
|
|
except Exception:
|
|
return None
|