"""Hiérarchie d'exceptions du generateur-doc.
Chaque classe correspond à un cas d'échec RÉEL du pipeline. Aucune exception
générique ne doit être levée directement : toujours la sous-classe la plus
précise, pour permettre un traitement exhaustif côté main(), jamais un
`except` générique silencieux.
"""
class ErreurGenerateurDoc(Exception):
"""Base commune — ne jamais lever directement, toujours une sous-classe."""
class ErreurCibleIntrouvable(ErreurGenerateurDoc):
"""Le dossier ou fichier cible n'existe pas (vérifié AVANT toute analyse)."""
class ErreurCibleNonAccessible(ErreurGenerateurDoc):
"""Permission refusée sur la cible ou un de ses sous-éléments."""
class ErreurLangageNonSupporte(ErreurGenerateurDoc):
"""Extension de fichier hors du périmètre supporté (.py / .rs) en mode
fichier unique — en mode dossier, un fichier non supporté est simplement
ignoré (comportement documenté, pas une erreur fatale)."""
class ErreurAnalyseSyntaxique(ErreurGenerateurDoc):
"""Le fichier Python n'a pas pu être parsé par `ast.parse` (SyntaxError
réelle) — en mode fichier unique cette erreur est fatale et nommée ;
en mode dossier elle est collectée par fichier sans interrompre le scan."""
def __init__(self, chemin: str, detail: str):
self.chemin = chemin
self.detail = detail
super().__init__(f"{chemin}: {detail}")
class ErreurEcritureRapport(ErreurGenerateurDoc):
"""Le rapport de sortie n'a pas pu être écrit (--out)."""
class ErreurInterne(ErreurGenerateurDoc):
"""Dernier recours NOMMÉ pour tout cas non prévu ci-dessus — jamais un
`except Exception: pass` silencieux."""
def __init__(self, cause: Exception):
self.cause = cause
super().__init__(f"Erreur interne non catégorisée : {type(cause).__name__}: {cause}")