From 27fbdebcc8b31e0f715a3dabb8803c0ebe30d62b Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Tue, 1 Apr 2025 20:28:08 +0200 Subject: [PATCH 01/13] Feat: Ajout de la classe AfficheurCLI et de animations.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajout de la classe AfficheurCLI qui permet d'intéragir avec la ligne de commande et d'afficher l'animation de chargement - Ajout du dossier assets qui contient tous les fichiers d'éléments visuels - Ajout du fichier animations.json qui contient les ASCIIs à afficher dans la ligne de commande --- app/cli/afficheur_cli.py | 182 +++++++++++++++++++++++++++++++++++++++ app/main.py | 17 ++-- assets/animations.json | 18 ++++ 3 files changed, 205 insertions(+), 12 deletions(-) create mode 100644 app/cli/afficheur_cli.py create mode 100644 assets/animations.json diff --git a/app/cli/afficheur_cli.py b/app/cli/afficheur_cli.py new file mode 100644 index 0000000..0e800df --- /dev/null +++ b/app/cli/afficheur_cli.py @@ -0,0 +1,182 @@ +""" +Module pour les intéractions avec la ligne de commande. +""" + +import sys +from json import load +from time import sleep +from random import choice +import colorama +import threading + + +class AfficheurCLI: + """ + Représente une classe pour afficher des informations dans la ligne de commande. + + Attributes: + COULEUR_MESSAGE_NORMAL (str): La couleur pour les messages normaux en CLI. + COULEUR_MESSAGE_ERREUR (str): La couleur pour les messages d'erreur en CLI. + _thread_chargement (Union[None,Thread]): Le thread de l'animation de chargement. + _thread_chargement_demande_arret (Event): L'évènement pour demander au thread de + l'animation de chargement de s'arrêter. + _animations_actuelles (dict): Les éléments visuels pour l'animation de chargement. + """ + COULEUR_MESSAGE_NORMAL = colorama.Fore.WHITE + COULEUR_MESSAGE_ERREUR = colorama.Fore.RED + + def __init__(self): + """ + Initialise un objet pour afficher des informations dans la ligne de commande. + """ + # Initialise les variables pour le chargement + self._thread_chargement = None + self._thread_chargement_demande_arret = threading.Event() + # Récupère les animations + with open("assets/animations.json", "r", encoding="utf-8") as animations: + elements_animations = load(animations) + # Choisis une animation au hasard parmi chaque catégorie d'animation + self._animations_actuelles = { + "chasseur": choice(elements_animations["chasseurs"]), + "fantome": choice(elements_animations["fantomes"]), + "rayon_laser": elements_animations["rayons_laser"] + } + + def reecrire_ligne(self, message: str): + """ + Permet d'écrire des caractères par dessus la dernière ligne dans la + ligne de commande. + + Args: + message (str): Les caractères à afficher. + + Returns: + None + + Raises: + TypeError: Le paramètre ``message`` n'est pas une chaîne de caractères. + """ + # Validation du paramètre + if not isinstance(message, str): + raise TypeError("Le message pour la réécriture doit être une chaîne de caractères.") + # Ecriture du message + sys.stdout.write("\r" + self.COULEUR_MESSAGE_NORMAL + message) + sys.stdout.flush() + + def affiche_message(self, message: str): + """ + Permet d'écrire un message commun dans la ligne de commande avec la bonne + couleur. + + Args: + message (str): Le message à afficher. + + Returns: + None + + Raises: + TypeError: Le paramètre ``message`` n'est pas une chaîne de caractères. + """ + # Validation du paramètre + if not isinstance(message, str): + raise TypeError("Le message doit être une chaîne de caractères.") + # Ecriture du message + print(self.COULEUR_MESSAGE_NORMAL + message, flush=True) + + def affiche_erreur(self, message: str, exception: Exception): + """ + Permet d'écrire un message d'erreur dans la ligne de commande avec la bonne + couleur. + + Args: + message (str): Le message à afficher. + exception (Exception): L'exception à afficher. + + Returns: + None + + Raises: + TypeError: Le paramètre ``message`` n'est pas une chaîne de caractères ou + le paramètre ``exception`` n'est pas une instance de la classe :class:`Exception`. + """ + # Validation des paramètres + if not isinstance(message, str): + raise TypeError("Le message d'erreur doit être une chaîne de caractères.") + if not isinstance(exception, Exception): + raise TypeError("L'exception à afficher doit être une instance de Exception.") + # Ecriture du message + print(self.COULEUR_MESSAGE_ERREUR + f"{message}\n{exception}", flush=True, end="\r") + + def lance_animation_chargement(self): + """ + Lance une animation de chargement dans la ligne de commande via un thread non bloquant. + Si l'animation de chargement est déjà en cours, cette méthode ne fait rien. + + Returns: + None + """ + # Si le thread est déjà lancé, annulation de l'animation + if self._thread_chargement and self._thread_chargement.is_alive(): + return + # On réinitialise la demande d'arrêt + self._thread_chargement_demande_arret.clear() + # Initialisation du thread pour le chargement + self._thread_chargement = threading.Thread(target=self.__animation_chargement) + # Lancement du thread pour le chargement + self._thread_chargement.start() + + def __animation_chargement(self): + """ + Lance l'animation de chargement en boucle jusqu'à la demande d'arrêt via + l'attribut :attr:`_thread_chargement_demande_arret`. + + Returns: + None + """ + # Eléments de l'animation de chargement + chasseur_chargement = self._animations_actuelles["chasseur"][0] + fantome_chargement = self._animations_actuelles["fantome"][0] + signes_rayon_laser = self._animations_actuelles["rayon_laser"] + couleurs = ["\033[91m", "\033[93m", "\033[94m", "\033[95m"] # Rouge, Jaune, Bleu, Magenta + + # Eléments de l'animation de fin de chargement + chasseur_gagne = self._animations_actuelles["chasseur"][2] + fantome_perd = self._animations_actuelles["fantome"][1] + + # Variables pour l'animation de chargement + index_boucle = 0 + rayon_laser = "" + + # Début de l'animation (jusqu'à la demande d'arrêt) + while not self._thread_chargement_demande_arret.is_set(): + # Récupération de la prochaine couleur + couleur_courante = couleurs[(index_boucle % len(couleurs))] + # Récupération du prochain signe du rayon + signe_courant = signes_rayon_laser[(index_boucle % len(signes_rayon_laser))] + # Ajout du dernier signe avec la nouvelle couleur au rayon + rayon_laser += couleur_courante + signe_courant + # Réactualisation de l'animation de chargement + self.reecrire_ligne(f"{chasseur_chargement}{rayon_laser}\033[0m{fantome_chargement}") + index_boucle += 1 + sleep(0.05) + + # Suppression de la ligne de chargement + self.reecrire_ligne("\033[K") + # Message d'animation terminée + self.reecrire_ligne(f"{chasseur_gagne}{" " * index_boucle}\033[0m{fantome_perd}") + + def stop_animation_chargement(self): + """ + Lance une demande d'arrêt au thread qui gère l'animation de chargement + en cours. Si aucune animation n'est en cours, cette méthode ne fait rien. + + Returns: + None + """ + # Si le thread de chargement existe et est lancé + if self._thread_chargement and self._thread_chargement.is_alive(): + # Lancement de la demade d'arrêt + self._thread_chargement_demande_arret.set() + # Attente de l'arrêt depuis le thread principal + self._thread_chargement.join() + self.affiche_message(f"\nAnalyse terminée! We came, we saw, we logged it.") diff --git a/app/main.py b/app/main.py index 4833dc2..7727c19 100644 --- a/app/main.py +++ b/app/main.py @@ -3,6 +3,7 @@ """ import colorama +from cli.afficheur_cli import AfficheurCLI from cli.parseur_arguments_cli import ParseurArgumentsCLI, ArgumentCLIException from parse.parseur_log_apache import ParseurLogApache, FormatLogApacheInvalideException from analyse.analyseur_log_apache import AnalyseurLogApache @@ -14,19 +15,10 @@ def main(): Point d'entrée de l'application. """ colorama.init() - print(colorama.Style.DIM + r""" - .-. .-') .-') .-') _ ('-. _ .-') ,---. - \ ( OO ) ( OO ). ( OO) ) _( OO)( \( -O ) | | - ,--. .-'),-----. ,----. ;-----.\ ,--. ,--. (_)---\_)/ '._(,------.,------. | | - | |.-') ( OO' .-. ' ' .-./-') | .-. | | | | | / _ | |'--...__)| .---'| /`. '| | - | | OO )/ | | | | | |_( O- )| '-' /_) | | | .-') \ :` `. '--. .--'| | | / | || | - | |`-' |\_) | |\| | | | .--, \| .-. `. | |_|( OO ) '..`''.) | | (| '--. | |_.' || .' -(| '---.' \ | | | |(| | '. (_/| | \ | | | | `-' /.-._) \ | | | .--' | . '.'`--' - | | `' '-' ' | '--' | | '--' /(' '-'(_.-' \ / | | | `---.| |\ \ .--. - `------' `-----' `------' `------' `-----' `-----' `--' `------'`--' '--''--' - - """) + a = AfficheurCLI() try: + a.affiche_message("Who ya gonna call? LogBuster!") + a.lance_animation_chargement() # Récupération des arguments parseur_cli = ParseurArgumentsCLI() arguments_cli = parseur_cli.parse_args() @@ -39,6 +31,7 @@ def main(): # Exportation de l'analyse exporteur = Exporteur(arguments_cli.sortie) exporteur.export_vers_json(analyse) + a.stop_animation_chargement() except ArgumentCLIException as ex: print(f"Erreur dans les arguments fournis !\n {ex}") except FileNotFoundError as ex: diff --git a/assets/animations.json b/assets/animations.json new file mode 100644 index 0000000..eb38a6f --- /dev/null +++ b/assets/animations.json @@ -0,0 +1,18 @@ +{ + "chasseurs": [ + ["(҂-_•)⊃═O", "(҂x_x)", "d(•᎑-҂)"], + ["(⌐■_■)⊃═O", "(⌐x_x)", "d(■᎑■⌐)"], + ["(∩•_•)⊃═O", "(∩x_x)", "d(•᎑•∩)"], + ["(ò_ó)⊃═O", "(x_x)", "d(ò᎑ó)"] + ], + + "fantomes": [ + ["ε=(( ꐑº-° )ꐑ", "(( x-x)", "ε=(( ꐑº᎑° )ꐑ"], + ["ε=(¬ ´ཀ` )¬", "( xཀx)", "ε=(¬ ´᎑` )¬"], + ["ε=༼ つ ╹ ╹ ༽つ", "༼ x x ༽", "ε=༼ つ ╹᎑╹ ༽つ"], + ["ε=( >_<)", "( x_x)", "ε=( >᎑<)"], + ["ε=(ง'̀-'́)ง", "('x-x)", "ε=(ง'̀᎑'́)ง"] + ], + + "rayons_laser": ["-", "=", "~", "*", "~", "=", "-"] +} \ No newline at end of file From 122d33f30885b8faa1359dbd5b06093c26a88087 Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:13:58 +0200 Subject: [PATCH 02/13] =?UTF-8?q?Refractor:=20Am=C3=A9lioration=20de=20la?= =?UTF-8?q?=20gestion=20des=20exceptions=20dans=20main.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajout de la fonction gestion_exception qui permet de gérer une exception rencontrée durant le déroulement du script améliorant ainsi la lisibilité du code --- app/main.py | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/app/main.py b/app/main.py index 7727c19..3b1c5d1 100644 --- a/app/main.py +++ b/app/main.py @@ -1,7 +1,7 @@ """ Point d'entrée de l'application LogBuster ! """ - +from time import sleep import colorama from cli.afficheur_cli import AfficheurCLI from cli.parseur_arguments_cli import ParseurArgumentsCLI, ArgumentCLIException @@ -14,11 +14,10 @@ def main(): """ Point d'entrée de l'application. """ - colorama.init() - a = AfficheurCLI() + afficheur_cli = AfficheurCLI() + afficheur_cli.affiche_message("Who ya gonna call? LogBuster!") try: - a.affiche_message("Who ya gonna call? LogBuster!") - a.lance_animation_chargement() + afficheur_cli.lance_animation_chargement() # Récupération des arguments parseur_cli = ParseurArgumentsCLI() arguments_cli = parseur_cli.parse_args() @@ -31,18 +30,33 @@ def main(): # Exportation de l'analyse exporteur = Exporteur(arguments_cli.sortie) exporteur.export_vers_json(analyse) - a.stop_animation_chargement() - except ArgumentCLIException as ex: - print(f"Erreur dans les arguments fournis !\n {ex}") - except FileNotFoundError as ex: - print(f"Erreur dans la recherche du log Apache !\n{ex}") - except FormatLogApacheInvalideException as ex: - print(f"Erreur dans l'analyse du log Apache !\n{ex}") - except ExportationException as ex: - print(f"Erreur dans l'exportation de l'analyse !\n{ex}") + afficheur_cli.stop_animation_chargement() except Exception as ex: - print(f"Erreur interne !\n{ex}") + gestion_exception(afficheur_cli, ex) + +def gestion_exception(afficheur_cli, exception): + """ + Gère les erreurs qui demandent une fin du programme. + Affiche également un message d'erreur personnalisé en fonction + de l'exception. + Args: + afficheur_cli (AfficheurCLI): L'objet permettant d'intéragir avec la ligne + de commande. + exception (Exception): L'exception qui s'est produite. + + Returns: + None + """ + erreurs = { + ArgumentCLIException: "Erreur dans les arguments fournis !", + FileNotFoundError: "Erreur dans la recherche du log Apache !", + FormatLogApacheInvalideException: "Erreur dans l'analyse du log Apache !", + ExportationException: "Erreur dans l'exportation de l'analyse !" + } + message = erreurs.get(type(exception), "Erreur interne !") + afficheur_cli.stop_animation_chargement(True) + afficheur_cli.affiche_erreur(message, exception) if __name__ == "__main__": main() From 171d3d5de77b03cd5e020d851e64e358a3d5d4f5 Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:15:23 +0200 Subject: [PATCH 03/13] =?UTF-8?q?Refractor:=20Am=C3=A9lioratio=20de=20la?= =?UTF-8?q?=20v=C3=A9rification=20de=20lancement=20de=20chargement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Amélioration de la condition qui vérifier que l'animation n'est pas déjà lancée lorsque on lance une nouvelle animation de chargement --- app/cli/afficheur_cli.py | 89 +++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/app/cli/afficheur_cli.py b/app/cli/afficheur_cli.py index 0e800df..7494301 100644 --- a/app/cli/afficheur_cli.py +++ b/app/cli/afficheur_cli.py @@ -3,13 +3,13 @@ """ import sys +from pathlib import Path from json import load from time import sleep from random import choice import colorama import threading - class AfficheurCLI: """ Représente une classe pour afficher des informations dans la ligne de commande. @@ -18,8 +18,10 @@ class AfficheurCLI: COULEUR_MESSAGE_NORMAL (str): La couleur pour les messages normaux en CLI. COULEUR_MESSAGE_ERREUR (str): La couleur pour les messages d'erreur en CLI. _thread_chargement (Union[None,Thread]): Le thread de l'animation de chargement. - _thread_chargement_demande_arret (Event): L'évènement pour demander au thread de - l'animation de chargement de s'arrêter. + _thread_chargement_termine (Event): L'évènement pour demander au thread de + l'animation de chargement de s'arrêter lorsque le chargement est terminé. + _thread_chargement_erreur (Event): L'évènement pour demander au thread de + l'animation de chargement de s'arrêter lorsque une erreur s'est produite. _animations_actuelles (dict): Les éléments visuels pour l'animation de chargement. """ COULEUR_MESSAGE_NORMAL = colorama.Fore.WHITE @@ -29,11 +31,16 @@ def __init__(self): """ Initialise un objet pour afficher des informations dans la ligne de commande. """ + # Normalise les codes couleurs pour fonctionner partout + colorama.init() # Initialise les variables pour le chargement self._thread_chargement = None - self._thread_chargement_demande_arret = threading.Event() + self._thread_chargement_termine = threading.Event() + self._thread_chargement_erreur = threading.Event() # Récupère les animations - with open("assets/animations.json", "r", encoding="utf-8") as animations: + chemin_racine = Path(__file__).parent.parent.parent.resolve() + chemin_animations = chemin_racine / "assets" / "animations.json" + with open(chemin_animations, "r", encoding="utf-8") as animations: elements_animations = load(animations) # Choisis une animation au hasard parmi chaque catégorie d'animation self._animations_actuelles = { @@ -105,7 +112,7 @@ def affiche_erreur(self, message: str, exception: Exception): if not isinstance(exception, Exception): raise TypeError("L'exception à afficher doit être une instance de Exception.") # Ecriture du message - print(self.COULEUR_MESSAGE_ERREUR + f"{message}\n{exception}", flush=True, end="\r") + print(self.COULEUR_MESSAGE_ERREUR + f"{message}\n{exception}", flush=True) def lance_animation_chargement(self): """ @@ -116,16 +123,16 @@ def lance_animation_chargement(self): None """ # Si le thread est déjà lancé, annulation de l'animation - if self._thread_chargement and self._thread_chargement.is_alive(): - return - # On réinitialise la demande d'arrêt - self._thread_chargement_demande_arret.clear() - # Initialisation du thread pour le chargement - self._thread_chargement = threading.Thread(target=self.__animation_chargement) - # Lancement du thread pour le chargement - self._thread_chargement.start() + if self._thread_chargement is None: + # On réinitialise les demandes d'arrêt + self._thread_chargement_termine.clear() + self._thread_chargement_erreur.clear() + # Initialisation du thread pour le chargement + self._thread_chargement = threading.Thread(target=self._animation_chargement, daemon=True) + # Lancement du thread pour le chargement + self._thread_chargement.start() - def __animation_chargement(self): + def _animation_chargement(self): """ Lance l'animation de chargement en boucle jusqu'à la demande d'arrêt via l'attribut :attr:`_thread_chargement_demande_arret`. @@ -139,44 +146,62 @@ def __animation_chargement(self): signes_rayon_laser = self._animations_actuelles["rayon_laser"] couleurs = ["\033[91m", "\033[93m", "\033[94m", "\033[95m"] # Rouge, Jaune, Bleu, Magenta - # Eléments de l'animation de fin de chargement + # Eléments de l'animation de fin de chargement en cas de succès chasseur_gagne = self._animations_actuelles["chasseur"][2] fantome_perd = self._animations_actuelles["fantome"][1] + # Eléments de l'animation de fin de chargement en cas d'erreur + chasseur_perd = self._animations_actuelles["chasseur"][1] + fantome_gagne = self._animations_actuelles["fantome"][2] + # Variables pour l'animation de chargement index_boucle = 0 rayon_laser = "" # Début de l'animation (jusqu'à la demande d'arrêt) - while not self._thread_chargement_demande_arret.is_set(): - # Récupération de la prochaine couleur - couleur_courante = couleurs[(index_boucle % len(couleurs))] - # Récupération du prochain signe du rayon - signe_courant = signes_rayon_laser[(index_boucle % len(signes_rayon_laser))] - # Ajout du dernier signe avec la nouvelle couleur au rayon - rayon_laser += couleur_courante + signe_courant - # Réactualisation de l'animation de chargement - self.reecrire_ligne(f"{chasseur_chargement}{rayon_laser}\033[0m{fantome_chargement}") - index_boucle += 1 + while not (self._thread_chargement_termine.is_set() + or self._thread_chargement_erreur.is_set()): + # Arrête d'ajouter des caractères lorsque la chaîne est trop longue + if (index_boucle < 40): + # Récupération de la prochaine couleur + couleur_courante = couleurs[(index_boucle % len(couleurs))] + # Récupération du prochain signe du rayon + signe_courant = signes_rayon_laser[(index_boucle % len(signes_rayon_laser))] + # Ajout du dernier signe avec la nouvelle couleur au rayon + rayon_laser += couleur_courante + signe_courant + # Réactualisation de l'animation de chargement + self.reecrire_ligne(f"{chasseur_chargement}{rayon_laser}\033[0m{fantome_chargement}") + index_boucle += 1 sleep(0.05) # Suppression de la ligne de chargement self.reecrire_ligne("\033[K") - # Message d'animation terminée - self.reecrire_ligne(f"{chasseur_gagne}{" " * index_boucle}\033[0m{fantome_perd}") - - def stop_animation_chargement(self): + if (self._thread_chargement_termine.is_set()): + # Message d'animation terminée + self.reecrire_ligne(f"{chasseur_gagne}{" " * index_boucle}\033[0m{fantome_perd}\n") + self.affiche_message(f"Analyse terminée! We came, we saw, we logged it.") + else: + # Message d'animation erreur + self.reecrire_ligne(f"{chasseur_perd}{" " * index_boucle}\033[0m{fantome_gagne}\n") + + def stop_animation_chargement(self, erreur: bool = False): """ Lance une demande d'arrêt au thread qui gère l'animation de chargement en cours. Si aucune animation n'est en cours, cette méthode ne fait rien. + Args: + erreur (bool): Indique si la demande d'arrêt est dûe à une erreur ou non. + Returns: None """ # Si le thread de chargement existe et est lancé if self._thread_chargement and self._thread_chargement.is_alive(): # Lancement de la demade d'arrêt - self._thread_chargement_demande_arret.set() + if not erreur: + self._thread_chargement_termine.set() + else: + self._thread_chargement_erreur.set() # Attente de l'arrêt depuis le thread principal self._thread_chargement.join() - self.affiche_message(f"\nAnalyse terminée! We came, we saw, we logged it.") + self._thread_chargement = None From a815538346071f5e4798a00bcccfad7b0461845c Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:17:03 +0200 Subject: [PATCH 04/13] Test: Ajout des tests unitaires de AfficheurCLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajout des tests unitaires pour la classe AfficheurCLI - Ajout du fichier .coveragerc pour exclure la vérification "if __name__ == "__main__" --- analyse-log-apache.json | 77 +++++++++++++++++++++++++++++++++++ tests/.coveragerc | 3 ++ tests/conftest.py | 5 +++ tests/test_afficheur_cli.py | 81 +++++++++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 analyse-log-apache.json create mode 100644 tests/.coveragerc create mode 100644 tests/test_afficheur_cli.py diff --git a/analyse-log-apache.json b/analyse-log-apache.json new file mode 100644 index 0000000..e1d5c52 --- /dev/null +++ b/analyse-log-apache.json @@ -0,0 +1,77 @@ +{ + "chemin": "C:\\Users\\Work\\App\\Xampp\\apache\\logs\\access.log", + "statistiques": { + "total_entrees": 17594, + "requetes": { + "top_urls": [ + { + "url": "/assets/icons/muted.png", + "total": 665, + "taux": 3.7796976241900646 + }, + { + "url": "/style/Header.css", + "total": 616, + "taux": 3.501193588723429 + }, + { + "url": "/assets/icon.ico", + "total": 595, + "taux": 3.381834716380584 + } + ], + "repartition_code_statut_http": [ + { + "code": 200, + "total": 14996, + "taux": 85.23360236444243 + }, + { + "code": 304, + "total": 1494, + "taux": 8.491531203819484 + }, + { + "code": 206, + "total": 604, + "taux": 3.432988518813232 + }, + { + "code": 404, + "total": 230, + "taux": 1.307263839945436 + }, + { + "code": 302, + "total": 188, + "taux": 1.0685460952597476 + }, + { + "code": 403, + "total": 40, + "taux": 0.22735023303398885 + }, + { + "code": 500, + "total": 20, + "taux": 0.11367511651699443 + }, + { + "code": 301, + "total": 13, + "taux": 0.07388882573604638 + }, + { + "code": 400, + "total": 6, + "taux": 0.03410253495509833 + }, + { + "code": 408, + "total": 3, + "taux": 0.017051267477549165 + } + ] + } + } +} \ No newline at end of file diff --git a/tests/.coveragerc b/tests/.coveragerc new file mode 100644 index 0000000..7d5cb5a --- /dev/null +++ b/tests/.coveragerc @@ -0,0 +1,3 @@ +[report] +exclude_lines = + if __name__ == "__main__": \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 550738c..861d5e2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,7 @@ """ import pytest +from cli.afficheur_cli import AfficheurCLI from cli.parseur_arguments_cli import ParseurArgumentsCLI from parse.parseur_log_apache import ParseurLogApache from analyse.analyseur_log_apache import AnalyseurLogApache @@ -47,6 +48,10 @@ # Fixtures générales # ------------------ +@pytest.fixture +def afficheur_cli(): + return AfficheurCLI() + @pytest.fixture def parseur_arguments_cli(): """ diff --git a/tests/test_afficheur_cli.py b/tests/test_afficheur_cli.py new file mode 100644 index 0000000..089ae17 --- /dev/null +++ b/tests/test_afficheur_cli.py @@ -0,0 +1,81 @@ +""" +Modules des tests unitaires pour l'affichage d'informations dans la CLI. +""" + +import pytest +from time import sleep +from io import StringIO +from cli.afficheur_cli import AfficheurCLI + +# Données +messages = [ + "Un message normal", + "Test\r avec des \ncaractères\t spéciaux", + "Test d'un message très long" * 1000, + "\033[31mTest avec couleur\033[0m", + "🎉 Test avec des unicodes 🎉" +] + +# Tests unitaires + +@pytest.mark.parametrize("message", messages) +def test_afficheur_cli_affiche_message(mocker, afficheur_cli, message): + # Remplacement de la sortie standard par un StringIO (nommé sortie_cli) + with mocker.patch("sys.stdout", new_callable=StringIO) as sortie_cli: + afficheur_cli.affiche_message(message) + assert sortie_cli.getvalue() == afficheur_cli.COULEUR_MESSAGE_NORMAL + message + "\n" + +def test_afficheur_cli_exception_affiche_message_type(afficheur_cli): + with pytest.raises(TypeError): + afficheur_cli.affiche_message(123) + +@pytest.mark.parametrize("message, exception", [ + ("Un message d'erreur !", Exception("Erreur générale !")), + ("Erreur de typage !", TypeError("Une variable str était attendue !")), + ("Erreur dans la recherche !", FileNotFoundError("Fichier non trouvé !")) +]) +def test_afficheur_cli_affiche_erreur(mocker, afficheur_cli, message, exception): + # Remplacement de la sortie standard par un StringIO (nommé sortie_cli) + with mocker.patch("sys.stdout", new_callable=StringIO) as sortie_cli: + afficheur_cli.affiche_erreur(message, exception) + assert sortie_cli.getvalue() == (afficheur_cli.COULEUR_MESSAGE_ERREUR + + message + "\n" + str(exception) + "\n") + +@pytest.mark.parametrize("message, exception", [ + (False, Exception("Erreur générale !")), + ("Erreur de typage !", False) +]) +def test_afficheur_cli_exception_affiche_erreur_type(afficheur_cli, message, exception): + with pytest.raises(TypeError): + afficheur_cli.affiche_erreur(message, exception) + +@pytest.mark.parametrize("message", messages) +def test_afficheur_cli_reecrire_ligne(mocker, afficheur_cli, message): + # Remplacement de la sortie standard par un StringIO (nommé sortie_cli) + with mocker.patch("sys.stdout", new_callable=StringIO) as sortie_cli: + afficheur_cli.reecrire_ligne(message) + assert sortie_cli.getvalue() == "\r" + afficheur_cli.COULEUR_MESSAGE_NORMAL + message + +def test_afficheur_cli_exception_reecrire_ligne_type(afficheur_cli): + with pytest.raises(TypeError): + afficheur_cli.reecrire_ligne(123) + +def test_afficheur_cli_lance_animation_chargement(mocker, afficheur_cli): + mocker.patch.object(afficheur_cli, "_animation_chargement", side_effect=lambda: sleep(10)) + assert afficheur_cli._thread_chargement is None + afficheur_cli.lance_animation_chargement() + assert afficheur_cli._thread_chargement is not None + assert afficheur_cli._thread_chargement.is_alive() + +def test_afficheur_cli_stop_animation_chargement_terminee(mocker, afficheur_cli): + afficheur_cli.lance_animation_chargement() + afficheur_cli.stop_animation_chargement() + assert afficheur_cli._thread_chargement is None + assert afficheur_cli._thread_chargement is None + assert afficheur_cli._thread_chargement_termine.is_set() + +def test_afficheur_cli_stop_animation_chargement_erreur(mocker, afficheur_cli): + afficheur_cli.lance_animation_chargement() + afficheur_cli.stop_animation_chargement(True) + assert afficheur_cli._thread_chargement is None + assert afficheur_cli._thread_chargement_erreur.is_set() \ No newline at end of file From a15b368e7ac13188bd595e950822edcf0035831e Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:20:26 +0200 Subject: [PATCH 05/13] =?UTF-8?q?CI:=20Am=C3=A9lioration=20de=20l'action?= =?UTF-8?q?=20des=20tests=20unitaires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Déplacement du lancement des tests unitaires vers le fichier tests afin que le dossier de configuration de coverage.py soit pris en compte --- .github/workflows/tests.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index b315e8c..098018d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -3,7 +3,7 @@ name: Tests unitaires - LogBuster on: push: branches: - - develop + - feat/interaction-cli # Permissions (lecture uniquement) permissions: @@ -39,7 +39,8 @@ jobs: # Étape 4 : Lancer les tests unitaires - name: Lancer les tests unitaires run: | - pytest tests/ --basetemp=resultats_pytest --verbose --cov=app --cov-report=term-missing --cov-report=xml:resultats_pytest/tests-couverture.xml --junitxml=resultats_pytest/tests-rapport.xml + cd tests + pytest --basetemp=resultats_pytest --verbose --cov=app --cov-report=term-missing --cov-report=xml:resultats_pytest/tests-couverture.xml --junitxml=resultats_pytest/tests-rapport.xml # Étape 5 : Sauvegarder les artefacts - name: Sauvegarder les résultats de test From b4c6290d274ccd4a34d96a8418bcbb24b9e88f14 Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:24:11 +0200 Subject: [PATCH 06/13] =?UTF-8?q?CI:=20Am=C3=A9lioration=20des=20chemins?= =?UTF-8?q?=20dans=20l'action=20des=20tests=20unitaires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Modification de chemin dans test.yaml qui était mauvais depuis le déplacement des tests vers le dossier tests --- .github/workflows/tests.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 098018d..8f7bf63 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -40,7 +40,7 @@ jobs: - name: Lancer les tests unitaires run: | cd tests - pytest --basetemp=resultats_pytest --verbose --cov=app --cov-report=term-missing --cov-report=xml:resultats_pytest/tests-couverture.xml --junitxml=resultats_pytest/tests-rapport.xml + pytest --basetemp=resultats_pytest --verbose --cov=../app --cov-report=term-missing --cov-report=xml:resultats_pytest/tests-couverture.xml --junitxml=resultats_pytest/tests-rapport.xml # Étape 5 : Sauvegarder les artefacts - name: Sauvegarder les résultats de test @@ -49,4 +49,4 @@ jobs: with: if-no-files-found: error name: tests-resultats-python-${{ matrix.python-version }} # Nom de l'artefact - path: resultats_pytest # Eléments à sauvegarder + path: tests/resultats_pytest # Eléments à sauvegarder From 9e79b8b3b68bbd8d8c46adc616a232b0a14c733b Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:26:24 +0200 Subject: [PATCH 07/13] CI: Modification du chemin de l'atefact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Modification du chemin de l'artefact qui était mauvais depuis le changement du dossier où les tests unitaires sont activés --- .github/workflows/tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8f7bf63..34e2bb6 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -49,4 +49,4 @@ jobs: with: if-no-files-found: error name: tests-resultats-python-${{ matrix.python-version }} # Nom de l'artefact - path: tests/resultats_pytest # Eléments à sauvegarder + path: resultats_pytest # Eléments à sauvegarder From d6f48bfdd8e80f27b772759f0eb66f8f87e7d2a8 Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:35:54 +0200 Subject: [PATCH 08/13] =?UTF-8?q?Fix:=20Correction=20erreur=20compatibilit?= =?UTF-8?q?=C3=A9=20avec=20python=20inf=C3=A9rieur=20=C3=A0=203.12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Modification d'une chaine de caractere qui était incorrecte pour les versions de python inférieur à 3.12 --- app/cli/afficheur_cli.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/cli/afficheur_cli.py b/app/cli/afficheur_cli.py index 7494301..2e1a758 100644 --- a/app/cli/afficheur_cli.py +++ b/app/cli/afficheur_cli.py @@ -176,13 +176,14 @@ def _animation_chargement(self): # Suppression de la ligne de chargement self.reecrire_ligne("\033[K") + espace_rayon_laser = " " * index_boucle if (self._thread_chargement_termine.is_set()): # Message d'animation terminée - self.reecrire_ligne(f"{chasseur_gagne}{" " * index_boucle}\033[0m{fantome_perd}\n") + self.reecrire_ligne(f"{chasseur_gagne}{espace_rayon_laser}\033[0m{fantome_perd}\n") self.affiche_message(f"Analyse terminée! We came, we saw, we logged it.") else: # Message d'animation erreur - self.reecrire_ligne(f"{chasseur_perd}{" " * index_boucle}\033[0m{fantome_gagne}\n") + self.reecrire_ligne(f"{chasseur_perd}{espace_rayon_laser}\033[0m{fantome_gagne}\n") def stop_animation_chargement(self, erreur: bool = False): """ From 1f03f3c5f10c886bdd2044f8d63e3271079fd0e2 Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:37:46 +0200 Subject: [PATCH 09/13] CI: Modification chemin artefact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Modification du chemin de l'artefact qui était incorretc depuis la dernière correction --- .github/workflows/tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 34e2bb6..8f7bf63 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -49,4 +49,4 @@ jobs: with: if-no-files-found: error name: tests-resultats-python-${{ matrix.python-version }} # Nom de l'artefact - path: resultats_pytest # Eléments à sauvegarder + path: tests/resultats_pytest # Eléments à sauvegarder From 2b0e428f022e6a3106c8eb5255a624336016a7eb Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:39:33 +0200 Subject: [PATCH 10/13] CI: Remise de l'action tests unitaires sur develop - Modification de la branche de l'action des tests unitaires vers la branche develop --- .github/workflows/tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8f7bf63..9497987 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -3,7 +3,7 @@ name: Tests unitaires - LogBuster on: push: branches: - - feat/interaction-cli + - develop # Permissions (lecture uniquement) permissions: From 85678b8dab1eac51e8e76748358b05ae4b6b9933 Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 19:51:26 +0200 Subject: [PATCH 11/13] =?UTF-8?q?Refractor:=20Am=C3=A9lioration=20de=20la?= =?UTF-8?q?=20documentation=20des=20tests=20unitaires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Amélioration de la documentation des tests unitaires de test_afficheur_cli.py et test_main.py --- tests/test_afficheur_cli.py | 134 +++++++++++++++++++++++++++++++++++- tests/test_main.py | 4 +- 2 files changed, 134 insertions(+), 4 deletions(-) diff --git a/tests/test_afficheur_cli.py b/tests/test_afficheur_cli.py index 089ae17..c68ec51 100644 --- a/tests/test_afficheur_cli.py +++ b/tests/test_afficheur_cli.py @@ -20,12 +20,40 @@ @pytest.mark.parametrize("message", messages) def test_afficheur_cli_affiche_message(mocker, afficheur_cli, message): + """ + Vérifie que la méthode affiche_message affiche correctement les messages avec la bonne + couleur dans le terminal. + + Scénarios testés: + - Passage d'un message à la méthode. + + Asserts: + - Le message est le même que celui fourni avec la bonne couleur. + + Args: + mocker (MockerFixture): Fixture qui permet de modifier le stdout. + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + message (str): Message à afficher. + """ # Remplacement de la sortie standard par un StringIO (nommé sortie_cli) with mocker.patch("sys.stdout", new_callable=StringIO) as sortie_cli: afficheur_cli.affiche_message(message) assert sortie_cli.getvalue() == afficheur_cli.COULEUR_MESSAGE_NORMAL + message + "\n" def test_afficheur_cli_exception_affiche_message_type(afficheur_cli): + """ + Vérifie que la méthode affiche_message lève une exception TypeError + lorsque l'argument fourni n'est pas une chaîne de caractères. + + Scénarios testés: + - Passage d'un entier à la méthode. + + Asserts: + - Vérifie que l'exception TypeError est levée. + + Args: + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + """ with pytest.raises(TypeError): afficheur_cli.affiche_message(123) @@ -35,6 +63,22 @@ def test_afficheur_cli_exception_affiche_message_type(afficheur_cli): ("Erreur dans la recherche !", FileNotFoundError("Fichier non trouvé !")) ]) def test_afficheur_cli_affiche_erreur(mocker, afficheur_cli, message, exception): + """ + Vérifie que la méthode affiche_erreur affiche correctement les messages d'erreur + dans le terminal avec la couleur adéquate. + + Scénarios testés: + - Affichage d'erreurs avec différents types d'exceptions. + + Asserts: + - Vérifie que le message d'erreur et l'exception sont bien affichés. + + Args: + mocker (MockerFixture): Fixture pour modifier le stdout. + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + message (str): Message d'erreur à afficher. + exception (Exception): Exception associée à l'erreur. + """ # Remplacement de la sortie standard par un StringIO (nommé sortie_cli) with mocker.patch("sys.stdout", new_callable=StringIO) as sortie_cli: afficheur_cli.affiche_erreur(message, exception) @@ -46,35 +90,121 @@ def test_afficheur_cli_affiche_erreur(mocker, afficheur_cli, message, exception) ("Erreur de typage !", False) ]) def test_afficheur_cli_exception_affiche_erreur_type(afficheur_cli, message, exception): + """ + Vérifie que la méthode affiche_erreur lève une exception TypeError + lorsque les arguments ne sont pas du bon type. + + Scénarios testés: + - Passage d'un mauvais type pour le paramètre ``message``. + - Passage d'un mauvais type pour le paramètre ``exception``. + + Asserts: + - Vérifie que l'exception TypeError est levée. + + Args: + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + message (Any): Valeur incorrecte à tester. + exception (Any): Valeur incorrecte à tester. + """ with pytest.raises(TypeError): afficheur_cli.affiche_erreur(message, exception) @pytest.mark.parametrize("message", messages) def test_afficheur_cli_reecrire_ligne(mocker, afficheur_cli, message): + """ + Vérifie que la méthode reecrire_ligne affiche correctement un message + sur la même ligne du terminal. + + Scénarios testés: + - Affichage de plusieurs messages. + + Asserts: + - Vérifie que la sortie standard contient le message formaté. + + Args: + mocker (MockerFixture): Fixture pour modifier le stdout. + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + message (str): Message à afficher. + """ # Remplacement de la sortie standard par un StringIO (nommé sortie_cli) with mocker.patch("sys.stdout", new_callable=StringIO) as sortie_cli: afficheur_cli.reecrire_ligne(message) assert sortie_cli.getvalue() == "\r" + afficheur_cli.COULEUR_MESSAGE_NORMAL + message def test_afficheur_cli_exception_reecrire_ligne_type(afficheur_cli): + """ + Vérifie que la méthode reecrire_ligne lève une exception TypeError + lorsqu'un argument de type incorrect est fourni. + + Scénarios testés: + - Passage d'un entier au lieu d'une chaîne de caractères. + + Asserts: + - Vérifie que l'exception TypeError est levée. + + Args: + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + """ with pytest.raises(TypeError): afficheur_cli.reecrire_ligne(123) def test_afficheur_cli_lance_animation_chargement(mocker, afficheur_cli): + """ + Vérifie que la méthode lance_animation_chargement démarre bien un thread + pour l'animation de chargement. + + Scénarios testés: + - Lancement de l'animation de chargement. + + Asserts: + - Vérifie que le thread est bien initialisé et actif. + + Args: + mocker (MockerFixture): Fixture pour modifier les méthodes internes. + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + """ mocker.patch.object(afficheur_cli, "_animation_chargement", side_effect=lambda: sleep(10)) assert afficheur_cli._thread_chargement is None afficheur_cli.lance_animation_chargement() assert afficheur_cli._thread_chargement is not None assert afficheur_cli._thread_chargement.is_alive() -def test_afficheur_cli_stop_animation_chargement_terminee(mocker, afficheur_cli): +def test_afficheur_cli_stop_animation_chargement_terminee(afficheur_cli): + """ + Vérifie que la méthode stop_animation_chargement arrête correctement l'animation en + cas de demande d'arrêt suite à une fin de chargement normale. + + Scénarios testés: + - Arrêt normal de l'animation de chargement. + + Asserts: + - Vérifie que le thread est bien arrêté. + - Vérifie que le flag d'arrêt normale est activé. + + Args: + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + """ afficheur_cli.lance_animation_chargement() afficheur_cli.stop_animation_chargement() assert afficheur_cli._thread_chargement is None assert afficheur_cli._thread_chargement is None assert afficheur_cli._thread_chargement_termine.is_set() -def test_afficheur_cli_stop_animation_chargement_erreur(mocker, afficheur_cli): +def test_afficheur_cli_stop_animation_chargement_erreur(afficheur_cli): + """ + Vérifie que la méthode stop_animation_chargement arrête correctement l'animation en + cas de demande d'arrêt suite à une erreur. + + Scénarios testés: + - Arrêt normal de l'animation de chargement. + + Asserts: + - Vérifie que le thread est bien arrêté. + - Vérifie que le flag d'arrêt d'erreur est activé. + + Args: + afficheur_cli (AfficheurCLI): Fixture pour l'instance de la classe ``AfficheurCLI``. + """ afficheur_cli.lance_animation_chargement() afficheur_cli.stop_animation_chargement(True) assert afficheur_cli._thread_chargement is None diff --git a/tests/test_main.py b/tests/test_main.py index c2fb6e1..a92fba9 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -24,7 +24,7 @@ def test_main_gestion_exception(mocker, exception): - Vérification que les exceptions n'arrête pas le programme. Args: - mocker (any): Une fixture pour simuler des exceptions. + mocker (MockerFixture): Une fixture pour simuler des exceptions. exception (any): L'exception à simuler. """ mocker.patch("main.ParseurArgumentsCLI", side_effect=exception) @@ -40,7 +40,7 @@ def test_main_succes(mocker): d'un déroulement normal. Args: - mocker (any): Une fixture pour simuler des retours pour les classes + mocker (MockerFixture): Une fixture pour simuler des retours pour les classes et méthodes dans main. """ # Mock des classes pour simuler un fonctionnement correct From 989556f25687968b912c5b883668f6d2c068d63c Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 20:05:38 +0200 Subject: [PATCH 12/13] Docs: Ajout de la documentation de AfficheurCLI - Ajout de la documentation pour la classe AfficheurCLI - Modification de la documentation des constantes de la classe AfficheurCLI --- app/cli/afficheur_cli.py | 6 ++++-- docs/source/modules/cli/afficheur_cli.rst | 7 +++++++ docs/source/modules/cli/index_cli.rst | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 docs/source/modules/cli/afficheur_cli.rst diff --git a/app/cli/afficheur_cli.py b/app/cli/afficheur_cli.py index 2e1a758..6e1fd5e 100644 --- a/app/cli/afficheur_cli.py +++ b/app/cli/afficheur_cli.py @@ -15,14 +15,16 @@ class AfficheurCLI: Représente une classe pour afficher des informations dans la ligne de commande. Attributes: - COULEUR_MESSAGE_NORMAL (str): La couleur pour les messages normaux en CLI. - COULEUR_MESSAGE_ERREUR (str): La couleur pour les messages d'erreur en CLI. _thread_chargement (Union[None,Thread]): Le thread de l'animation de chargement. _thread_chargement_termine (Event): L'évènement pour demander au thread de l'animation de chargement de s'arrêter lorsque le chargement est terminé. _thread_chargement_erreur (Event): L'évènement pour demander au thread de l'animation de chargement de s'arrêter lorsque une erreur s'est produite. _animations_actuelles (dict): Les éléments visuels pour l'animation de chargement. + + Class-level variables: + :cvar COULEUR_MESSAGE_NORMAL: La couleur pour les messages normaux en CLI. + :cvar COULEUR_MESSAGE_ERREUR: La couleur pour les messages d'erreur en CLI. """ COULEUR_MESSAGE_NORMAL = colorama.Fore.WHITE COULEUR_MESSAGE_ERREUR = colorama.Fore.RED diff --git a/docs/source/modules/cli/afficheur_cli.rst b/docs/source/modules/cli/afficheur_cli.rst new file mode 100644 index 0000000..ff28b66 --- /dev/null +++ b/docs/source/modules/cli/afficheur_cli.rst @@ -0,0 +1,7 @@ +AfficheurCLI +====================== + +.. automodule:: cli.afficheur_cli + :members: + :show-inheritance: + :undoc-members: diff --git a/docs/source/modules/cli/index_cli.rst b/docs/source/modules/cli/index_cli.rst index 5494b23..3f644e3 100644 --- a/docs/source/modules/cli/index_cli.rst +++ b/docs/source/modules/cli/index_cli.rst @@ -5,3 +5,4 @@ CLI :maxdepth: 4 parseur_arguments_cli.rst + afficheur_cli.rst From 5dbc592c390c8e29b489af0b5f0d09cc14d77691 Mon Sep 17 00:00:00 2001 From: AnthonyGuillauma Date: Thu, 3 Apr 2025 20:07:49 +0200 Subject: [PATCH 13/13] Docs: Ajout des types pour les constantes de AfficheurCLI - Ajout des types des constantes dans la documentation des constantes de AfficheurCLI --- app/cli/afficheur_cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/cli/afficheur_cli.py b/app/cli/afficheur_cli.py index 6e1fd5e..5083b13 100644 --- a/app/cli/afficheur_cli.py +++ b/app/cli/afficheur_cli.py @@ -23,8 +23,8 @@ class AfficheurCLI: _animations_actuelles (dict): Les éléments visuels pour l'animation de chargement. Class-level variables: - :cvar COULEUR_MESSAGE_NORMAL: La couleur pour les messages normaux en CLI. - :cvar COULEUR_MESSAGE_ERREUR: La couleur pour les messages d'erreur en CLI. + :cvar COULEUR_MESSAGE_NORMAL (str): La couleur pour les messages normaux en CLI. + :cvar COULEUR_MESSAGE_ERREUR (str): La couleur pour les messages d'erreur en CLI. """ COULEUR_MESSAGE_NORMAL = colorama.Fore.WHITE COULEUR_MESSAGE_ERREUR = colorama.Fore.RED