Files
anonymisation/gui_v6/profile_view.py
Domi31tls a9e8b2c2e6 feat(gui): addenda Dom GUI V6 — sous-onglet Profils, libellés, aide, bêta
Suite des retours Dom sur la GUI V6 (par-dessus 6a0a581).

Addendum Profils / Réglages :
- Nouveau sous-onglet Administration « 👤 Profils » : le profil actif devient
  un objet lisible (nom, description, masque requis, template, listes locales
  avec compteurs) — données réelles lues depuis profile_defaults.
- Fenêtre « Tableau des termes » (terms_table_window.py) : table scrollable
  avec recherche/filtre, colonnes Type/Terme/Source ; reste lisible à 50+
  termes. Ajouter/éditer/supprimer désactivés « (à venir) » (écriture par
  profil non câblée).
- Réglages : « Profil métier » → « Profil d'anonymisation », « Sortie… » →
  « Dossier de sortie… » (+ infobulle), hints moteurs (standard/optionnel/
  plus lent), bouton « Voir le profil », « Ouvrir le tableau des termes ».
- Aide « ? » + infobulles (ui_kit.attach_tooltip) près des éléments ambigus.
- profile_view.py : logique pure (résumé profil + lignes du tableau),
  testable sans display.

Addendum bêta : en-tête « aivanonym » + badge « bêta », titre fenêtre
« … — bêta ». Détail version conservé dans À propos.

tests/unit/test_gui_v6_profiles.py + ajouts shell. 237 tests unit OK
(228 → 237, 0 régression), self-test GUI V6 OK, navigation des 5 sous-onglets
+ thème OK. V5/moteur/app_aivanov/profile_defaults non touchés, 0 dépendance.
Aucun build/push sans GO Dom — validation visuelle Dom attendue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:02:54 +02:00

70 lines
2.3 KiB
Python

"""Vue lisible d'un profil d'anonymisation (logique pure, testable sans display).
Un profil de ``profile_defaults`` est un dict riche (label, description,
require_manual_mask, force_disable_vlm, preferred_manual_mask_template,
param_lists). Ce module en extrait un résumé affichable et les lignes du
« tableau des termes » pour les utilisateurs non informaticiens.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Optional
# Ordre + libellés lisibles des listes locales d'un profil.
LIST_LABELS = {
"whitelist_phrases": "À conserver",
"blacklist_force_mask_terms": "À masquer",
"additional_stopwords": "À ignorer",
}
@dataclass
class ProfileSummary:
key: str
label: str
description: str
require_manual_mask: bool
mask_template: str # "" si aucun
disable_vlm: bool
list_counts: dict[str, int]
def summarize_profile(key: str, profile: Optional[dict[str, Any]]) -> ProfileSummary:
profile = profile or {}
param_lists = profile.get("param_lists") or {}
counts = {
label: len(param_lists.get(raw) or [])
for raw, label in LIST_LABELS.items()
}
return ProfileSummary(
key=key,
label=str(profile.get("label") or key or ""),
description=str(profile.get("description") or ""),
require_manual_mask=bool(profile.get("require_manual_mask")),
mask_template=str(profile.get("preferred_manual_mask_template") or ""),
disable_vlm=bool(profile.get("force_disable_vlm")),
list_counts=counts,
)
def profile_term_rows(profile: Optional[dict[str, Any]]) -> list[tuple[str, str, str]]:
"""Lignes ``(type, terme, source)`` pour le tableau des termes du profil."""
profile = profile or {}
source = str(profile.get("label") or "")
param_lists = profile.get("param_lists") or {}
rows: list[tuple[str, str, str]] = []
for raw, type_label in LIST_LABELS.items():
for term in (param_lists.get(raw) or []):
rows.append((type_label, str(term), source))
return rows
def filter_term_rows(
rows: list[tuple[str, str, str]], query: str
) -> list[tuple[str, str, str]]:
q = (query or "").strip().lower()
if not q:
return list(rows)
return [r for r in rows if q in r[1].lower() or q in r[0].lower()]