MMOON commited on
Commit
cdf24f8
·
verified ·
1 Parent(s): 61e1dfd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -50
app.py CHANGED
@@ -42,7 +42,11 @@ class PesticideDataFetcher:
42
  response = self.session.get(url, timeout=10)
43
  response.raise_for_status()
44
  data = response.json()
45
- logger.info(f"Réponse API pour {url}: {data[:200]}")
 
 
 
 
46
  return data
47
  except requests.RequestException as e:
48
  logger.error(f"Échec de la requête {url}: {e}")
@@ -50,22 +54,27 @@ class PesticideDataFetcher:
50
 
51
  def preload_substance_names(self):
52
  url = f"{self.BASE_URL}/active_substances?format=json&api-version=v2.0"
53
- while url:
54
- data = self.fetch_data(url)
55
- if "error" in data:
56
- logger.error(f"Erreur préchargement substances: {data.get('error')}")
57
- break
58
- for item in data.get("value", []):
59
- substance_id = item.get("substanceId") # Utilisation de substanceId (camelCase)
60
- if substance_id:
61
- self._substance_cache[substance_id] = SubstanceDetails(
62
- name=item.get("substanceName", "Nom non trouvé"),
63
- status=item.get("substanceStatus"),
64
- approval_date=item.get("approvalDate"),
65
- expiry_date=item.get("expiryDate")
66
- )
67
- url = data.get("nextLink")
68
- logger.info(f"Cache substances prérempli avec {len(self._substance_cache)} entrées")
 
 
 
 
 
69
 
70
  def get_product_list(self) -> List[Dict[str, Any]]:
71
  if self._product_cache:
@@ -74,10 +83,10 @@ class PesticideDataFetcher:
74
  while url:
75
  data = self.fetch_data(url)
76
  if "error" in data:
77
- logger.error(f"Erreur récupération produits: {data.get('error')}")
78
  break
79
  for product in data.get("value", []):
80
- product_id = product.get("productId") # Utilisation de productId (camelCase)
81
  if product_id:
82
  self._product_cache[product_id] = product
83
  url = data.get("nextLink")
@@ -88,18 +97,21 @@ class PesticideDataFetcher:
88
  url = f"{self.BASE_URL}/pesticide_residues_mrls?format=json&product_id={product_id}&api-version=v2.0"
89
  response = self.fetch_data(url)
90
  if "error" in response:
91
- logger.error(f"Erreur MRLs pour {product_id}: {response.get('error')}")
92
  return []
93
  return response.get("value", [])
94
 
 
 
 
 
95
  class PesticideApp:
96
  def __init__(self):
97
  self.fetcher = PesticideDataFetcher()
98
  self.product_list = {
99
- p.get('productName', 'Aucun nom'): p.get('productId', 0) # Utilisation de productName (camelCase)
100
  for p in self.fetcher.get_product_list()
101
  }
102
- # Correction : Accès au cache via self.fetcher
103
  self.substances = [
104
  sd.name for sd in self.fetcher._substance_cache.values()
105
  ]
@@ -112,7 +124,7 @@ class PesticideApp:
112
  return datetime.strptime(date_str, fmt).strftime("%d/%m/%Y")
113
  except ValueError:
114
  continue
115
- return "Format inconnu"
116
 
117
  def get_product_details(self, product_name: str) -> pd.DataFrame:
118
  product_id = self.product_list.get(product_name)
@@ -120,28 +132,28 @@ class PesticideApp:
120
  return pd.DataFrame([{"Erreur": "Produit non trouvé"}])
121
 
122
  mrls = self.fetcher.get_mrls(product_id)
 
 
 
123
  data = []
124
  for mrl in mrls:
125
- substance_id = mrl.get("pesticideResidueId", 0) # Utilisation de pesticideResidueId (camelCase)
126
- substance_name = self.fetcher._substance_cache.get(substance_id, {}).get("name", "Substance inconnue")
 
127
 
128
  data.append({
129
  "Substance": substance_name,
130
  "Valeur LMR": mrl.get("mrlValue", "N/C"),
131
- "Date d'effet": self.format_date(mrl.get("entryIntoForceDate")), # entryIntoForceDate (camelCase)
132
- "Statut": self.fetcher._substance_cache.get(substance_id, {}).get("status", "N/C")
133
  })
134
  return pd.DataFrame(data)
135
 
136
- def search_substances(self, query: str) -> pd.DataFrame:
137
- matches = [s for s in self.substances if query.lower() in s.lower()]
138
- return pd.DataFrame(matches, columns=["Substance"]) if matches else pd.DataFrame([{"Message": "Aucun résultat"}])
139
-
140
  def create_ui(self) -> gr.Blocks:
141
- with gr.Blocks() as ui:
142
  gr.HTML("""
143
  <div style="text-align: center; padding: 20px; background: #006633; color: white;">
144
- <h1>Base de Données Pesticides UE</h1>
145
  </div>
146
  """)
147
 
@@ -154,6 +166,7 @@ class PesticideApp:
154
  output = gr.Dataframe(
155
  headers=["Substance", "Valeur LMR", "Date d'effet", "Statut"],
156
  max_height=500,
 
157
  interactive=False
158
  )
159
  product.change(
@@ -161,22 +174,6 @@ class PesticideApp:
161
  inputs=[product],
162
  outputs=output
163
  )
164
-
165
- with gr.Tab("Recherche par Substance"):
166
- substance_search = gr.Textbox(
167
- label="Rechercher une substance",
168
- placeholder="Entrez un nom..."
169
- )
170
- substance_results = gr.Dataframe(max_height=300)
171
- substance_search.submit(
172
- fn=self.search_substances,
173
- inputs=[substance_search],
174
- outputs=substance_results
175
- )
176
-
177
- gr.Button("Actualiser les données", variant="secondary").click(
178
- lambda: self.fetcher.preload_substance_names()
179
- )
180
  return ui
181
 
182
  def main():
@@ -184,4 +181,4 @@ def main():
184
  app.create_ui().launch(share=False)
185
 
186
  if __name__ == "__main__":
187
- main()
 
42
  response = self.session.get(url, timeout=10)
43
  response.raise_for_status()
44
  data = response.json()
45
+ # Correction du slicing et vérification du type de `data`
46
+ if isinstance(data, dict):
47
+ logger.info(f"Réponse API pour {url}: {str(data)[:200]}")
48
+ else:
49
+ logger.warning(f"Réponse inattendue de l'API pour {url}: {type(data)}")
50
  return data
51
  except requests.RequestException as e:
52
  logger.error(f"Échec de la requête {url}: {e}")
 
54
 
55
  def preload_substance_names(self):
56
  url = f"{self.BASE_URL}/active_substances?format=json&api-version=v2.0"
57
+ with ThreadPoolExecutor(max_workers=5) as executor:
58
+ while url:
59
+ data = self.fetch_data(url)
60
+ if "error" in data:
61
+ logger.error(f"Erreur lors du préchargement: {data.get('error', 'Aucune info')}")
62
+ break
63
+ tasks = []
64
+ for item in data.get("value", []):
65
+ tasks.append(executor.submit(self._cache_substance, item))
66
+ url = data.get("nextLink")
67
+ logger.info(f"Cache prérempli avec {len(self._substance_cache)} substances")
68
+
69
+ def _cache_substance(self, item: Dict[str, Any]):
70
+ substance_id = item.get("substanceId")
71
+ if substance_id:
72
+ self._substance_cache[substance_id] = SubstanceDetails(
73
+ name=item.get("substanceName", "Nom non trouvé"),
74
+ status=item.get("substanceStatus"),
75
+ approval_date=item.get("approvalDate"),
76
+ expiry_date=item.get("expiryDate")
77
+ )
78
 
79
  def get_product_list(self) -> List[Dict[str, Any]]:
80
  if self._product_cache:
 
83
  while url:
84
  data = self.fetch_data(url)
85
  if "error" in data:
86
+ logger.error(f"Erreur produits: {data.get('error', 'Aucune info')}")
87
  break
88
  for product in data.get("value", []):
89
+ product_id = product.get("productId")
90
  if product_id:
91
  self._product_cache[product_id] = product
92
  url = data.get("nextLink")
 
97
  url = f"{self.BASE_URL}/pesticide_residues_mrls?format=json&product_id={product_id}&api-version=v2.0"
98
  response = self.fetch_data(url)
99
  if "error" in response:
100
+ logger.error(f"Erreur MRLs pour le produit {product_id}: {response.get('error', 'Aucune info')}")
101
  return []
102
  return response.get("value", [])
103
 
104
+ def get_substance_name(self, substance_id: int) -> str:
105
+ substance = self._substance_cache.get(substance_id)
106
+ return substance.name if substance else f"Substance {substance_id}"
107
+
108
  class PesticideApp:
109
  def __init__(self):
110
  self.fetcher = PesticideDataFetcher()
111
  self.product_list = {
112
+ p.get('productName', 'Aucun nom'): p.get('productId', 0)
113
  for p in self.fetcher.get_product_list()
114
  }
 
115
  self.substances = [
116
  sd.name for sd in self.fetcher._substance_cache.values()
117
  ]
 
124
  return datetime.strptime(date_str, fmt).strftime("%d/%m/%Y")
125
  except ValueError:
126
  continue
127
+ return "Format de date inconnu"
128
 
129
  def get_product_details(self, product_name: str) -> pd.DataFrame:
130
  product_id = self.product_list.get(product_name)
 
132
  return pd.DataFrame([{"Erreur": "Produit non trouvé"}])
133
 
134
  mrls = self.fetcher.get_mrls(product_id)
135
+ if not mrls:
136
+ return pd.DataFrame([{"Erreur": "Aucune donnée MRL trouvée"}])
137
+
138
  data = []
139
  for mrl in mrls:
140
+ substance_id = mrl.get("pesticideResidueId", 0)
141
+ substance_name = self.fetcher.get_substance_name(substance_id)
142
+ substance = self.fetcher._substance_cache.get(substance_id)
143
 
144
  data.append({
145
  "Substance": substance_name,
146
  "Valeur LMR": mrl.get("mrlValue", "N/C"),
147
+ "Date d'effet": self.format_date(mrl.get("entryIntoForceDate")),
148
+ "Statut": getattr(substance, "status", "N/C")
149
  })
150
  return pd.DataFrame(data)
151
 
 
 
 
 
152
  def create_ui(self) -> gr.Blocks:
153
+ with gr.Blocks(theme=gr.themes.Default()) as ui:
154
  gr.HTML("""
155
  <div style="text-align: center; padding: 20px; background: #006633; color: white;">
156
+ <h1>Base de Données des Pesticides UE</h1>
157
  </div>
158
  """)
159
 
 
166
  output = gr.Dataframe(
167
  headers=["Substance", "Valeur LMR", "Date d'effet", "Statut"],
168
  max_height=500,
169
+ overflow_scroll=True,
170
  interactive=False
171
  )
172
  product.change(
 
174
  inputs=[product],
175
  outputs=output
176
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  return ui
178
 
179
  def main():
 
181
  app.create_ui().launch(share=False)
182
 
183
  if __name__ == "__main__":
184
+ main()