{"content":"# Rapport QA - Bitcoin Price Tracker\n\n## Analyse complète du code\n\n---\n\nSTATUT: OK\n\nBUGS:\n- Bug 1 : **Mutation de l'objet partagé `API_PARAMS` (risque mineur mais mauvaise pratique)** — Ligne 30-33 — `API_PARAMS` est un dictionnaire global mutable. Si une fonction modifiait accidentellement ce dictionnaire, toutes les requêtes suivantes seraient affectées. Correction suggérée : utiliser une copie locale dans `get_bitcoin_price()` avec `params=API_PARAMS.copy()` ou définir les params directement dans la fonction.\n\n- Bug 2 : **Gestion incomplète de `KeyboardInterrupt` dans la boucle** — Ligne 196-202 — Le `KeyboardInterrupt` est capturé à l'intérieur du bloc `while True`, mais il est géré correctement avec un `break`. Cependant, si le `KeyboardInterrupt` survient pendant `time.sleep(REFRESH_INTERVAL)` à la ligne 210, il sera bien intercepté. Mais si un `KeyboardInterrupt` se produit pendant `get_bitcoin_price()` (notamment dans `requests.get()`), il sera capturé par le bloc `except Exception as e` (ligne 204) au lieu du bloc `except KeyboardInterrupt`, car `KeyboardInterrupt` hérite de `BaseException` et non `Exception` — donc ce point est en réalité **correct** en Python 3. Pas de bug ici, mais attention dans des portages Python 2.\n\n- Bug 3 : **Absence de vérification du type des valeurs USD/EUR retournées par l'API** — Lignes 90-97 — La conversion `float(usd_price)` peut lever une `ValueError` si l'API retourne une chaîne non convertible. Bien que ce cas soit géré par le bloc `except (ValueError, KeyError)` en ligne 111, il serait plus robuste d'ajouter une validation préalable : `if not isinstance(usd_price, (int, float)): ...` avant la conversion.\n\n- Bug 4 : **Variable `variation_display` construite mais jamais utilisée** — Ligne 155 — Dans `display_prices()`, la variable `variation_display = \"\"` est assignée à la ligne 155 mais n'est jamais utilisée par la suite dans la fonction. C'est du code mort. Correction suggérée : supprimer cette ligne inutile.\n\n- Bug 5 : **Formatage des nombres avec virgule (`,`) potentiellement incorrect selon la locale** — Lignes 147-148 — Le formatage `f\"${prices['usd']:,.2f}\"` utilise la virgule américaine comme séparateur de milliers (ex: `$95,000.00`), ce qui est correct pour USD. Cependant, pour l'EUR (`€{prices['eur']:,.2f}`), le format attendu en Europe serait `95.000,00` et non `95,000.00`. Il y a une incohérence culturelle dans l'affichage EUR. Correction suggérée : utiliser `locale` pour formater correctement selon la devise, ou documenter explicitement que le format est volontairement américain.\n\n- Bug 6 : **Pas de gestion du cas `variation_pct = 0.0` dans le signe** — Ligne 161 — `sign = \"+\" if variation_pct > 0 else \"\"` — Si `variation_pct` est exactement `0.0` mais que `trend` est \"◆ STABLE\", ce chemin ne sera jamais atteint car la branche `is_first or trend is None` serait fausse mais le trend serait \"STABLE\". L'affichage sera `(0.00%)` sans signe, ce qui est acceptable, mais on pourrait préférer `(±0.00%)` pour la clarté. Mineur.\n\n- Bug 7 : **Absence de timeout global ou de limite de tentatives en cas d'erreurs API répétées** — Lignes 186-192 — Si l'API est indisponible pendant une longue période, le script continuera de boucler indéfiniment sans jamais informer l'utilisateur du nombre de tentatives échouées. Correction suggérée : ajouter un compteur de tentatives consécutives échouées et afficher un avertissement après N échecs (ex: 5 tentatives).\n\n- Bug 8 : **`colorama_init(autoreset=True)` rend les fonctions de couleur partiellement redondantes** — Lignes 23-24 et 41-43 — Avec `autoreset=True`, colorama réinitialise automatiquement le style après chaque `print()`. Cependant, les fonctions `color_*` ajoutent explicitement `{Style.RESET_ALL}` à la fin du texte coloré, ce qui est redondant avec `autoreset=True`. Ce n'est pas un bug fonctionnel mais une duplication inutile. Correction suggérée : retirer `{Style.RESET_ALL}` des f-strings puisque `autoreset=True` s'en charge.\n\n- Bug 9 : **Pas de gestion des erreurs JSON malformé distinct de `ValueError`** — Ligne 111 — `response.json()` peut lever `requests.exceptions.JSONDecodeError` (sous-classe de `ValueError` en Python 3.5+, mais sous-classe de `json.JSONDecodeError`). La gestion actuelle via `except (ValueError, KeyError)` capture correctement ce cas en Python 3, mais pour plus de clarté et de robustesse, il serait préférable d'ajouter `except requests.exceptions.JSONDecodeError` séparément avant le bloc `ValueError`.\n\n- Bug 10 : **Le script ne gère pas la limite de taux (rate limiting) de l'API CoinGecko** — Global — L'API publique CoinGecko limite les requêtes (environ 10-50 appels/minute). Avec `REFRESH_INTERVAL = 15` secondes, le script fait ~4 requêtes/minute, ce qui est dans les limites. Cependant, en cas d'erreur HTTP 429 (Too Many Requests), bien que `raise_for_status()` lève une `HTTPError` gérée, il n'y a pas de logique d'attente exponentielle (exponential backoff). Correction suggérée : détecter spécifiquement le code 429 et augmenter temporairement le délai d'attente.\n\n---\n\nSCORE: 7/10\n\n**Résumé** : Le code est globalement bien structuré, lisible et fonctionnel. La gestion des erreurs est présente et couvre les cas principaux. Les problèmes identifiés sont majoritairement des améliorations de robustesse et des incohérences mineures (variable inutilisée, format locale EUR, redondance colorama) plutôt que des bugs bloquants. Le bug le plus notable est la variable `variation_display` non utilisée (code mort, ligne 155) et l'absence de backoff exponentiel pour le rate limiting API."}