Files
rpa_vision_v3/validate_imports.py
Dom a27b74cf22 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>
2026-01-29 11:23:51 +01:00

214 lines
7.3 KiB
Python

#!/usr/bin/env python3
"""
Validation des imports pour Fiche #4 - RPA Vision V3
Auteur: Dom, Alice Kiro - 15 décembre 2024
Objectif: Valider que tous les imports utilisent 'from core...' au lieu de 'from rpa_vision_v3.core...'
Usage:
python validate_imports.py # Validation seule
python validate_imports.py --fix # Correction automatique
python validate_imports.py --stats # Statistiques détaillées
"""
import os
import re
import sys
import argparse
from pathlib import Path
from typing import List, Tuple, Dict
class ImportValidator:
"""Validateur d'imports pour la Fiche #4"""
def __init__(self):
self.bad_pattern = re.compile(r'from rpa_vision_v3\.core')
self.good_pattern = re.compile(r'from core\.')
self.exclude_dirs = {
'venv', 'venv_v3', '__pycache__', '.git',
'node_modules', '.pytest_cache', '.hypothesis',
'htmlcov', 'rpa_vision_v3.egg-info'
}
self.exclude_files = {
'validate_imports.py', 'setup.py', 'test_fiche4_imports_stables.py'
}
def should_skip(self, filepath: Path) -> bool:
"""Vérifier si on doit ignorer ce fichier/dossier"""
# Ignorer les dossiers exclus
for part in filepath.parts:
if part in self.exclude_dirs:
return True
# Ignorer les fichiers exclus
if filepath.name in self.exclude_files:
return True
# Ignorer les fichiers non-Python
if not filepath.name.endswith('.py'):
return True
return False
def scan_file(self, filepath: Path) -> List[Tuple[int, str]]:
"""Scanner un fichier pour les imports non-conformes"""
bad_imports = []
try:
with open(filepath, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if self.bad_pattern.search(line):
bad_imports.append((line_num, line.strip()))
except (UnicodeDecodeError, PermissionError):
# Ignorer les fichiers binaires ou non-accessibles
pass
return bad_imports
def fix_file(self, filepath: Path) -> int:
"""Corriger les imports dans un fichier"""
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Compter les remplacements
original_content = content
content = self.bad_pattern.sub('from core', content)
if content != original_content:
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
return content.count('from core') - original_content.count('from core')
except (UnicodeDecodeError, PermissionError):
pass
return 0
def validate_all(self) -> Dict[str, List[Tuple[int, str]]]:
"""Valider tous les fichiers Python"""
bad_files = {}
for root, dirs, files in os.walk('.'):
# Filtrer les dossiers à ignorer
dirs[:] = [d for d in dirs if d not in self.exclude_dirs]
for file in files:
filepath = Path(root) / file
if self.should_skip(filepath):
continue
bad_imports = self.scan_file(filepath)
if bad_imports:
bad_files[str(filepath)] = bad_imports
return bad_files
def fix_all(self) -> Dict[str, int]:
"""Corriger tous les fichiers Python"""
fixed_files = {}
for root, dirs, files in os.walk('.'):
# Filtrer les dossiers à ignorer
dirs[:] = [d for d in dirs if d not in self.exclude_dirs]
for file in files:
filepath = Path(root) / file
if self.should_skip(filepath):
continue
fixes = self.fix_file(filepath)
if fixes > 0:
fixed_files[str(filepath)] = fixes
return fixed_files
def get_stats(self) -> Dict[str, int]:
"""Obtenir des statistiques sur les imports"""
stats = {
'total_python_files': 0,
'files_with_bad_imports': 0,
'total_bad_imports': 0,
'files_with_good_imports': 0,
'total_good_imports': 0
}
for root, dirs, files in os.walk('.'):
# Filtrer les dossiers à ignorer
dirs[:] = [d for d in dirs if d not in self.exclude_dirs]
for file in files:
filepath = Path(root) / file
if self.should_skip(filepath):
continue
stats['total_python_files'] += 1
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
bad_count = len(self.bad_pattern.findall(content))
good_count = len(self.good_pattern.findall(content))
if bad_count > 0:
stats['files_with_bad_imports'] += 1
stats['total_bad_imports'] += bad_count
if good_count > 0:
stats['files_with_good_imports'] += 1
stats['total_good_imports'] += good_count
except (UnicodeDecodeError, PermissionError):
pass
return stats
def main():
parser = argparse.ArgumentParser(description='Validation imports Fiche #4')
parser.add_argument('--fix', action='store_true', help='Corriger automatiquement')
parser.add_argument('--stats', action='store_true', help='Afficher statistiques')
args = parser.parse_args()
validator = ImportValidator()
if args.stats:
print("📊 Statistiques des imports:")
stats = validator.get_stats()
for key, value in stats.items():
print(f" {key}: {value}")
return
if args.fix:
print("🔧 Correction automatique des imports...")
fixed_files = validator.fix_all()
if fixed_files:
print(f"{len(fixed_files)} fichiers corrigés:")
for filepath, count in fixed_files.items():
print(f" {filepath}: {count} imports corrigés")
else:
print("✅ Aucune correction nécessaire")
return
# Validation par défaut
print("🔍 Validation des imports...")
bad_files = validator.validate_all()
if bad_files:
print(f"{len(bad_files)} fichiers avec imports non-conformes:")
for filepath, bad_imports in bad_files.items():
print(f"\n📁 {filepath}:")
for line_num, line in bad_imports:
print(f" ligne {line_num}: {line}")
print(f"\n💡 Pour corriger automatiquement: python {sys.argv[0]} --fix")
sys.exit(1)
else:
print("✅ Tous les imports sont conformes")
sys.exit(0)
if __name__ == "__main__":
main()