From 2aa99453a04fbdf23189048850b978d3d9c33d2c Mon Sep 17 00:00:00 2001 From: Chahrazad650 Date: Tue, 10 Feb 2026 19:39:47 +0100 Subject: [PATCH 1/2] modefication fonction prix() return None+tests --- main.py | 111 ++++++++++++++++++++------------------------------- test_main.py | 20 +++++----- 2 files changed, 53 insertions(+), 78 deletions(-) diff --git a/main.py b/main.py index a0a06c0..b0ad7b4 100644 --- a/main.py +++ b/main.py @@ -35,90 +35,65 @@ class _ScraperData: return None return cast(dict[str, object], current_data.get("attributes")) - def prix(self) -> float: + def prix(self) -> float | None: """ - Retourne le prix unitaire d'une bouteille (75cl). + Retourne le prix unitaire d'une bouteille (75cl). - Le JSON contient plusieurs formats de vente dans content["items"] : - - bouteille seule : nbunit = 1 et equivbtl = 1 -> prix direct - - caisse de plusieurs bouteilles : nbunit > 1 -> on divise le prix total - - formats spéciaux (magnum etc.) : equivbtl > 1 -> même calcul + Si aucun prix n'est disponible, retourne None. + """ - Formule générale : - prix_unitaire = offerPrice / (nbunit * equivbtl) - - """ - - content = self._getcontent() - - # si content n'existe pas -> erreur + content = self._getcontent() + if content is None: - raise ValueError("Contenu introuvable") + return None - # On récupère la liste des formats disponibles (bouteille, carton...) items = content.get("items") - # Vérification que items est bien une liste non vide - if not isinstance(items, list) or len(items) == 0: - raise ValueError("Aucun prix disponible (items vide)") - - # -------------------------- - # CAS 1 : bouteille unitaire - # -------------------------- - # On cherche un format où nbunit=1 et equivbtl=1 ->bouteille standard 75cl - for item in items: + # Si aucun format disponible -> pas de prix + if isinstance(items, list): - if not isinstance(item, dict): - continue + if len(items) == 0: + return None - # On récupère les attributs du format - attrs = item.get("attributes", {}) + for item in items: - # On récupère nbunit et equivbtl - nbunit = attrs.get("nbunit", {}).get("value") - equivbtl = attrs.get("equivbtl", {}).get("value") + if not isinstance(item, dict): + continue - # Si c'est une bouteille unitaire - if nbunit == "1" and equivbtl == "1": + attrs = item.get("attributes", {}) + + nbunit = attrs.get("nbunit", {}).get("value") + equivbtl = attrs.get("equivbtl", {}).get("value") + + if nbunit == "1" and equivbtl == "1": + + p = item.get("offerPrice") + + if isinstance(p, (int, float)): + return float(p) + + for item in items: + + if not isinstance(item, dict): + continue p = item.get("offerPrice") + attrs = item.get("attributes", {}) - # Vérification que c'est bien un nombre - if isinstance(p, (int, float)): - return float(p) + nbunit = attrs.get("nbunit", {}).get("value") + equivbtl = attrs.get("equivbtl", {}).get("value") - # -------------------------- - # CAS 2 : caisse ou autre format - # -------------------------- - # On calcule le prix unitaire à partir du prix total - for item in items: + if isinstance(p, (int, float)) and nbunit and equivbtl: - if not isinstance(item, dict): - continue + denom = float(nbunit) * float(equivbtl) - p = item.get("offerPrice") - attrs = item.get("attributes", {}) + if denom > 0: - nbunit = attrs.get("nbunit", {}).get("value") - equivbtl = attrs.get("equivbtl", {}).get("value") + prix_unitaire = float(p) / denom - # Vérification que toutes les valeurs existent - if isinstance(p, (int, float)) and nbunit and equivbtl: + return round(prix_unitaire, 2) - # Calcul du nombre total de bouteilles équivalentes - denom = float(nbunit) * float(equivbtl) - - # Évite division par zéro - if denom > 0: - - # Calcul du prix unitaire - prix_unitaire = float(p) / denom - - # Arrondi à 2 décimales - return round(prix_unitaire, 2) - - # Si aucun prix trouvé - raise ValueError("Impossible de trouver le prix unitaire.") + return None def appellation(self) -> str | None: """_summary_ @@ -181,12 +156,14 @@ class _ScraperData: parker = self.parker() robinson = self.robinson() suckling = self.suckling() - prix = self.prix() - + try: + prix = self.prix() + except ValueError: + prix = None + return f"{appellation},{parker},{robinson},{suckling},{prix}" - class Scraper: """ Scraper est une classe qui permet de gerer diff --git a/test_main.py b/test_main.py index be5f703..2297262 100644 --- a/test_main.py +++ b/test_main.py @@ -225,22 +225,20 @@ def test_critiques(scraper: Scraper): assert contenu.suckling() == "93.5" assert contenu._getcritiques("test_ts") is None + def test_prix(scraper: Scraper): vide = scraper.getjsondata("") poubelle = scraper.getjsondata("poubelle") contenu = scraper.getjsondata("nino-negri-5-stelle-sfursat-2022.html") - - # Cas vide : items == [] -> on ne peut pas calculer -> ValueError - with pytest.raises(ValueError): - _ = vide.prix() - - # Cas poubelle : JSON incomplet -> _getcontent() None -> ValueError - with pytest.raises(ValueError): - _ = poubelle.prix() - + assert vide.prix() is None + assert poubelle.prix() is None assert contenu.prix() == 65.0 - + + def test_informations(scraper: Scraper): contenu = scraper.getjsondata("nino-negri-5-stelle-sfursat-2022.html") assert contenu.informations() == "Sforzato di Valtellina,91,17,93.5,65.0" - + vide = scraper.getjsondata("") + poubelle = scraper.getjsondata("poubelle") + assert vide.informations() == "None,None,None,None,None" + assert poubelle.informations() == "None,None,None,None,None" From cd1e266f25f7644bfb09c7a374b04136fae29981 Mon Sep 17 00:00:00 2001 From: Chahrazad650 Date: Tue, 10 Feb 2026 19:57:20 +0100 Subject: [PATCH 2/2] optimisation fonction prix() --- main.py | 76 +++++++++++++++++++++++---------------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/main.py b/main.py index b0ad7b4..c820cd3 100644 --- a/main.py +++ b/main.py @@ -43,58 +43,44 @@ class _ScraperData: """ content = self._getcontent() - if content is None: return None items = content.get("items") - # Si aucun format disponible -> pas de prix - if isinstance(items, list): - - if len(items) == 0: - return None - - for item in items: - - if not isinstance(item, dict): - continue - - attrs = item.get("attributes", {}) - - nbunit = attrs.get("nbunit", {}).get("value") - equivbtl = attrs.get("equivbtl", {}).get("value") - - if nbunit == "1" and equivbtl == "1": - - p = item.get("offerPrice") - - if isinstance(p, (int, float)): - return float(p) - - for item in items: - - if not isinstance(item, dict): - continue - - p = item.get("offerPrice") - attrs = item.get("attributes", {}) - - nbunit = attrs.get("nbunit", {}).get("value") - equivbtl = attrs.get("equivbtl", {}).get("value") - - if isinstance(p, (int, float)) and nbunit and equivbtl: - - denom = float(nbunit) * float(equivbtl) - - if denom > 0: - - prix_unitaire = float(p) / denom - - return round(prix_unitaire, 2) - + # Vérifie que items existe et n'est pas vide + if not isinstance(items, list) or len(items) == 0: return None + prix_calcule: float | None = None + + for item in items: + + if not isinstance(item, dict): + continue + + p = item.get("offerPrice") + attrs = item.get("attributes", {}) + + nbunit = attrs.get("nbunit", {}).get("value") + equivbtl = attrs.get("equivbtl", {}).get("value") + + if not isinstance(p, (int, float)) or not nbunit or not equivbtl: + continue + + nb = float(nbunit) + eq = float(equivbtl) + + if nb <= 0 or eq <= 0: + continue + + if nb == 1 and eq == 1: + return float(p) + + prix_calcule = round(float(p) / (nb * eq), 2) + + return prix_calcule + def appellation(self) -> str | None: """_summary_