Protection multi-instance GUI V6 : mutex kernel nommé sur Windows (partagé avec l'installeur Inno via AppMutex), fcntl exclusif sur POSIX (dev/test). 3 tests unitaires, self-test OK, 0 régression gui_v6 (145 passed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
88 lines
2.7 KiB
Python
88 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Point d'entrée de la GUI V6 de Pseudonymisation.
|
|
|
|
Usage :
|
|
python Pseudonymisation_Gui_V6.py # lance la fenêtre
|
|
python Pseudonymisation_Gui_V6.py --self-test # importe l'app, sort 0, sans fenêtre
|
|
|
|
Le mode ``--self-test`` vérifie que tout le socle GUI V6 s'importe correctement
|
|
(utile en CI / build sans display). Il n'ouvre aucune fenêtre.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
import os
|
|
|
|
# Frozen Windows : désactiver le manager ONNX legacy AVANT tout import du cœur,
|
|
# pour éviter « cannot load module more than once per process » (hotfix CLI 6c6f653).
|
|
os.environ.setdefault("ANON_SKIP_LEGACY_ONNX_MANAGER", "1")
|
|
|
|
|
|
def _self_test() -> int:
|
|
"""Importe les modules du socle GUI V6 sans créer de fenêtre."""
|
|
from gui_v6 import ( # noqa: F401
|
|
app,
|
|
config_state,
|
|
engine_bridge,
|
|
license_client,
|
|
license_store,
|
|
machine_id,
|
|
processing_runner,
|
|
theme,
|
|
ui_kit,
|
|
)
|
|
from gui_v6.tabs import tab_about, tab_config, tab_usage # noqa: F401
|
|
|
|
# Sanity check des contrats publics du socle.
|
|
assert hasattr(app, "AnonymisationApp")
|
|
assert hasattr(license_client, "LicenseClient")
|
|
assert hasattr(license_client, "LicenseStatus")
|
|
assert hasattr(license_store, "LicenseStore")
|
|
assert hasattr(processing_runner, "ProcessingRunner")
|
|
assert hasattr(engine_bridge, "make_process_fn")
|
|
assert hasattr(config_state, "ConfigState")
|
|
assert hasattr(machine_id, "default_machine_id")
|
|
assert hasattr(ui_kit, "Card")
|
|
assert hasattr(theme, "PALETTES") and set(theme.PALETTES) >= {"sombre", "clair", "medical", "neutre"}
|
|
assert hasattr(tab_about, "AboutTab")
|
|
assert hasattr(tab_config, "ConfigTab")
|
|
assert hasattr(tab_usage, "UsageTab")
|
|
print("GUI V6 self-test OK")
|
|
return 0
|
|
|
|
|
|
def main(argv=None) -> int:
|
|
argv = list(sys.argv[1:] if argv is None else argv)
|
|
if "--self-test" in argv:
|
|
return _self_test()
|
|
|
|
from gui_v6.logging_setup import setup_file_logging
|
|
|
|
setup_file_logging()
|
|
|
|
from gui_v6.app import AnonymisationApp
|
|
from gui_v6.single_instance import AlreadyRunningError, SingleInstance
|
|
|
|
guard = SingleInstance()
|
|
try:
|
|
guard.acquire()
|
|
except AlreadyRunningError:
|
|
try:
|
|
import tkinter.messagebox as mb
|
|
|
|
mb.showinfo("Anonymisation", "L'application est déjà ouverte.")
|
|
except Exception:
|
|
print("L'application est déjà ouverte.")
|
|
return 0
|
|
try:
|
|
application = AnonymisationApp()
|
|
application.mainloop()
|
|
finally:
|
|
guard.release()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|