v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
375
verifier_zip_vwb.py
Normal file
375
verifier_zip_vwb.py
Normal file
@@ -0,0 +1,375 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script de vérification du ZIP VWB propre
|
||||
Auteur : Dom, Alice, Kiro - 8 janvier 2026
|
||||
"""
|
||||
|
||||
import zipfile
|
||||
import os
|
||||
import json
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
class VerificateurZipVWB:
|
||||
"""Classe pour vérifier la qualité du ZIP VWB"""
|
||||
|
||||
def __init__(self, nom_zip):
|
||||
self.nom_zip = nom_zip
|
||||
self.dossier_temp = None
|
||||
self.resultats = {}
|
||||
|
||||
def extraire_zip_temporaire(self):
|
||||
"""Extraire le ZIP dans un dossier temporaire"""
|
||||
self.dossier_temp = tempfile.mkdtemp(prefix="verif_vwb_")
|
||||
|
||||
with zipfile.ZipFile(self.nom_zip, 'r') as zipf:
|
||||
zipf.extractall(self.dossier_temp)
|
||||
|
||||
print(f"📁 ZIP extrait dans: {self.dossier_temp}")
|
||||
return True
|
||||
|
||||
def verifier_structure_generale(self):
|
||||
"""Vérifier la structure générale du projet"""
|
||||
print("🏗️ Vérification de la structure...")
|
||||
|
||||
dossiers_requis = [
|
||||
"visual_workflow_builder",
|
||||
"visual_workflow_builder/backend",
|
||||
"visual_workflow_builder/frontend",
|
||||
"visual_workflow_builder/backend/api",
|
||||
"visual_workflow_builder/frontend/src",
|
||||
"visual_workflow_builder/frontend/src/components",
|
||||
]
|
||||
|
||||
fichiers_requis = [
|
||||
"README.md",
|
||||
"version.json",
|
||||
"diagnostic_backend_complet.py",
|
||||
"demarrer_backend_propre.py",
|
||||
"test_systeme_complet.py",
|
||||
"visual_workflow_builder/backend/app.py",
|
||||
"visual_workflow_builder/frontend/package.json",
|
||||
]
|
||||
|
||||
structure_ok = True
|
||||
|
||||
# Vérifier les dossiers
|
||||
for dossier in dossiers_requis:
|
||||
chemin = os.path.join(self.dossier_temp, dossier)
|
||||
if os.path.exists(chemin):
|
||||
print(f" ✅ Dossier: {dossier}")
|
||||
else:
|
||||
print(f" ❌ Dossier manquant: {dossier}")
|
||||
structure_ok = False
|
||||
|
||||
# Vérifier les fichiers
|
||||
for fichier in fichiers_requis:
|
||||
chemin = os.path.join(self.dossier_temp, fichier)
|
||||
if os.path.exists(chemin):
|
||||
print(f" ✅ Fichier: {fichier}")
|
||||
else:
|
||||
print(f" ❌ Fichier manquant: {fichier}")
|
||||
structure_ok = False
|
||||
|
||||
self.resultats['structure'] = structure_ok
|
||||
return structure_ok
|
||||
|
||||
def verifier_conformite_attribution(self):
|
||||
"""Vérifier la conformité de l'attribution"""
|
||||
print("👥 Vérification de l'attribution...")
|
||||
|
||||
fichiers_python = []
|
||||
fichiers_typescript = []
|
||||
fichiers_css = []
|
||||
|
||||
# Parcourir tous les fichiers
|
||||
for root, dirs, files in os.walk(self.dossier_temp):
|
||||
for file in files:
|
||||
chemin_complet = os.path.join(root, file)
|
||||
extension = os.path.splitext(file)[1].lower()
|
||||
|
||||
if extension == '.py':
|
||||
fichiers_python.append(chemin_complet)
|
||||
elif extension in ['.ts', '.tsx']:
|
||||
fichiers_typescript.append(chemin_complet)
|
||||
elif extension == '.css':
|
||||
fichiers_css.append(chemin_complet)
|
||||
|
||||
conformes = 0
|
||||
total = 0
|
||||
|
||||
# Vérifier les fichiers Python
|
||||
for fichier in fichiers_python:
|
||||
total += 1
|
||||
try:
|
||||
with open(fichier, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
if ('Auteur : Dom, Alice, Kiro' in contenu or 'Auteur: Dom, Alice, Kiro' in contenu) and '8 janvier 2026' in contenu:
|
||||
conformes += 1
|
||||
print(f" ✅ {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
else:
|
||||
print(f" ❌ {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
except:
|
||||
print(f" ⚠️ Erreur lecture: {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
|
||||
# Vérifier les fichiers TypeScript
|
||||
for fichier in fichiers_typescript:
|
||||
total += 1
|
||||
try:
|
||||
with open(fichier, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
if 'Auteur : Dom, Alice, Kiro' in contenu and '8 janvier 2026' in contenu:
|
||||
conformes += 1
|
||||
print(f" ✅ {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
else:
|
||||
print(f" ❌ {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
except:
|
||||
print(f" ⚠️ Erreur lecture: {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
|
||||
# Vérifier les fichiers CSS
|
||||
for fichier in fichiers_css:
|
||||
total += 1
|
||||
try:
|
||||
with open(fichier, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
if 'Auteur : Dom, Alice, Kiro' in contenu and '8 janvier 2026' in contenu:
|
||||
conformes += 1
|
||||
print(f" ✅ {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
else:
|
||||
print(f" ❌ {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
except:
|
||||
print(f" ⚠️ Erreur lecture: {os.path.relpath(fichier, self.dossier_temp)}")
|
||||
|
||||
taux_conformite = (conformes / total) * 100 if total > 0 else 100
|
||||
print(f" 📊 Conformité attribution: {conformes}/{total} ({taux_conformite:.1f}%)")
|
||||
|
||||
self.resultats['attribution'] = taux_conformite >= 80
|
||||
return taux_conformite >= 80
|
||||
|
||||
def verifier_version_info(self):
|
||||
"""Vérifier les informations de version"""
|
||||
print("📋 Vérification des informations de version...")
|
||||
|
||||
chemin_version = os.path.join(self.dossier_temp, "version.json")
|
||||
|
||||
if not os.path.exists(chemin_version):
|
||||
print(" ❌ Fichier version.json manquant")
|
||||
self.resultats['version'] = False
|
||||
return False
|
||||
|
||||
try:
|
||||
with open(chemin_version, 'r', encoding='utf-8') as f:
|
||||
version_data = json.load(f)
|
||||
|
||||
champs_requis = ['version', 'date_creation', 'auteurs', 'description', 'conformite']
|
||||
|
||||
for champ in champs_requis:
|
||||
if champ in version_data:
|
||||
print(f" ✅ {champ}: {version_data[champ]}")
|
||||
else:
|
||||
print(f" ❌ Champ manquant: {champ}")
|
||||
self.resultats['version'] = False
|
||||
return False
|
||||
|
||||
# Vérifier la conformité
|
||||
conformite = version_data.get('conformite', {})
|
||||
if conformite.get('langue') == 'français' and conformite.get('tests_reels') == True:
|
||||
print(" ✅ Conformité française validée")
|
||||
self.resultats['version'] = True
|
||||
return True
|
||||
else:
|
||||
print(" ❌ Conformité française non validée")
|
||||
self.resultats['version'] = False
|
||||
return False
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
print(f" ❌ Erreur JSON: {e}")
|
||||
self.resultats['version'] = False
|
||||
return False
|
||||
|
||||
def verifier_readme(self):
|
||||
"""Vérifier le README principal"""
|
||||
print("📄 Vérification du README...")
|
||||
|
||||
chemin_readme = os.path.join(self.dossier_temp, "README.md")
|
||||
|
||||
if not os.path.exists(chemin_readme):
|
||||
print(" ❌ README.md manquant")
|
||||
self.resultats['readme'] = False
|
||||
return False
|
||||
|
||||
try:
|
||||
with open(chemin_readme, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
elements_requis = [
|
||||
"Visual Workflow Builder",
|
||||
"Auteur : Dom, Alice, Kiro",
|
||||
"8 janvier 2026",
|
||||
"Démarrage rapide",
|
||||
"Backend",
|
||||
"Frontend",
|
||||
"Tests",
|
||||
]
|
||||
|
||||
elements_presents = 0
|
||||
for element in elements_requis:
|
||||
if element in contenu:
|
||||
elements_presents += 1
|
||||
print(f" ✅ {element}")
|
||||
else:
|
||||
print(f" ❌ Manquant: {element}")
|
||||
|
||||
taux_completude = (elements_presents / len(elements_requis)) * 100
|
||||
print(f" 📊 Complétude README: {elements_presents}/{len(elements_requis)} ({taux_completude:.1f}%)")
|
||||
|
||||
self.resultats['readme'] = taux_completude >= 80
|
||||
return taux_completude >= 80
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Erreur lecture README: {e}")
|
||||
self.resultats['readme'] = False
|
||||
return False
|
||||
|
||||
def compter_fichiers_par_type(self):
|
||||
"""Compter les fichiers par type"""
|
||||
print("📊 Statistiques des fichiers...")
|
||||
|
||||
compteurs = {
|
||||
'python': 0,
|
||||
'typescript': 0,
|
||||
'css': 0,
|
||||
'json': 0,
|
||||
'markdown': 0,
|
||||
'autres': 0
|
||||
}
|
||||
|
||||
for root, dirs, files in os.walk(self.dossier_temp):
|
||||
for file in files:
|
||||
extension = os.path.splitext(file)[1].lower()
|
||||
|
||||
if extension == '.py':
|
||||
compteurs['python'] += 1
|
||||
elif extension in ['.ts', '.tsx']:
|
||||
compteurs['typescript'] += 1
|
||||
elif extension == '.css':
|
||||
compteurs['css'] += 1
|
||||
elif extension == '.json':
|
||||
compteurs['json'] += 1
|
||||
elif extension == '.md':
|
||||
compteurs['markdown'] += 1
|
||||
else:
|
||||
compteurs['autres'] += 1
|
||||
|
||||
total = sum(compteurs.values())
|
||||
|
||||
for type_fichier, count in compteurs.items():
|
||||
pourcentage = (count / total) * 100 if total > 0 else 0
|
||||
print(f" 📁 {type_fichier.capitalize()}: {count} fichiers ({pourcentage:.1f}%)")
|
||||
|
||||
print(f" 📈 Total: {total} fichiers")
|
||||
return compteurs
|
||||
|
||||
def generer_rapport_final(self):
|
||||
"""Générer le rapport final de vérification"""
|
||||
print("\n" + "=" * 60)
|
||||
print("📊 RAPPORT DE VÉRIFICATION DU ZIP VWB")
|
||||
print("=" * 60)
|
||||
|
||||
tests_reussis = sum(1 for resultat in self.resultats.values() if resultat)
|
||||
total_tests = len(self.resultats)
|
||||
taux_reussite = (tests_reussis / total_tests) * 100 if total_tests > 0 else 0
|
||||
|
||||
print(f"📈 Résultats: {tests_reussis}/{total_tests} ({taux_reussite:.1f}%)")
|
||||
print("\n📋 Détail des vérifications:")
|
||||
|
||||
for test, resultat in self.resultats.items():
|
||||
icone = "✅" if resultat else "❌"
|
||||
print(f" {icone} {test.replace('_', ' ').title()}")
|
||||
|
||||
# Déterminer la qualité
|
||||
if taux_reussite == 100:
|
||||
qualite = "🏆 EXCELLENTE - ZIP parfaitement conforme"
|
||||
code_sortie = 0
|
||||
elif taux_reussite >= 80:
|
||||
qualite = "✅ BONNE - ZIP majoritairement conforme"
|
||||
code_sortie = 0
|
||||
elif taux_reussite >= 60:
|
||||
qualite = "⚠️ ACCEPTABLE - Quelques améliorations nécessaires"
|
||||
code_sortie = 1
|
||||
else:
|
||||
qualite = "❌ INSUFFISANTE - Corrections majeures requises"
|
||||
code_sortie = 2
|
||||
|
||||
print(f"\n🎯 QUALITÉ GLOBALE: {qualite}")
|
||||
|
||||
# Informations sur le ZIP
|
||||
taille_zip = os.path.getsize(self.nom_zip)
|
||||
taille_mb = taille_zip / (1024 * 1024)
|
||||
print(f"\n📦 Informations ZIP:")
|
||||
print(f" 📁 Nom: {self.nom_zip}")
|
||||
print(f" 📏 Taille: {taille_mb:.2f} MB")
|
||||
|
||||
return code_sortie
|
||||
|
||||
def nettoyer_dossier_temp(self):
|
||||
"""Nettoyer le dossier temporaire"""
|
||||
if self.dossier_temp and os.path.exists(self.dossier_temp):
|
||||
shutil.rmtree(self.dossier_temp)
|
||||
print(f"🧹 Dossier temporaire supprimé")
|
||||
|
||||
def executer_verification_complete(self):
|
||||
"""Exécuter la vérification complète"""
|
||||
print("🔍 VÉRIFICATION COMPLÈTE DU ZIP VWB")
|
||||
print("=" * 50)
|
||||
|
||||
if not os.path.exists(self.nom_zip):
|
||||
print(f"❌ Fichier ZIP introuvable: {self.nom_zip}")
|
||||
return 1
|
||||
|
||||
try:
|
||||
# Extraire le ZIP
|
||||
self.extraire_zip_temporaire()
|
||||
|
||||
# Exécuter les vérifications
|
||||
self.verifier_structure_generale()
|
||||
self.verifier_conformite_attribution()
|
||||
self.verifier_version_info()
|
||||
self.verifier_readme()
|
||||
self.compter_fichiers_par_type()
|
||||
|
||||
# Générer le rapport
|
||||
code_sortie = self.generer_rapport_final()
|
||||
|
||||
return code_sortie
|
||||
|
||||
except Exception as e:
|
||||
print(f"💥 Erreur critique: {e}")
|
||||
return 3
|
||||
finally:
|
||||
self.nettoyer_dossier_temp()
|
||||
|
||||
def main():
|
||||
"""Fonction principale"""
|
||||
import sys
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python3 verifier_zip_vwb.py <nom_du_zip>")
|
||||
return 1
|
||||
|
||||
nom_zip = sys.argv[1]
|
||||
verificateur = VerificateurZipVWB(nom_zip)
|
||||
|
||||
try:
|
||||
return verificateur.executer_verification_complete()
|
||||
except KeyboardInterrupt:
|
||||
print("\n⚠️ Vérification interrompue")
|
||||
verificateur.nettoyer_dossier_temp()
|
||||
return 2
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user