Standards Qualité
Ce projet respecte les standards de qualité pour un projet Python moderne.
Voir aussi : Tests et Coverage (coverage 93%), Pipeline CI/CD (pipeline automatisé), Architecture Technique (stack technique)
Gestion de Projet
Structure Cohérente
Packages organisés :
utils/,visualization/,data/Modules séparés par fonctionnalité
Séparation logique code/tests/documentation
Environnement Python
Gestionnaire moderne :
uv(remplaçant pip)Configuration :
pyproject.tomlEnvironnement virtuel isolé
Dépendances versionnées
Git et GitHub
Commits réguliers et descriptifs
Branches de développement
Pull Requests avec review
Historique traçable
Documentation
README.md complet (installation, utilisation)
Documentation Sphinx auto-générée
Guides techniques (CI/CD, tests, S3)
Docstrings sur toutes les fonctions
Streamlit
Interface utilisateur intuitive
Widgets interactifs (sliders, selectbox)
Storytelling des analyses
Graphiques Plotly dynamiques
Programmation
Programmation Orientée Objet
Classes implémentées dans le projet :
Classe DataLoader (data.loaders)
Gestion du chargement de données avec exceptions :
class DataLoader:
def load_recipes(self) -> pl.DataFrame:
"""Charge recettes depuis S3 avec gestion erreurs."""
def load_ratings(
self,
min_interactions: int = 100,
return_metadata: bool = False,
verbose: bool = False
) -> pl.DataFrame | tuple:
"""Charge ratings avec options configurables."""
Hiérarchie Exceptions (exceptions.py)
6 classes d’exceptions personnalisées :
class MangetamainError(Exception):
"""Exception de base."""
class DataLoadError(MangetamainError):
"""Erreur chargement S3/DuckDB."""
def __init__(self, source: str, detail: str): ...
class AnalysisError(MangetamainError):
"""Erreur analyse statistique."""
class ConfigurationError(MangetamainError):
"""Erreur configuration."""
class DatabaseError(MangetamainError):
"""Erreur opérations DuckDB."""
class ValidationError(MangetamainError):
"""Erreur validation données."""
Autres Classes
Configuration environnement (logging, détection preprod/prod)
Utilitaires graphiques (application thème, gestion couleurs)
Type Hinting
Annotations de types complètes :
def apply_chart_theme(fig: go.Figure, title: str = None) -> go.Figure:
"""Applique le thème à un graphique."""
pass
def get_ratings_longterm(
min_interactions: int = 100,
return_metadata: bool = False,
verbose: bool = False
) -> pd.DataFrame:
"""Charge les ratings depuis S3."""
pass
Respect PEP8
Validation automatique avec
flake8Formatage avec
blackLigne maximale : 88 caractères
Pipeline CI vérifie à chaque push
Gestion des Exceptions
Try/except personnalisés avec messages clairs :
try:
data = load_from_s3(bucket, key)
except boto3.exceptions.NoCredentialsError:
st.error("Credentials S3 introuvables. Vérifier 96_keys/credentials")
except Exception as e:
st.error(f"Erreur chargement données : {e}")
return None
Logging
Système Loguru 0.7.3 complet avec séparation PREPROD/PROD :
Architecture : 2 fichiers (debug.log, errors.log) par environnement
Détection auto : Variable
APP_ENVou path automatiqueRotation : 10 MB (debug), 5 MB (errors) avec compression
Thread-safe :
enqueue=Truepour Streamlit multithreadBacktrace : Diagnostic complet des erreurs
from loguru import logger
def load_data():
try:
logger.info("Starting data load")
data = load_from_s3()
logger.success(f"Loaded {len(data)} records")
except Exception as e:
logger.error(f"Load failed: {e}")
raise
Voir : Architecture Technique section Logging pour configuration complète.
Événements Loggués
L’application Streamlit enregistre 21 événements dans les fichiers de log.
main.py (13 événements)
Démarrage application:
logger.info(519) : « 🚀 Enhanced Streamlit application starting »logger.info(833) : « ✅ Application fully loaded »logger.info(837) : « 🌟 Starting Enhanced Mangetamain Analytics »
Ressources et vérifications:
logger.warning(527) : « CSS file not found: {css_path} »logger.warning(633) : « S3 not accessible: {e} »logger.warning(636) : « Unexpected error checking S3: {e} »
Erreurs analyses:
logger.warning(246) : « Erreur lors de l’analyse de {table}: {e} »logger.error(315) : « DatabaseError in temporal analysis: {e} »logger.error(318) : « AnalysisError in temporal analysis: {e} »logger.error(321) : « Unexpected error in temporal analysis: {e} »logger.error(381) : « DatabaseError in user analysis: {e} »logger.error(384) : « AnalysisError in user analysis: {e} »logger.error(387) : « Unexpected error in user analysis: {e} »
Chargement données (data/loaders.py - 8 événements)
Le chargement des fichiers Parquet depuis S3 génère des logs détaillés avec gestion d’erreurs via DataLoadError :
Chargement recettes :
logger.error(40) : "Module mangetamain_data_utils introuvable: {e}"logger.info(47) : "Chargement recettes depuis S3 (Parquet)"logger.info(49) : "Recettes chargées: {len(recipes)} lignes"logger.error(52) : "Échec chargement recettes depuis S3: {e}"
Chargement ratings :
logger.error(81) : "Module mangetamain_data_utils introuvable: {e}"logger.info(88) : "Chargement ratings depuis S3 (Parquet) - min_interactions={min_interactions}"logger.info(98/100) : "Ratings chargés: {len(data)} lignes (avec metadata)" ou "Ratings chargés: {len(result)} lignes"logger.error(103) : "Échec chargement ratings depuis S3: {e}"
Répartition par niveau:
INFO : 7 événements (3 démarrage + 4 chargement données)
WARNING : 4 événements (CSS, S3, analyses)
ERROR : 10 événements (6 analyses + 4 chargement données)
Sécurité
Credentials S3 dans fichier gitignore (
96_keys/)Secrets GitHub chiffrés
Pas de tokens en clair dans le code
Validation des inputs utilisateurs
Tests et Qualité
Tests Unitaires
Framework : pytest 8.5.0
Nombre : 118 tests
Résultat : 118 tests passent
Organisation :
tests/unit/+50_test/
Coverage
Objectif : >= 90%
Atteint : 93%
Outil : pytest-cov
Rapport : HTML avec lignes manquantes
Métriques par Module
Module |
Coverage |
Tests |
|---|---|---|
utils/color_theme.py |
97% |
35 |
utils/chart_theme.py |
100% |
10 |
visualization/trendlines.py |
100% |
8 |
visualization/ratings.py |
90-100% |
5-14 |
data/cached_loaders.py |
78% |
3 |
Commentaires
Documentation inline des sections complexes
Explication des algorithmes
Références aux sources de données
Notes sur les optimisations
Docstrings
Format : Google Style
Couverture : Toutes fonctions/classes/modules
Validation : pydocstyle dans CI
Exemple :
def calculate_seasonal_patterns(df: pd.DataFrame) -> pd.DataFrame:
"""Calcule les patterns saisonniers des recettes.
Analyse la distribution mensuelle des recettes et identifie
les pics d'activité saisonniers.
Args:
df: DataFrame avec colonnes 'date' et 'recipe_id'
Returns:
DataFrame avec patterns saisonniers agrégés par mois
Raises:
ValueError: Si colonnes requises manquantes
"""
pass
Documentation Sphinx
Génération automatique depuis docstrings
Theme Read the Docs professionnel
API documentation complète
Guides utilisateur (installation, usage, architecture)
CI/CD
Pipeline CI
Vérifications automatiques à chaque push :
PEP8 : flake8 avec config
.flake8Docstrings : pydocstyle (convention Google)
Tests : pytest avec coverage >= 90%
Quality : black, mypy (optionnel)
Exécution Automatique
Sur push vers branche de développement
Sur Pull Request vers main
Sur merge vers main
Bloque le merge si tests échouent
CD PREPROD
Déploiement automatique sur https://mangetamain.lafrance.io/
Déclenché en parallèle du CI (pas d’attente)
Déploiement ultra-rapide : ~40 secondes
Rollback automatique si CI échoue
Runner self-hosted (VM dataia)
Health checks automatiques
Notifications Discord
CD PRODUCTION
Déploiement manuel sur https://backtothefuturekitchen.lafrance.io/
Confirmation obligatoire (taper « DEPLOY »)
Backup automatique avant déploiement
Rollback documenté si échec
Notifications Discord avec détails
Alerting
Notifications Discord temps réel :
Démarrage déploiement
Succès/échec avec détails
Instructions rollback si échec
Historique complet des déploiements
Choix Techniques Avancés
Base de Données OLAP
DuckDB - Base de données columnar haute performance :
Performance : 10-100x plus rapide que SQLite sur agrégations
Zero-copy : Lecture directe Parquet sans import
Volume : 581 MB, 7 tables
Données : 178K recettes, 1.1M+ interactions
Runner Self-Hosted
Infrastructure autonome : Déploiement sans dépendance VPN
Runner GitHub hébergé sur VM dataia
Déploiement ultra-rapide : 30-40 secondes
Gain productivité : 10 min manuelles → 30s automatiques
Disponibilité : 24/7 sans intervention
Architecture Multi-Environnement
Isolation complète PREPROD/PROD :
Bases de données : Distinctes par environnement
Logs : Niveau debug (PREPROD), errors only (PROD)
Variables : Environment-specific configuration
Ports : 8500 (PREPROD) vs 8501 (PROD)
Résumé Standards
Standard |
Statut |
Détails |
|---|---|---|
Structure projet |
✅ |
Packages, modules |
Environnement Python |
✅ |
uv + pyproject.toml |
Git + GitHub |
✅ |
Commits réguliers |
README.md |
✅ |
Complet |
Streamlit |
✅ |
UX interactive |
POO |
✅ |
DataLoader + hiérarchie exceptions |
Type Hinting |
✅ |
Complet |
PEP8 |
✅ |
100% compliance |
Exceptions personnalisées |
✅ |
Hiérarchie 6 classes |
Logger |
✅ |
Loguru complet |
Sécurité |
✅ |
Secrets protégés |
Tests unitaires |
✅ |
118 tests |
Coverage >= 90% |
✅ |
93% atteint |
Commentaires |
✅ |
Sections complexes |
Docstrings |
✅ |
Google Style |
Documentation Sphinx |
✅ |
Auto-générée |
Pipeline CI |
✅ |
PEP8 + tests + cov |
Exécution auto |
✅ |
Push + PR + merge |
CD (bonus) |
✅ |
PREPROD + PROD |