From 4b5925306e18ff0b4834be671e69d66a20d1a3e1 Mon Sep 17 00:00:00 2001 From: Domi31tls Date: Tue, 14 Apr 2026 10:28:11 +0200 Subject: [PATCH] =?UTF-8?q?feat(gui):=20exposer=20additional=5Fstopwords?= =?UTF-8?q?=20dans=20le=20panneau=20Param=C3=A8tres=20avanc=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Troisième liste paramétrable dans la GUI v5.4, après whitelist_phrases et blacklist.force_mask_terms : "Mots à ne jamais identifier comme noms". Cible les sigles, acronymes métier locaux, ou termes ALL-CAPS récurrents qui ressemblent à des noms propres mais n'en sont pas. Différence avec la whitelist : - whitelist_phrases : terme spécifique à protéger même s'il a été masqué par regex/NER (filtre final sur l'audit + sous-mots de hits multi-mots) - additional_stopwords : empêche le terme d'être candidat-nom dès l'amont (intégré à _MEDICAL_STOP_WORDS_SET, filtre toutes les étapes) Wired dans _load_params, _save_params, _export_params, _import_params. La nouvelle clé additional_stopwords est incluse dans le JSON d'échange inter-établissements. Co-Authored-By: Claude Opus 4.6 (1M context) --- Pseudonymisation_Gui_V5.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/Pseudonymisation_Gui_V5.py b/Pseudonymisation_Gui_V5.py index 06e0f2a..5d74675 100644 --- a/Pseudonymisation_Gui_V5.py +++ b/Pseudonymisation_Gui_V5.py @@ -576,6 +576,16 @@ class App: color_tag="#fce4ec", ) + # --- Stop-words additionnels (mots à ne jamais identifier comme noms) --- + # Différent de la whitelist : agit en amont, pour les sigles, acronymes, + # termes métier locaux qui ressemblent à des noms mais n'en sont pas. + self._sw_listbox, self._sw_entry = self._build_phrase_list( + self._params_frame, + title="\u26a0 Mots à ne jamais identifier comme noms (sigles, acronymes...) :", + placeholder="Ajouter un mot (ex: sigle local, acronyme métier)...", + color_tag="#fff8e1", + ) + # Boutons sauvegarder + exporter btn_row = tk.Frame(self._params_frame, bg=CLR_BG) btn_row.pack(fill=tk.X, pady=(4, 4)) @@ -1244,6 +1254,12 @@ class App: for term in bl: if term and str(term).strip(): self._bl_listbox.insert(tk.END, str(term).strip()) + # Stop-words additionnels + sw = data.get("additional_stopwords", []) + self._sw_listbox.delete(0, tk.END) + for term in sw: + if term and str(term).strip(): + self._sw_listbox.insert(tk.END, str(term).strip()) except Exception: pass @@ -1255,6 +1271,7 @@ class App: wl = list(self._wl_listbox.get(0, tk.END)) bl = list(self._bl_listbox.get(0, tk.END)) + sw = list(self._sw_listbox.get(0, tk.END)) export_data = { "version": APP_VERSION, @@ -1262,6 +1279,7 @@ class App: "etablissement": "", # à remplir par l'utilisateur "whitelist_phrases": wl, "blacklist_force_mask_terms": bl, + "additional_stopwords": sw, "instructions": ( "Ce fichier contient les paramètres d'anonymisation personnalisés. " "Envoyez-le par email à l'équipe technique pour mise à jour du programme." @@ -1328,13 +1346,23 @@ class App: self._bl_listbox.insert(tk.END, str(term).strip()) added_bl += 1 + # Fusionner stop-words additionnels + new_sw = data.get("additional_stopwords", []) + existing_sw = set(self._sw_listbox.get(0, tk.END)) + added_sw = 0 + for term in new_sw: + if term and str(term).strip() and str(term).strip() not in existing_sw: + self._sw_listbox.insert(tk.END, str(term).strip()) + added_sw += 1 + version = data.get("version", "?") date_exp = data.get("date_export", "?")[:10] messagebox.showinfo( "Import réussi", f"Paramètres importés (v{version}, {date_exp}) :\n\n" f" + {added_wl} phrase(s) ajoutée(s) à la whitelist\n" - f" + {added_bl} terme(s) ajouté(s) à la blacklist\n\n" + f" + {added_bl} terme(s) ajouté(s) à la blacklist\n" + f" + {added_sw} mot(s) ajouté(s) aux stop-words\n\n" f"Cliquez sur « Sauvegarder » pour appliquer.", ) except Exception as e: @@ -1358,6 +1386,9 @@ class App: data["blacklist"] = {} data["blacklist"]["force_mask_terms"] = list(self._bl_listbox.get(0, tk.END)) + # Stop-words additionnels (mots à ne jamais identifier comme noms) + data["additional_stopwords"] = list(self._sw_listbox.get(0, tk.END)) + cfg_path.write_text( yaml.dump(data, allow_unicode=True, default_flow_style=False, sort_keys=False), encoding="utf-8",