Code/utils/logger.py
Stéphan Peccini f812fac89e
feat: Amelioration structure - tests, documentation et qualite du code
Cette mise a jour complete ameliore significativement la qualite et la maintenabilite du projet.

1. Extension de la couverture de tests

Couverture globale passee de 8% a 16% (+100%)
- Ajout de 25 nouveaux tests (total: 67 tests, 100% passent)
- Nouveaux fichiers de tests:
  * tests/unit/test_gitea.py (17 tests)
  * tests/unit/test_fiches_tickets.py (8 tests)

Etat de la couverture par module:
- utils/gitea.py: 100%
- utils/widgets.py: 100%
- utils/logger.py: 94%
- app/fiches/utils/tickets/core.py: 77%
- utils/graph_utils.py: 59%

2. Documentation d'architecture complete

Creation de 3 nouveaux documents (30 Ko total):
- docs/ARCHITECTURE.md (15 Ko)
  * Architecture complete du projet
  * Flux de donnees detailles
  * Indices de vulnerabilite (IHH, ISG, ICS, IVC)
  * Structure du graphe NetworkX

- docs/MODULES.md (15 Ko)
  * Guide des 11 modules principaux
  * Exemples de code (15+ snippets)
  * Bonnes pratiques
  * Guide de depannage

- docs/README.md (4 Ko)
  * Index de toute la documentation

Contenu documente:
- 5 modules applicatifs
- 6 modules utilitaires
- 4 indices de vulnerabilite avec formules et seuils
- Conventions de code

3. Reorganisation de la documentation

Structure finale optimisee:
- Racine: README.md (mis a jour) + Instructions.md
- docs/: 11 documents organises par categorie

Fichiers deplaces vers docs/:
- README_connexion.md -> docs/CONNEXION.md
- GUIDE_LOGS.md -> docs/
- GUIDE_RUFF.md -> docs/
- RAPPORT_RUFF.md -> docs/
- RAPPORT_CORRECTIONS_AUTO.md -> docs/
- REFACTORING_REPORT.md -> docs/
- VERIFICATION_LOGS.md -> docs/
- TODO_IA_BATCH.md -> docs/

4. Ajout de docstrings

52 fonctions documentees en style Google (100%)
Documentation en francais avec Args, Returns, Raises

5. Corrections automatiques Ruff

Application de 347 corrections automatiques:
- Formatage du code (line-length: 120)
- Organisation des imports
- Simplifications syntaxiques
- Suppressions de code mort
- Ameliorations de performance

6. Configuration qualite du code

Nouveaux fichiers:
- pyproject.toml: configuration Ruff complete
- .vscode/settings.json: integration Ruff avec formatOnSave
- GUIDE_RUFF.md: documentation du linter
- GUIDE_LOGS.md: documentation du logging
- .gitignore: ajout htmlcov/ pour rapports de couverture

Etat final du projet:
- Linter: Ruff configure (15 regles actives)
- Tests: 67 tests (100% passent)
- Couverture de code: 16%
- Docstrings: 52/52 (100%)
- Documentation: 11 fichiers organises

Impact:
- Tests plus robustes et maintenables
- Documentation technique complete
- Meilleure organisation des fichiers
- Workflow optimise avec Ruff
- Code pret pour integration continue

References:
- Architecture: docs/ARCHITECTURE.md
- Guide modules: docs/MODULES.md
- Tests: tests/unit/
- Configuration: pyproject.toml

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-07 19:00:49 +01:00

109 lines
3.2 KiB
Python

"""Module de logging centralisé pour l'application FabNum.
Ce module fournit une configuration de logging standardisée pour tous les modules
de l'application, avec support de la console et des fichiers.
Usage:
from utils.logger import setup_logger
logger = setup_logger(__name__)
logger.info("Message d'information")
logger.warning("Avertissement")
logger.error("Erreur", exc_info=True)
"""
import logging
import sys
from pathlib import Path
def setup_logger(
name: str,
level: str = "INFO",
log_to_file: bool = True
) -> logging.Logger:
"""Configure un logger avec formatage cohérent pour l'application.
Args:
name: Nom du logger (généralement __name__ du module appelant)
level: Niveau de log (DEBUG, INFO, WARNING, ERROR, CRITICAL)
log_to_file: Si True, écrit aussi dans un fichier logs/
Returns:
Logger configuré avec handlers console et fichier
Examples:
>>> logger = setup_logger(__name__)
>>> logger.info("Application démarrée")
>>> logger.warning("Fichier non trouvé", extra={"file": "config.yaml"})
>>> logger.error("Erreur critique", exc_info=True)
"""
logger = logging.getLogger(name)
# Éviter de reconfigurer si déjà fait
if logger.handlers:
return logger
# Format structuré avec timestamp
formatter = logging.Formatter(
fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# Handler console (stdout)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
console_handler.setLevel(logging.DEBUG) # Console affiche tout
logger.addHandler(console_handler)
# Handler fichier (optionnel)
if log_to_file:
try:
log_dir = Path("logs")
log_dir.mkdir(exist_ok=True)
# Nom de fichier basé sur le module
log_filename = f"{name.replace('.', '_')}.log"
log_file = log_dir / log_filename
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.DEBUG)
logger.addHandler(file_handler)
except (OSError, PermissionError) as e:
# Si impossible d'écrire dans logs/, continuer quand même
console_handler.emit(
logging.LogRecord(
name=name,
level=logging.WARNING,
pathname=__file__,
lineno=0,
msg=f"Impossible de créer le fichier de log: {e}",
args=(),
exc_info=None
)
)
# Définir le niveau global du logger
logger.setLevel(getattr(logging, level.upper(), logging.INFO))
# Empêcher la propagation au logger root (évite doublons)
logger.propagate = False
return logger
def get_logger(name: str) -> logging.Logger:
"""Récupère un logger existant ou en crée un nouveau.
Args:
name: Nom du logger
Returns:
Logger configuré
"""
logger = logging.getLogger(name)
if not logger.handlers:
return setup_logger(name)
return logger