From 434944def60063a79c511de7c54cc37ff5ef9e6c Mon Sep 17 00:00:00 2001 From: Ralph Mayola Date: Sun, 23 Aug 2026 17:53:12 +0200 Subject: [PATCH] Renforce les contrats : types complets et docstrings de methode protegees Co-Authored-By: Claude Opus 5 --- contrats.py | 12 +++++++++--- tests/test_contrats.py | 8 ++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/contrats.py b/contrats.py index 579d54f..8746287 100644 --- a/contrats.py +++ b/contrats.py @@ -5,7 +5,13 @@ le noyau parle au monde extérieur. Tout ce qui dépend d'un système d'exploita d'une bibliothèque d'affichage ou d'un moteur de transcription vit DERRIÈRE l'un d'eux — jamais dans `core.py`, `controller.py` ni `audio_level.py`. """ -from typing import Protocol +from typing import IO, Protocol + +# numpy entre dans ce fichier volontairement minuscule car c'est déjà une +# dépendance dure du projet, et le type du signal audio fait partie du +# contrat : un `Any` implicite laisserait passer un mauvais type sans que +# rien ne bronche. +import numpy as np class Transcripteur(Protocol): @@ -14,7 +20,7 @@ class Transcripteur(Protocol): def warmup(self) -> None: """Charge le modèle une fois, pour que la première dictée ne traîne pas.""" - def transcrire(self, audio) -> str: + def transcrire(self, audio: np.ndarray) -> str: """Rend le texte d'un tableau numpy float32 mono.""" @@ -55,5 +61,5 @@ class Systeme(Protocol): def dossier_donnees(self) -> str: """Dossier des données de l'application (verrou d'instance, réglages).""" - def acquerir_verrou_instance(self, chemin: str): + def acquerir_verrou_instance(self, chemin: str) -> IO | None: """Verrou exclusif non bloquant ; rend le fichier, ou None s'il est pris.""" diff --git a/tests/test_contrats.py b/tests/test_contrats.py index 6f4cb61..d25d1b9 100644 --- a/tests/test_contrats.py +++ b/tests/test_contrats.py @@ -21,6 +21,14 @@ def test_le_contrat_declare_exactement_ses_methodes(contrat, methodes): if not n.startswith("_")] assert sorted(declarees) == sorted(methodes) + # Ce sont les docstrings de MÉTHODE qui portent l'essentiel du contrat + # (la plage [0, 1] de set_level, l'affinité thread, la sémantique de + # retour) : une docstring vidée ici doit rougir, pas seulement celle + # de la classe. + for nom in methodes: + methode = getattr(contrat, nom) + assert methode.__doc__, f"{contrat.__name__}.{nom} doit dire à quoi il sert" + def test_les_contrats_sont_documentes(): for contrat in (Transcripteur, Overlay, Systeme):