Skip to content

Commit e90d943

Browse files
committed
fix: generate Data360 verification URLs for non-WDI databases to prevent broken classic API links
1 parent c47d663 commit e90d943

2 files changed

Lines changed: 64 additions & 17 deletions

File tree

lib/wb_client/wdi_client.py

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -450,12 +450,21 @@ def _clean(text: str | None) -> str | None:
450450
f"?DATABASE_ID={_wgi_db_id}&INDICATOR={wgi_ind_id}"
451451
f"&REF_AREA=WLD&COMP_BREAKDOWN_1=WGI_EST"
452452
)
453-
elif indicator_code.startswith("WB_") or indicator_code.startswith("IMF_"):
454-
parts = indicator_code.split("_")
455-
classic_code = ".".join(parts[2:])
453+
elif indicator_code in _GHG_CODES:
456454
verifier_url = (
457-
f"https://api.worldbank.org/v2/indicator/{classic_code}?format=json"
455+
f"{DATA360_BASE_URL}/data360/data"
456+
f"?DATABASE_ID={meta_db_id}&INDICATOR={full_indicator_id}&REF_AREA=WLD"
458457
)
458+
elif indicator_code.startswith("WB_") or indicator_code.startswith("IMF_"):
459+
parts = indicator_code.split("_")
460+
if len(parts) >= 2 and parts[1] == "WDI":
461+
classic_code = ".".join(parts[2:])
462+
verifier_url = f"https://api.worldbank.org/v2/indicator/{classic_code}?format=json"
463+
else:
464+
verifier_url = (
465+
f"{DATA360_BASE_URL}/data360/data"
466+
f"?DATABASE_ID={meta_db_id}&INDICATOR={full_indicator_id}&REF_AREA=WLD"
467+
)
459468
else:
460469
verifier_url = f"https://api.worldbank.org/v2/indicator/{indicator_code}?format=json"
461470

@@ -807,19 +816,31 @@ def fetch_time_series(
807816
display_code = indicator_code # keep CC.EST as the label
808817
elif indicator_code.startswith("WB_") or indicator_code.startswith("IMF_"):
809818
parts = indicator_code.split("_")
810-
seal_code = ".".join(parts[2:])
811-
countries_str = ";".join(countries)
812-
verifiable_url = (
813-
f"{CLASSIC_BASE_URL}/country/{countries_str}/indicator/{seal_code}"
814-
f"?format=json&per_page=500"
815-
)
816-
if start_year and end_year:
817-
verifiable_url += f"&date={start_year}:{end_year}"
818-
elif start_year:
819-
verifiable_url += f"&date={start_year}:2030"
820-
elif end_year:
821-
verifiable_url += f"&date=1960:{end_year}"
822-
display_code = seal_code
819+
if len(parts) >= 2 and parts[1] == "WDI":
820+
seal_code = ".".join(parts[2:])
821+
countries_str = ";".join(countries)
822+
verifiable_url = (
823+
f"{CLASSIC_BASE_URL}/country/{countries_str}/indicator/{seal_code}"
824+
f"?format=json&per_page=500"
825+
)
826+
if start_year and end_year:
827+
verifiable_url += f"&date={start_year}:{end_year}"
828+
elif start_year:
829+
verifiable_url += f"&date={start_year}:2030"
830+
elif end_year:
831+
verifiable_url += f"&date=1960:{end_year}"
832+
display_code = seal_code
833+
else:
834+
# Non-WDI database (like WB_ESG, IMF_IFS, etc.) -> use Data360 GET URL
835+
verifiable_url = (
836+
f"{DATA360_BASE_URL}/data360/data?DATABASE_ID={database_id}"
837+
f"&INDICATOR={full_indicator_id}&REF_AREA={','.join(countries)}"
838+
)
839+
if start_year:
840+
verifiable_url += f"&timePeriodFrom={start_year}"
841+
if end_year:
842+
verifiable_url += f"&timePeriodTo={end_year}"
843+
display_code = indicator_code
823844
elif indicator_code in _GHG_CODES:
824845
# GHG indicators: Classic WB API removed these in 2023; Data360 is authoritative.
825846
# Use the already-computed database_id and full_indicator_id.

tests/test_data_api.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,32 @@ def test_ghg_total_seal_url_uses_data360(self, responses):
438438
assert "data360api.worldbank.org" in result["retrieval_url"]
439439
assert "api.worldbank.org/v2" not in result["retrieval_url"]
440440

441+
def test_esg_seal_url_uses_data360(self, responses):
442+
"""Indicators in non-WDI databases like WB_ESG must use Data360 URL, not Classic API."""
443+
responses.add(
444+
responses_lib.GET,
445+
"https://data360api.worldbank.org/data360/data",
446+
json={
447+
"count": 1,
448+
"value": [
449+
{
450+
"REF_AREA": "IND",
451+
"TIME_PERIOD": "2020",
452+
"OBS_VALUE": "1.57",
453+
"INDICATOR": "WB_ESG_EN_ATM_CO2E_PC",
454+
"DATABASE_ID": "WB_ESG",
455+
}
456+
],
457+
},
458+
status=200,
459+
)
460+
461+
result = get_time_series("WB_ESG_EN_ATM_CO2E_PC", ["IND"])
462+
463+
assert result["data_available"] is True
464+
assert "data360api.worldbank.org" in result["retrieval_url"]
465+
assert "api.worldbank.org/v2" not in result["retrieval_url"]
466+
441467

442468
class TestDataCoverageNote:
443469
"""Bug 3 fix: data_coverage_note fires when max_data_year < current_year - 1."""

0 commit comments

Comments
 (0)