sws-api-client 2.7.2__tar.gz → 2.7.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/PKG-INFO +1 -1
  2. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/pyproject.toml +1 -1
  3. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/data_retrieval.py +56 -6
  4. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/datasets.py +3 -3
  5. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/datatable.py +3 -3
  6. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/sessions.py +3 -3
  7. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/LICENSE +0 -0
  8. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/README.md +0 -0
  9. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/__init__.py +0 -0
  10. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/auth.py +0 -0
  11. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/codelist.py +0 -0
  12. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/db.py +0 -0
  13. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/discover.py +0 -0
  14. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/files.py +0 -0
  15. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/flaglist.py +0 -0
  16. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/generic_models.py +0 -0
  17. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/mail.py +0 -0
  18. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/metadata_instances.py +0 -0
  19. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/plugins.py +0 -0
  20. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/s3.py +0 -0
  21. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/sws_api_client.py +0 -0
  22. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/tags.py +0 -0
  23. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/tasks.py +0 -0
  24. {sws_api_client-2.7.2 → sws_api_client-2.7.3}/sws_api_client/token.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sws_api_client
3
- Version: 2.7.2
3
+ Version: 2.7.3
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Matteo
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "sws_api_client"
3
- version = "2.7.2"
3
+ version = "2.7.3"
4
4
  description = ""
5
5
  authors = ["Matteo <matteo.terrinoni@fao.org>", "Daniele <daniele.mansillo@fao.org>"]
6
6
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  from time import time
3
- from typing import Callable, Dict, Any
3
+ from typing import Callable, Dict, Any, Optional, TypedDict
4
4
 
5
5
  import pandas as pd
6
6
  import requests
@@ -12,6 +12,20 @@ from sws_api_client.tasks import TaskManager, PluginPayload
12
12
  logger = logging.getLogger(__name__)
13
13
 
14
14
 
15
+ class GetDataMetadata(TypedDict):
16
+ retrieval_method: Optional[str]
17
+ task_id: Optional[str]
18
+ url: Optional[str]
19
+ execution_time_seconds: Optional[float]
20
+ error: Optional[str]
21
+
22
+
23
+ class GetDataResult(TypedDict):
24
+ data: Optional[pd.DataFrame]
25
+ metadata: GetDataMetadata
26
+ success: bool
27
+
28
+
15
29
  class DataRetrieval:
16
30
  """Generic utility for data retrieval with fallback strategy.
17
31
 
@@ -36,11 +50,11 @@ class DataRetrieval:
36
50
  plugin_params: Dict[str, Any],
37
51
  s3_export: bool = False,
38
52
  cache_time: int = 0,
39
- ) -> Dict[str, Any]:
53
+ ) -> GetDataResult:
40
54
  start_time = time()
41
55
  logger.debug("Starting generic data retrieval for %s %s", entity_type, entity_id)
42
56
 
43
- metadata_info: Dict[str, Any] = {
57
+ metadata_info: GetDataMetadata = {
44
58
  "retrieval_method": None,
45
59
  "task_id": None,
46
60
  "url": None,
@@ -344,10 +358,46 @@ class DataRetrieval:
344
358
  except Exception as e:
345
359
  logger.warning("Failed to parse CSV after plugin execution: %s", str(e))
346
360
 
347
- logger.info("Plugin task created successfully for %s %s", entity_type, entity_id)
348
- metadata_info["retrieval_method"] = "plugin_task"
361
+ # Fallback: Check for task artifact
362
+ output = task_response.info.output
363
+ output_type = None
364
+ if hasattr(output, 'type'):
365
+ output_type = output.type
366
+ elif isinstance(output, dict):
367
+ output_type = output.get('type')
368
+
369
+ if output_type == 'file':
370
+ logger.debug("Checking task artifact for data...")
371
+ try:
372
+ artifact_url = tasks.get_task_artifact_url(task_id)
373
+ resp = requests.get(artifact_url)
374
+ if resp.status_code == 200:
375
+ from io import StringIO
376
+ df = pd.read_csv(StringIO(resp.text), dtype=str)
377
+ for col in ['Value', 'value']:
378
+ if col in df.columns:
379
+ df[col] = pd.to_numeric(df[col], errors='coerce')
380
+
381
+ logger.info(
382
+ "Retrieved data from task artifact (%s rows)",
383
+ len(df),
384
+ )
385
+ metadata_info["retrieval_method"] = "plugin_task_artifact"
386
+ metadata_info["url"] = artifact_url
387
+ metadata_info["execution_time_seconds"] = time() - start_time
388
+ return {
389
+ "data": df,
390
+ "metadata": metadata_info,
391
+ "success": True,
392
+ "source": "task_artifact"
393
+ }
394
+ except Exception as e:
395
+ logger.warning("Failed to retrieve/parse task artifact: %s", str(e))
396
+
397
+ logger.error("Plugin task succeeded but no data could be retrieved for %s %s", entity_type, entity_id)
398
+ metadata_info["error"] = "Task succeeded but data retrieval failed"
349
399
  metadata_info["execution_time_seconds"] = time() - start_time
350
- return {"data": plugin_resp, "metadata": metadata_info, "success": True}
400
+ return {"data": None, "metadata": metadata_info, "success": False}
351
401
 
352
402
  logger.error(
353
403
  "Plugin task failed for %s %s: %s",
@@ -12,7 +12,7 @@ from sws_api_client.flaglist import Flaglists
12
12
  from sws_api_client.generic_models import Code, Multilanguage
13
13
  from sws_api_client.sws_api_client import SwsApiClient
14
14
  from sws_api_client.s3 import S3
15
- from sws_api_client.data_retrieval import DataRetrieval
15
+ from sws_api_client.data_retrieval import DataRetrieval, GetDataResult
16
16
  import pandas as pd
17
17
  from concurrent.futures import ThreadPoolExecutor, as_completed
18
18
 
@@ -859,7 +859,7 @@ class Datasets:
859
859
  metadata_as_array: bool = False,
860
860
  cache_time: int = 0,
861
861
  plugin_name: str = "get_data",
862
- ) -> Dict[str, Any]:
862
+ ) -> GetDataResult:
863
863
  """Retrieve dataset data using the shared DataRetrieval fallback strategy.
864
864
 
865
865
  Args:
@@ -884,7 +884,7 @@ class Datasets:
884
884
  plugin_name (str): Name of the plugin invoking this method. Defaults to "get_data".
885
885
 
886
886
  Returns:
887
- Dict[str, Any]: The dataset data.
887
+ GetDataResult: The dataset data.
888
888
  """
889
889
 
890
890
  def sql_query_fn(force_s3: bool = False) -> Dict:
@@ -12,7 +12,7 @@ from typing import Literal
12
12
  from datetime import datetime
13
13
  from time import sleep
14
14
  from sws_api_client.s3 import S3
15
- from sws_api_client.data_retrieval import DataRetrieval
15
+ from sws_api_client.data_retrieval import DataRetrieval, GetDataResult
16
16
  import json
17
17
  import pandas as pd
18
18
  import tempfile
@@ -382,7 +382,7 @@ class Datatables:
382
382
  s3_export: bool = False,
383
383
  cache_time: int = 0,
384
384
  plugin_name: str = "get_datatable_data",
385
- ) -> Dict[str, Any]:
385
+ ) -> GetDataResult:
386
386
  """Retrieve datatable data using the shared DataRetrieval fallback strategy.
387
387
 
388
388
  Args:
@@ -398,7 +398,7 @@ class Datatables:
398
398
  plugin_name (str): Name of the plugin invoking this method. Defaults to "get_datatable_data".
399
399
 
400
400
  Returns:
401
- Dict[str, Any]: The datatable data.
401
+ GetDataResult: The datatable data.
402
402
  """
403
403
 
404
404
  def sql_query_fn(force_s3: bool = False) -> Dict:
@@ -5,7 +5,7 @@ import pandas as pd
5
5
  from pydantic import BaseModel
6
6
  from sws_api_client.datasets import Datasets, ValueFilter, MetadataFilter, FlagsFilter, DimensionsProps
7
7
  from sws_api_client.sws_api_client import SwsApiClient
8
- from sws_api_client.data_retrieval import DataRetrieval
8
+ from sws_api_client.data_retrieval import DataRetrieval, GetDataResult
9
9
 
10
10
  import logging
11
11
 
@@ -272,7 +272,7 @@ class Sessions:
272
272
  limit: Optional[int] = None,
273
273
  metadata_as_array: bool = False,
274
274
  cache_time: int = 0,
275
- ) -> Dict:
275
+ ) -> GetDataResult:
276
276
  """Retrieve session data using the shared DataRetrieval fallback strategy.
277
277
 
278
278
  Args:
@@ -291,7 +291,7 @@ class Sessions:
291
291
  cache_time (int): Cache time in seconds. Defaults to 0.
292
292
 
293
293
  Returns:
294
- Dict: The session data.
294
+ GetDataResult: The session data.
295
295
  """
296
296
 
297
297
  def sql_query_fn(force_s3: bool = False) -> Dict:
File without changes
File without changes