- Correction des 907 erreurs ruff (pathlib, imports, nommage, simplifications, docstrings) - Fix déduplication labels dans multiselect nœuds d'arrivée (analyse) - Expansion 1→N label→IDs pour le Sankey (Pays d'opération) - Ajout CLAUDE.md et document de design de l'audit - Mise à jour .gitignore (artefacts tests exploratoires) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.2 KiB
Audit qualite, securite et simplicite - FabNum
Date : 2 mars 2026 Objectif : Bilan de sante complet du projet
Contexte
FabNum est une application Streamlit (Python 3.14) d'analyse de chaines de valeur numeriques. Le projet comprend ~11 200 lignes de code Python reparties sur 6 modules applicatifs, 7 utilitaires, 4 composants UI et des scripts auxiliaires (IA, batch, generation).
Etat actuel
| Metrique | Valeur |
|---|---|
| Securite (Bandit) | 0 vulnerabilite |
| Dependances (pip-audit --local) | 0 vulnerabilite |
| Qualite (ruff) | 907 erreurs |
| Tests | 67 tests, 100% passent |
| Couverture | 16% |
| Bugs averes | 1 (F821 nom indefini) |
| CLAUDE.md | Absent |
Plan par phases
Phase 1 : Critique (bugs et erreurs dangereuses)
Objectif : Corriger les problemes qui causent ou masquent des bugs.
| Regle | Nb | Description |
|---|---|---|
| F821 | 1 | Nom indefini ingested_section_ids dans scripts/generer_analyse.py:471 |
| E722 | 5 | except: nu (masque toutes les exceptions y compris KeyboardInterrupt) |
| B904 | 1 | raise sans from dans un except (perte de contexte d'erreur) |
| W605 | 1 | Sequence d'echappement invalide dans une chaine |
Total : 8 erreurs. Effort : ~30 minutes.
Verification : ruff check . --exclude venv,pgpt,.git --select F821,E722,B904,W605
Phase 2 : Nettoyage automatique (ruff --fix)
Objectif : Appliquer les 330 corrections automatiques sans risque.
Commande : ruff check . --exclude venv,pgpt,.git --fix
Principales corrections :
- W293 (125) : Espaces sur lignes vides
- I001 (41) : Imports non tries
- D212 (38) : Docstrings multi-lignes mal formatees
- F401 (27) : Imports inutilises
- UP006 (27) : Annotations type obsoletes (List -> list, Dict -> dict)
- RET505 (16) : Else superflu apres return
- W291 (15) : Espaces en fin de ligne
- Autres (41) : UP009, UP015, F541, D202, W292, UP007, UP024, SIM114, SIM300, UP012
Verification apres fix : relancer les 67 tests pour confirmer aucune regression.
Phase 3 : Qualite manuelle (577 erreurs restantes)
Objectif : Ameliorer la qualite du code manuellement, par sous-chantiers.
3a. Modernisation pathlib (~220 erreurs)
Remplacer les appels os.path.* et os.makedirs par pathlib.Path.
Regles : PTH118, PTH123, PTH110, PTH208, PTH103, PTH120, PTH122, PTH112,
PTH100, PTH119, PTH204, PTH207, PTH113.
Approche : traiter fichier par fichier, en commencant par utils/ puis app/.
3b. Nommage (88 erreurs)
N803 : noms d'arguments invalides.
Decision a prendre : G (convention NetworkX pour les graphes) est utilise partout.
Options :
- Ignorer N803 globalement pour les arguments nommes
G,G_temp,G_temp_ivc - Renommer en
graphpartout (refactoring lourd) Recommandation : ajouterGa la liste des noms acceptes dans la config ruff.
3c. Documentation (90 erreurs)
- D103 (35) : Fonctions publiques sans docstring
- D415 (26) : Docstrings sans ponctuation finale
- D200 (14) : Docstrings multi-lignes inutiles
- D205 (12) : Ligne vide manquante apres resume de docstring
- D417 (2) : Parametres non documentes
- D301 (1) : Sequence d'echappement dans docstring
3d. Code inutilise (~53 erreurs)
- B007 (30) : Variables de boucle inutilisees (remplacer par
_) - ARG001 (11) : Arguments de fonction inutilises
- ARG002 (7) : Arguments de methode inutilises
- F841 (5) : Variables locales inutilisees
3e. Imports (46 erreurs)
- E402 (29) : Imports pas en haut de fichier
Note : certains sont voulus dans Streamlit (imports apres st.set_page_config)
Decision : ajouter
# noqa: E402pour les cas legitimes - UP035 (17) : Imports deprecies (typing.List -> list, etc.)
3f. Simplifications (~59 erreurs)
- RET504 (23) : Assignation inutile avant return
- SIM108 (7) : If/else remplacable par expression ternaire
- SIM105 (6) : Try/except remplacable par contextlib.suppress
- SIM102 (5) : If imbriques collapsibles
- SIM201 (4) : Negation de comparaison (not x == y -> x != y)
- RET503 (4) : Return implicite
- Autres (10) : C401, C408, C405, E701, E741, PIE810, SIM103, SIM117, SIM210, UP038
Phase 4 : Couverture de tests (16% -> 40%)
Objectif : Couvrir les modules critiques qui sont a 0%.
Priorite haute :
- utils/persistance.py (0%, 112 lignes) : coeur de la gestion de session
- app/fiches/utils/dynamic/minerai/minerai.py (4%, 585 lignes) : module le plus gros
- app/fiches/generer.py (12%, 113 lignes) : generation de fiches
Priorite moyenne :
- app/personnalisation/ (0%, ~253 lignes)
- app/plan_d_action/ (0%, ~67 lignes interface)
- app/visualisations/ (0%, ~133 lignes)
Priorite basse :
- app/ia_nalyse/ (0%, 114 lignes) : depend d'un service externe
- utils/translations.py (28%)
- utils/visualisation.py (0%)
Note : les modules Streamlit sont difficiles a tester unitairement. Strategie : tester la logique metier en l'isolant de l'interface Streamlit.
Phase 5 : Simplification / Refactoring
Objectif : Decouper les gros fichiers pour ameliorer la maintenabilite.
Candidats :
- minerai.py (~585 lignes) : decouper par type de section (header, body, indices, etc.)
- modification.py (~341 lignes) : separer logique de donnees et interface
- fabnum.py (217 lignes) : extraire
get_total_bytes_for_sessionetcharger_themedans un moduleutils/session.pyou similaire
Phase bonus : Documentation projet
- Creer un CLAUDE.md avec les conventions du projet (structure, nommage, outils, commandes de dev, decisions architecturales)
Ordre d'execution recommande
- Phase 1 (critique) - a faire immediatement
- Phase 2 (auto-fix) - dans la foulee
- Phase 3b (nommage - decision sur
G) - debloquer avant le reste - Phase 3a (pathlib) - le plus gros chantier, fichier par fichier
- Phase 3d (code inutilise) - rapide
- Phase 3e (imports) - rapide
- Phase 3f (simplifications) - au fil de l'eau
- Phase 3c (documentation) - au fil de l'eau
- Phase 4 (tests) - en parallele des phases 3
- Phase 5 (refactoring) - une fois les tests en place
- Phase bonus (CLAUDE.md) - a tout moment
Criteres de succes
| Metrique | Avant | Objectif | Resultat |
|---|---|---|---|
| Erreurs ruff | 907 | < 50 | 0 |
| Couverture tests | 16% | >= 40% | 35% (448 tests) |
| Bugs averes | 1 | 0 | 0 |
| CLAUDE.md | Absent | Present | Present |
Resultats de l'audit (2 mars 2026)
Phase 1 : COMPLETE
- 8 erreurs critiques corrigees (F821, E722, B904, W605)
Phase 2 : COMPLETE
- 330 corrections automatiques appliquees avec ruff --fix
Phase 3 : COMPLETE
- 907 -> 0 erreurs ruff
- Migration complete vers pathlib (PTH)
- Ajout N803 aux ignores (convention NetworkX G)
- Corrections manuelles via 5 agents paralleles (RET, SIM, B007, D*, PTH)
Phase 4 : COMPLETE (35% au lieu de 40% vise)
- 67 -> 448 tests (+381 tests, x6.7)
- 14 modules a 100% de couverture
- Modules non-testes : principalement interface Streamlit (difficile a tester unitairement)
- La couverture restante concerne des modules UI fortement couples a Streamlit
Phase 5 : ANALYSEE (refactoring deporte)
- Candidats identifies : minerai.py (577L), modification.py (341L), fabnum.py (212L)
- Decision : refactoring deporte car fortement couple a Streamlit, risque eleve pour benefice limite dans le cadre de l'audit
- Recommandation : refactorer incrementalement lors des evolutions fonctionnelles
Bonus : COMPLETE
- CLAUDE.md cree avec conventions du projet