Spaces:
Sleeping
Sleeping
Claude
chore(sprint-S7)!: nettoyage qualité — shims supprimés, silent excepts éliminés
f8a5c40 unverified | """Sprint S7.4 — invariant CLAUDE.md : pas de ``except Exception: pass``. | |
| CLAUDE.md déclare comme règle stricte : | |
| **Ne jamais mettre `except Exception: pass`** : remplacer par | |
| `logger.warning("[module] fonctionnalité dégradée : %s", e)`. | |
| Ce test scanne la base et échoue si un nouveau silent-except est | |
| introduit. Trois patterns silencieux interdits : | |
| 1. ``except Exception: pass`` (le plus visible). | |
| 2. ``except Exception: ...`` (Ellipsis comme no-op). | |
| 3. ``except Exception as e: pass`` (typo qui ressemble à du log). | |
| Best-effort accepté avec ``logger.debug(...)`` minimum (signal | |
| opérationnel pour ops). | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from pathlib import Path | |
| REPO_ROOT = Path(__file__).resolve().parents[2] | |
| PRODUCTION = REPO_ROOT / "picarones" | |
| # Patterns interdits | |
| _SILENT_EXCEPT_RE = re.compile( | |
| r"except\s+(?:\([^)]*Exception[^)]*\)|Exception)\s*" | |
| r"(?:as\s+\w+)?\s*:\s*(?:#[^\n]*)?\s*\n" | |
| r"(\s+)(pass|\.\.\.)\s*$", | |
| re.MULTILINE, | |
| ) | |
| def _scan_silent_excepts() -> list[tuple[str, int, str]]: | |
| issues: list[tuple[str, int, str]] = [] | |
| for f in PRODUCTION.rglob("*.py"): | |
| if "__pycache__" in str(f): | |
| continue | |
| text = f.read_text(encoding="utf-8") | |
| for m in _SILENT_EXCEPT_RE.finditer(text): | |
| line_no = text[: m.start()].count("\n") + 1 | |
| relpath = str(f.relative_to(REPO_ROOT)) | |
| issues.append((relpath, line_no, m.group(2))) | |
| return issues | |
| def test_no_silent_except_exception_in_production() -> None: | |
| """Aucun ``except Exception: pass`` dans le code production. | |
| Le test échoue si un mainteneur introduit un silent except. | |
| Pour fixer : remplacer ``pass`` par ``logger.warning(...)`` | |
| ou ``logger.debug(...)`` selon la criticité. | |
| """ | |
| issues = _scan_silent_excepts() | |
| if issues: | |
| formatted = "\n".join( | |
| f" - {f}:{line} ({kind})" for f, line, kind in issues | |
| ) | |
| raise AssertionError( | |
| f"Violations CLAUDE.md règle « pas de " | |
| f"``except Exception: pass`` » détectées dans " | |
| f"{len(issues)} emplacement(s) :\n{formatted}\n\n" | |
| f"Remplacer ``pass`` par " | |
| f"``logger.warning('[module] feature dégradée : %s', e)`` " | |
| f"ou ``logger.debug(...)`` pour les best-effort." | |
| ) | |