feat(gui): GUI V6 G3 — câblage moteur, Configuration, licence UI, build-prep
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>
This commit is contained in:
63
gui_v6/config_state.py
Normal file
63
gui_v6/config_state.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""É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
|
||||
Reference in New Issue
Block a user