hdx-python-country 3.8.2__tar.gz → 3.8.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.
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/.config/pre-commit-config.yaml +3 -3
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/PKG-INFO +3 -2
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/pyproject.toml +5 -5
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/requirements.txt +13 -9
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/src/hdx/location/_version.py +2 -2
- hdx_python_country-3.8.3/src/hdx/location/wfp_api.py +157 -0
- hdx_python_country-3.8.3/src/hdx/location/wfp_exchangerates.py +73 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_List_1.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_List_2.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_1.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_10.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_2.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_3.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_4.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_5.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_6.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_7.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_8.json +1 -0
- hdx_python_country-3.8.3/tests/fixtures/wfp/Currency_UsdIndirectQuotation_9.json +1 -0
- hdx_python_country-3.8.3/tests/hdx/location/test_wfp_exchangerates.py +66 -0
- hdx_python_country-3.8.2/src/hdx/location/wfp_exchangerates.py +0 -101
- hdx_python_country-3.8.2/tests/hdx/location/test_wfp_exchangerates.py +0 -42
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/.config/coveragerc +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/.config/pytest.ini +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/.config/ruff.toml +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/.github/workflows/publish.yaml +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/.github/workflows/run-python-tests.yaml +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/.gitignore +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/CONTRIBUTING.md +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/LICENSE +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/README.md +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/documentation/.readthedocs.yaml +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/documentation/main.md +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/documentation/pydoc-markdown.yaml +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/src/hdx/location/Countries & Territories Taxonomy MVP - C&T Taxonomy with HXL Tags.csv +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/src/hdx/location/__init__.py +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/src/hdx/location/adminlevel.py +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/src/hdx/location/country.py +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/src/hdx/location/currency.py +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/src/hdx/location/phonetics.py +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/fixtures/adminlevel.yaml +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/fixtures/adminlevelparent.yaml +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/fixtures/download-global-pcode-lengths.csv +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/fixtures/download-global-pcodes-adm-1-2.csv +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/fixtures/secondary_historic_rates.csv +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/fixtures/secondary_rates.json +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/hdx/location/Countries_UZB_Deleted.csv +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/hdx/location/__init__.py +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/hdx/location/test_adminlevel.py +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/hdx/location/test_country.py +0 -0
- {hdx_python_country-3.8.2 → hdx_python_country-3.8.3}/tests/hdx/location/test_currency.py +0 -0
|
@@ -2,13 +2,13 @@ default_language_version:
|
|
|
2
2
|
python: python3.12
|
|
3
3
|
repos:
|
|
4
4
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
5
|
-
rev:
|
|
5
|
+
rev: v5.0.0
|
|
6
6
|
hooks:
|
|
7
7
|
- id: trailing-whitespace
|
|
8
8
|
- id: end-of-file-fixer
|
|
9
9
|
- id: check-ast
|
|
10
10
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
11
|
-
rev: v0.
|
|
11
|
+
rev: v0.7.0
|
|
12
12
|
hooks:
|
|
13
13
|
# Run the linter.
|
|
14
14
|
- id: ruff
|
|
@@ -17,7 +17,7 @@ repos:
|
|
|
17
17
|
- id: ruff-format
|
|
18
18
|
args: [--config, .config/ruff.toml]
|
|
19
19
|
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
20
|
-
rev: 0.4.
|
|
20
|
+
rev: 0.4.24
|
|
21
21
|
hooks:
|
|
22
22
|
# Run the pip compile
|
|
23
23
|
- id: pip-compile
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: hdx-python-country
|
|
3
|
-
Version: 3.8.
|
|
3
|
+
Version: 3.8.3
|
|
4
4
|
Summary: HDX Python country code and exchange rate (fx) utilities
|
|
5
5
|
Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-country
|
|
6
6
|
Author: Michael Rans
|
|
@@ -26,8 +26,9 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
26
26
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
27
|
Requires-Python: >=3.8
|
|
28
28
|
Requires-Dist: hdx-python-utilities>=3.7.4
|
|
29
|
-
Requires-Dist: libhxl>=5.2.
|
|
29
|
+
Requires-Dist: libhxl>=5.2.2
|
|
30
30
|
Requires-Dist: pyphonetics
|
|
31
|
+
Requires-Dist: tenacity
|
|
31
32
|
Provides-Extra: dev
|
|
32
33
|
Requires-Dist: pre-commit; extra == 'dev'
|
|
33
34
|
Provides-Extra: test
|
|
@@ -35,8 +35,9 @@ requires-python = ">=3.8"
|
|
|
35
35
|
|
|
36
36
|
dependencies = [
|
|
37
37
|
"hdx-python-utilities>=3.7.4",
|
|
38
|
-
"libhxl>=5.2.
|
|
38
|
+
"libhxl>=5.2.2",
|
|
39
39
|
"pyphonetics",
|
|
40
|
+
"tenacity",
|
|
40
41
|
]
|
|
41
42
|
dynamic = ["version"]
|
|
42
43
|
|
|
@@ -50,16 +51,12 @@ Homepage = "https://github.com/OCHA-DAP/hdx-python-country"
|
|
|
50
51
|
[project.optional-dependencies]
|
|
51
52
|
test = ["pytest", "pytest-cov"]
|
|
52
53
|
dev = ["pre-commit"]
|
|
53
|
-
#wfp = ["data-bridges-client@git+https://github.com/WFP-VAM/DataBridgesAPI@dev#egg=data-bridges-client"]
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
#########
|
|
57
57
|
# Hatch #
|
|
58
58
|
#########
|
|
59
59
|
|
|
60
|
-
#[tool.hatch.metadata]
|
|
61
|
-
#allow-direct-references = true
|
|
62
|
-
|
|
63
60
|
# Build
|
|
64
61
|
|
|
65
62
|
[tool.hatch.build.targets.wheel]
|
|
@@ -92,6 +89,9 @@ run = """
|
|
|
92
89
|
--cov-report=lcov --cov-report=term-missing
|
|
93
90
|
"""
|
|
94
91
|
|
|
92
|
+
[tool.hatch.envs.hatch-static-analysis]
|
|
93
|
+
dependencies = ["ruff==0.7.0"]
|
|
94
|
+
|
|
95
95
|
[tool.hatch.envs.hatch-static-analysis.scripts]
|
|
96
96
|
format-check = ["ruff format --config .config/ruff.toml --check --diff {args:.}",]
|
|
97
97
|
format-fix = ["ruff format --config .config/ruff.toml {args:.}",]
|
|
@@ -18,11 +18,11 @@ charset-normalizer==3.4.0
|
|
|
18
18
|
# via requests
|
|
19
19
|
click==8.1.7
|
|
20
20
|
# via typer
|
|
21
|
-
coverage==7.6.
|
|
21
|
+
coverage==7.6.4
|
|
22
22
|
# via pytest-cov
|
|
23
23
|
distlib==0.3.9
|
|
24
24
|
# via virtualenv
|
|
25
|
-
et-xmlfile==
|
|
25
|
+
et-xmlfile==2.0.0
|
|
26
26
|
# via openpyxl
|
|
27
27
|
filelock==3.16.1
|
|
28
28
|
# via virtualenv
|
|
@@ -54,7 +54,7 @@ jsonschema==4.23.0
|
|
|
54
54
|
# tableschema-to-template
|
|
55
55
|
jsonschema-specifications==2024.10.1
|
|
56
56
|
# via jsonschema
|
|
57
|
-
libhxl==5.2.
|
|
57
|
+
libhxl==5.2.2
|
|
58
58
|
# via hdx-python-country (pyproject.toml)
|
|
59
59
|
loguru==0.7.2
|
|
60
60
|
# via hdx-python-utilities
|
|
@@ -62,7 +62,7 @@ markdown-it-py==3.0.0
|
|
|
62
62
|
# via rich
|
|
63
63
|
marko==2.1.2
|
|
64
64
|
# via frictionless
|
|
65
|
-
markupsafe==3.0.
|
|
65
|
+
markupsafe==3.0.2
|
|
66
66
|
# via jinja2
|
|
67
67
|
mdurl==0.1.2
|
|
68
68
|
# via markdown-it-py
|
|
@@ -74,6 +74,8 @@ packaging==24.1
|
|
|
74
74
|
# via pytest
|
|
75
75
|
petl==1.7.15
|
|
76
76
|
# via frictionless
|
|
77
|
+
pip==24.3.1
|
|
78
|
+
# via simpleeval
|
|
77
79
|
platformdirs==4.3.6
|
|
78
80
|
# via virtualenv
|
|
79
81
|
pluggy==1.5.0
|
|
@@ -96,7 +98,7 @@ pytest==8.3.3
|
|
|
96
98
|
# via
|
|
97
99
|
# hdx-python-country (pyproject.toml)
|
|
98
100
|
# pytest-cov
|
|
99
|
-
pytest-cov==
|
|
101
|
+
pytest-cov==6.0.0
|
|
100
102
|
# via hdx-python-country (pyproject.toml)
|
|
101
103
|
python-dateutil==2.9.0.post0
|
|
102
104
|
# via
|
|
@@ -127,7 +129,7 @@ requests-file==2.1.0
|
|
|
127
129
|
# via hdx-python-utilities
|
|
128
130
|
rfc3986==2.0.0
|
|
129
131
|
# via frictionless
|
|
130
|
-
rich==13.9.
|
|
132
|
+
rich==13.9.3
|
|
131
133
|
# via typer
|
|
132
134
|
rpds-py==0.20.0
|
|
133
135
|
# via
|
|
@@ -135,11 +137,11 @@ rpds-py==0.20.0
|
|
|
135
137
|
# referencing
|
|
136
138
|
ruamel-yaml==0.18.6
|
|
137
139
|
# via hdx-python-utilities
|
|
138
|
-
ruamel-yaml-clib==0.2.
|
|
140
|
+
ruamel-yaml-clib==0.2.12
|
|
139
141
|
# via ruamel-yaml
|
|
140
142
|
shellingham==1.5.4
|
|
141
143
|
# via typer
|
|
142
|
-
simpleeval==1.0.
|
|
144
|
+
simpleeval==1.0.1
|
|
143
145
|
# via frictionless
|
|
144
146
|
six==1.16.0
|
|
145
147
|
# via python-dateutil
|
|
@@ -151,6 +153,8 @@ tableschema-to-template==0.0.13
|
|
|
151
153
|
# via hdx-python-utilities
|
|
152
154
|
tabulate==0.9.0
|
|
153
155
|
# via frictionless
|
|
156
|
+
tenacity==9.0.0
|
|
157
|
+
# via hdx-python-country (pyproject.toml)
|
|
154
158
|
text-unidecode==1.3
|
|
155
159
|
# via python-slugify
|
|
156
160
|
typer==0.12.5
|
|
@@ -171,7 +175,7 @@ urllib3==2.2.3
|
|
|
171
175
|
# requests
|
|
172
176
|
validators==0.34.0
|
|
173
177
|
# via frictionless
|
|
174
|
-
virtualenv==20.
|
|
178
|
+
virtualenv==20.27.1
|
|
175
179
|
# via pre-commit
|
|
176
180
|
wheel==0.44.0
|
|
177
181
|
# via libhxl
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
from tenacity import (
|
|
5
|
+
Retrying,
|
|
6
|
+
after_log,
|
|
7
|
+
retry_if_exception_type,
|
|
8
|
+
stop_after_attempt,
|
|
9
|
+
wait_fixed,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from hdx.utilities.base_downloader import DownloadError
|
|
13
|
+
from hdx.utilities.downloader import Download
|
|
14
|
+
from hdx.utilities.retriever import Retrieve
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class WFPAPI:
|
|
20
|
+
"""Light wrapper around WFP REST API. It needs a token_downloader that has
|
|
21
|
+
been configured with WFP basic authentication credentials and a retriever
|
|
22
|
+
that will configured by this class with the bearer token obtained from the
|
|
23
|
+
token_downloader.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
token_downloader (Download): Download object with WFP basic authentication
|
|
27
|
+
retriever (Retrieve): Retrieve object for interacting with WFP API
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
token_url = "https://api.wfp.org/token"
|
|
31
|
+
base_url = "https://api.wfp.org/vam-data-bridges/5.0.0/"
|
|
32
|
+
scope = "vamdatabridges_commodities-list_get vamdatabridges_commodityunits-list_get vamdatabridges_marketprices-alps_get vamdatabridges_commodities-categories-list_get vamdatabridges_commodityunits-conversion-list_get vamdatabridges_marketprices-priceweekly_get vamdatabridges_markets-geojsonlist_get vamdatabridges_marketprices-pricemonthly_get vamdatabridges_markets-list_get vamdatabridges_currency-list_get vamdatabridges_currency-usdindirectquotation_get"
|
|
33
|
+
default_retry_params = {
|
|
34
|
+
"retry": retry_if_exception_type(DownloadError),
|
|
35
|
+
"after": after_log(logger, logging.INFO),
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
token_downloader: Download,
|
|
41
|
+
retriever: Retrieve,
|
|
42
|
+
):
|
|
43
|
+
self.token_downloader = token_downloader
|
|
44
|
+
self.retriever = retriever
|
|
45
|
+
self.retry_params = {"attempts": 1, "wait": 1}
|
|
46
|
+
|
|
47
|
+
def get_retry_params(self) -> Dict:
|
|
48
|
+
return self.retry_params
|
|
49
|
+
|
|
50
|
+
def update_retry_params(self, attempts: int, wait: int) -> Dict:
|
|
51
|
+
self.retry_params["attempts"] = attempts
|
|
52
|
+
self.retry_params["wait"] = wait
|
|
53
|
+
return self.retry_params
|
|
54
|
+
|
|
55
|
+
def refresh_token(self) -> None:
|
|
56
|
+
self.token_downloader.download(
|
|
57
|
+
self.token_url,
|
|
58
|
+
post=True,
|
|
59
|
+
parameters={
|
|
60
|
+
"grant_type": "client_credentials",
|
|
61
|
+
"scope": self.scope,
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
bearer_token = self.token_downloader.get_json()["access_token"]
|
|
65
|
+
self.retriever.downloader.set_bearer_token(bearer_token)
|
|
66
|
+
|
|
67
|
+
def retrieve(
|
|
68
|
+
self,
|
|
69
|
+
url: str,
|
|
70
|
+
filename: str,
|
|
71
|
+
log: str,
|
|
72
|
+
parameters: Optional[Dict] = None,
|
|
73
|
+
) -> Any:
|
|
74
|
+
"""Retrieve JSON from WFP API.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
url (str): URL to download
|
|
78
|
+
filename (Optional[str]): Filename of saved file. Defaults to getting from url.
|
|
79
|
+
log (Optional[str]): Text to use in log string to describe download. Defaults to filename.
|
|
80
|
+
parameters (Dict): Parameters to pass to download_json call
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Any: The data from the JSON file
|
|
84
|
+
"""
|
|
85
|
+
retryer = Retrying(
|
|
86
|
+
retry=self.default_retry_params["retry"],
|
|
87
|
+
after=self.default_retry_params["after"],
|
|
88
|
+
stop=stop_after_attempt(self.retry_params["attempts"]),
|
|
89
|
+
wait=wait_fixed(self.retry_params["wait"]),
|
|
90
|
+
)
|
|
91
|
+
for attempt in retryer:
|
|
92
|
+
with attempt:
|
|
93
|
+
try:
|
|
94
|
+
results = self.retriever.download_json(
|
|
95
|
+
url, filename, log, False, parameters=parameters
|
|
96
|
+
)
|
|
97
|
+
except DownloadError:
|
|
98
|
+
response = self.retriever.downloader.response
|
|
99
|
+
if response and response.status_code not in (
|
|
100
|
+
104,
|
|
101
|
+
401,
|
|
102
|
+
403,
|
|
103
|
+
):
|
|
104
|
+
raise
|
|
105
|
+
self.refresh_token()
|
|
106
|
+
results = self.retriever.download_json(
|
|
107
|
+
url, filename, log, False, parameters=parameters
|
|
108
|
+
)
|
|
109
|
+
return results
|
|
110
|
+
|
|
111
|
+
def get_items(
|
|
112
|
+
self,
|
|
113
|
+
endpoint: str,
|
|
114
|
+
countryiso3: Optional[str] = None,
|
|
115
|
+
parameters: Optional[Dict] = None,
|
|
116
|
+
) -> List:
|
|
117
|
+
"""Retrieve a list of items from the WFP API.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
endpoint (str): End point to call
|
|
121
|
+
countryiso3 (Optional[str]): Country for which to obtain data. Defaults to all countries.
|
|
122
|
+
parameters (Optional[Dict]): Paramaters to pass to call. Defaults to None.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
List: List of items from the WFP endpoint
|
|
126
|
+
"""
|
|
127
|
+
if not parameters:
|
|
128
|
+
parameters = {}
|
|
129
|
+
all_data = []
|
|
130
|
+
url = f"{self.base_url}{endpoint}"
|
|
131
|
+
url_parts = url.split("/")
|
|
132
|
+
base_filename = f"{url_parts[-2]}_{url_parts[-1]}"
|
|
133
|
+
if countryiso3 == "PSE": # hack as PSE is treated by WFP as 2 areas
|
|
134
|
+
countryiso3s = ["PSW", "PSG"]
|
|
135
|
+
else:
|
|
136
|
+
countryiso3s = [countryiso3]
|
|
137
|
+
for countryiso3 in countryiso3s:
|
|
138
|
+
page = 1
|
|
139
|
+
data = None
|
|
140
|
+
while data is None or len(data) > 0:
|
|
141
|
+
page_parameters = {"page": page}
|
|
142
|
+
page_parameters.update(parameters)
|
|
143
|
+
if countryiso3 is None:
|
|
144
|
+
filename = f"{base_filename}_{page}.json"
|
|
145
|
+
log = f"{base_filename} page {page}"
|
|
146
|
+
else:
|
|
147
|
+
filename = f"{base_filename}_{countryiso3}_{page}.json"
|
|
148
|
+
log = f"{base_filename} for {countryiso3} page {page}"
|
|
149
|
+
page_parameters["CountryCode"] = countryiso3
|
|
150
|
+
try:
|
|
151
|
+
json = self.retrieve(url, filename, log, page_parameters)
|
|
152
|
+
except FileNotFoundError:
|
|
153
|
+
json = {"items": []}
|
|
154
|
+
data = json["items"]
|
|
155
|
+
all_data.extend(data)
|
|
156
|
+
page = page + 1
|
|
157
|
+
return all_data
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Dict, List
|
|
3
|
+
|
|
4
|
+
from . import get_int_timestamp
|
|
5
|
+
from .wfp_api import WFPAPI
|
|
6
|
+
from hdx.utilities.dateparse import parse_date
|
|
7
|
+
from hdx.utilities.typehint import ListTuple
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WFPExchangeRates:
|
|
13
|
+
"""Obtain WFP official exchange rates. It needs a WFP API object.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
wfp_api (WFPAPI): WFPAPI object
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, wfp_api: WFPAPI):
|
|
20
|
+
self.wfp_api = wfp_api
|
|
21
|
+
|
|
22
|
+
def get_currencies(self) -> List[str]:
|
|
23
|
+
"""Get list of currencies in WFP API
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
List[str]: List of currencies in WFP API
|
|
27
|
+
"""
|
|
28
|
+
currencies = []
|
|
29
|
+
for currency in self.wfp_api.get_items("Currency/List"):
|
|
30
|
+
currencies.append(currency["name"])
|
|
31
|
+
return currencies
|
|
32
|
+
|
|
33
|
+
def get_currency_historic_rates(self, currency: str) -> Dict[int, float]:
|
|
34
|
+
"""Get historic rates for currency from WFP API
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
currency (str): Currency
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Dict[int, float]: Mapping from timestamp to rate
|
|
41
|
+
"""
|
|
42
|
+
quotes = self.wfp_api.get_items(
|
|
43
|
+
"Currency/UsdIndirectQuotation",
|
|
44
|
+
parameters={"currencyName": currency},
|
|
45
|
+
)
|
|
46
|
+
historic_rates = {}
|
|
47
|
+
for quote in quotes:
|
|
48
|
+
if not quote["isOfficial"]:
|
|
49
|
+
continue
|
|
50
|
+
date = parse_date(quote["date"])
|
|
51
|
+
timestamp = get_int_timestamp(date)
|
|
52
|
+
historic_rates[timestamp] = quote["value"]
|
|
53
|
+
return historic_rates
|
|
54
|
+
|
|
55
|
+
def get_historic_rates(
|
|
56
|
+
self, currencies: ListTuple[str]
|
|
57
|
+
) -> Dict[str, Dict]:
|
|
58
|
+
"""Get historic rates for a list of currencies from WFP API
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
currencies (List[str]): List of currencies
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Dict[str, Dict]: Mapping from currency to mapping from timestamp to rate
|
|
65
|
+
"""
|
|
66
|
+
historic_rates = {}
|
|
67
|
+
for currency in currencies:
|
|
68
|
+
logger.info(f"Getting WFP historic rates for {currency}")
|
|
69
|
+
currency_historic_rates = self.get_currency_historic_rates(
|
|
70
|
+
currency
|
|
71
|
+
)
|
|
72
|
+
historic_rates[currency.upper()] = currency_historic_rates
|
|
73
|
+
return historic_rates
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"items": [{"createDate": "2021-08-02T18:24:29.657", "extendedName": "United Arab Emirates Dirham", "id": 131, "name": "AED", "updateDate": "2023-10-05T16:05:48.223"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Afghan Afghani", "id": 87, "name": "AFN", "updateDate": "2023-10-05T16:06:06.557"}, {"createDate": "2021-08-02T18:22:53.87", "extendedName": "Albanian Lek", "id": 130, "name": "ALL", "updateDate": "2023-10-05T16:06:11.963"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Armenian Dram", "id": 37, "name": "AMD", "updateDate": "2023-10-05T16:06:16.883"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Angolan Kwanza", "id": 96, "name": "AOA", "updateDate": "2023-10-05T15:07:06.5"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Argentine Peso", "id": 106, "name": "ARS", "updateDate": "2023-10-05T16:06:22.83"}, {"createDate": "2021-08-02T18:28:54.6", "extendedName": "Australian Dollar", "id": 133, "name": "AUD", "updateDate": "2023-10-05T16:06:28.503"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Azerbaijani Manat", "id": 36, "name": "AZN", "updateDate": "2023-10-05T16:06:33.617"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Bangladeshi Taka", "id": 25, "name": "BDT", "updateDate": "2023-10-05T16:06:39.94"}, {"createDate": "2021-08-02T18:27:55.72", "extendedName": "Bulgarian Lev", "id": 132, "name": "BGN", "updateDate": "2023-10-05T16:06:45.027"}, {"createDate": "2021-10-04T18:28:31.65", "extendedName": "Bahraini Dinar", "id": 138, "name": "BHD", "updateDate": "2023-10-05T16:06:52.357"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Burundian Franc", "id": 32, "name": "BIF", "updateDate": "2023-10-05T16:05:30.807"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Boliviano", "id": 46, "name": "BOB", "updateDate": "2023-10-05T16:07:16.897"}, {"createDate": "2024-01-19T10:08:31.157", "extendedName": "Brazilian Real", "id": 159, "name": "BRL", "updateDate": null}, {"createDate": "2021-11-16T13:56:25.917", "extendedName": "Bahamian Dollar", "id": 144, "name": "BSD", "updateDate": "2023-10-05T16:09:05.437"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Bhutanese Ngultrum", "id": 76, "name": "BTN", "updateDate": "2023-10-05T16:07:41.03"}, {"createDate": "2022-09-09T08:56:59.297", "extendedName": "Botswana Pula", "id": 148, "name": "BWP", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Belarusian Ruble", "id": 107, "name": "BYR", "updateDate": "2023-10-05T16:08:22.667"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Congolese Franc", "id": 27, "name": "CDF", "updateDate": "2023-10-05T16:08:43.547"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Chilean Peso", "id": 108, "name": "CLP", "updateDate": "2023-10-05T16:08:58.83"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Renminbi", "id": 109, "name": "CNY", "updateDate": "2023-10-05T16:09:23.17"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Colombian Peso", "id": 67, "name": "COP", "updateDate": "2023-10-05T16:09:51.277"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Costa Rican Colon", "id": 92, "name": "CRC", "updateDate": "2023-10-05T16:10:04.74"}, {"createDate": "2021-08-02T19:18:01.077", "extendedName": "Cuban Convertible Pesos", "id": 134, "name": "CUC", "updateDate": "2023-10-05T16:10:15.51"}, {"createDate": "2021-07-23T10:23:48.907", "extendedName": "Cuban Peso", "id": 127, "name": "CUP", "updateDate": "2021-07-23T10:24:03.74"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Cape Verdean Escudo", "id": 57, "name": "CVE", "updateDate": "2023-10-05T16:10:33.13"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Djiboutian Franc", "id": 59, "name": "DJF", "updateDate": "2023-10-05T16:10:45.763"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Dominican Peso", "id": 85, "name": "DOP", "updateDate": "2023-10-05T16:11:12.62"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Algerian Dinar", "id": 91, "name": "DZD", "updateDate": "2023-10-05T16:11:26.253"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Egyptian Pound", "id": 38, "name": "EGP", "updateDate": "2023-10-05T16:11:39.353"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Eritrean Nakfa", "id": 110, "name": "ERN", "updateDate": "2023-10-05T16:11:53.783"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Ethiopian Birr", "id": 47, "name": "ETB", "updateDate": "2023-10-05T16:12:07.26"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Euro", "id": 111, "name": "EUR", "updateDate": "2023-10-05T16:12:17.437"}, {"createDate": "2021-11-16T13:59:56.407", "extendedName": "Fijian dollar", "id": 146, "name": "FJD", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Georgian Lari", "id": 50, "name": "GEL", "updateDate": "2023-10-05T16:12:32.133"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Ghanaian Cedi", "id": 35, "name": "GHS", "updateDate": "2023-10-05T16:12:51.58"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Gambian Dalasi", "id": 42, "name": "GMD", "updateDate": "2023-10-05T16:13:02.697"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Guinean Franc", "id": 54, "name": "GNF", "updateDate": "2023-10-05T16:13:27.12"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Guatemalan Quetzal", "id": 82, "name": "GTQ", "updateDate": "2023-10-05T16:13:42.487"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Honduran Lempira", "id": 112, "name": "HNL", "updateDate": "2023-10-05T16:14:02.63"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Haitian Gourde", "id": 24, "name": "HTG", "updateDate": "2023-10-05T16:16:54.453"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Indonesian Rupiah", "id": 34, "name": "IDR", "updateDate": "2023-10-05T16:51:09.01"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "New Israeli Shekel", "id": 73, "name": "ILS", "updateDate": "2021-09-20T17:55:14.71"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Indian Rupee", "id": 68, "name": "INR", "updateDate": "2023-10-05T16:51:24.84"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Iraqi Dinar", "id": 84, "name": "IQD", "updateDate": "2023-10-05T16:51:42.25"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Iranian Rial", "id": 89, "name": "IRR", "updateDate": "2023-10-05T16:52:01.813"}, {"createDate": "2021-11-16T13:50:01.28", "extendedName": "Jamaican Dollar", "id": 139, "name": "JMD", "updateDate": "2021-11-16T13:51:47.597"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Jordanian Dinar", "id": 58, "name": "JOD", "updateDate": "2023-10-05T16:52:13.29"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Japanese Yen", "id": 113, "name": "JPY", "updateDate": "2023-10-05T16:52:25.02"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Kenyan Shilling", "id": 30, "name": "KES", "updateDate": "2023-10-05T17:20:23.877"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Kyrgyzstani Som", "id": 61, "name": "KGS", "updateDate": "2023-10-05T17:20:37.52"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Cambodian Riel", "id": 60, "name": "KHR", "updateDate": "2023-10-05T17:20:54.753"}, {"createDate": "2022-09-09T08:58:07.763", "extendedName": "Comorian Franc", "id": 149, "name": "KMF", "updateDate": null}, {"createDate": "2021-11-16T13:53:56.17", "extendedName": "North Korean Won", "id": 141, "name": "KPW", "updateDate": null}, {"createDate": "2021-11-16T13:57:58.577", "extendedName": "Cayman Islands Dollar", "id": 145, "name": "KYD", "updateDate": "2023-10-05T17:21:02.627"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Kazakhstani Tenge", "id": 99, "name": "KZT", "updateDate": "2023-10-05T17:21:22.537"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Lao Kip", "id": 63, "name": "LAK", "updateDate": "2023-10-05T17:21:33.213"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Lebanese Pound", "id": 90, "name": "LBP", "updateDate": "2023-10-05T17:21:44.72"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Sri Lankan Rupee", "id": 55, "name": "LKR", "updateDate": "2023-10-05T17:21:55.583"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Liberian Dollar", "id": 40, "name": "LRD", "updateDate": "2023-10-05T17:22:08.767"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Lesotho Loti", "id": 56, "name": "LSL", "updateDate": "2023-10-05T17:22:20.387"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Libyan Dinar", "id": 97, "name": "LYD", "updateDate": "2023-10-05T17:22:34.527"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Moroccan Dirham", "id": 101, "name": "MAD", "updateDate": "2023-10-05T17:22:45.337"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Moldovan Leu", "id": 100, "name": "MDL", "updateDate": "2023-10-05T17:22:56.143"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Malagasy Ariary", "id": 65, "name": "MGA", "updateDate": "2023-10-05T17:23:11.417"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Myanmar Kyat", "id": 74, "name": "MMK", "updateDate": "2023-10-05T17:23:21.75"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Mongolian T\u00f6gr\u00f6g", "id": 114, "name": "MNT", "updateDate": "2023-10-05T17:23:37.12"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Mauritanian Ouguiya", "id": 64, "name": "MRO", "updateDate": "2023-10-05T17:23:52.63"}, {"createDate": "2022-05-18T14:54:28.977", "extendedName": "Ouguiya", "id": 147, "name": "MRU", "updateDate": "2022-05-20T14:29:42.43"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Malawian Kwacha", "id": 66, "name": "MWK", "updateDate": "2023-10-05T17:24:11.41"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Mexican Peso", "id": 115, "name": "MXN", "updateDate": "2023-10-05T17:24:27.67"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Mozambican Metical", "id": 51, "name": "MZN", "updateDate": "2023-10-06T13:09:29"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Namibian Dollar", "id": 116, "name": "NAD", "updateDate": "2023-10-06T13:09:36.943"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Nigerian Naira", "id": 95, "name": "NGN", "updateDate": "2023-10-06T13:09:47.943"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Nicaraguan C\u00f3rdoba", "id": 86, "name": "NIO", "updateDate": "2023-10-06T13:10:00.62"}, {"createDate": "2023-10-06T13:10:24.21", "extendedName": "Norwegian krone", "id": 152, "name": "NOK", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Nepalese Rupee", "id": 62, "name": "NPR", "updateDate": "2023-10-06T13:10:37.26"}, {"createDate": "2023-10-06T13:11:01.767", "extendedName": "New Zealand Dollar", "id": 153, "name": "NZD", "updateDate": null}, {"createDate": "2023-10-06T13:11:20.807", "extendedName": "Omani Rial", "id": 154, "name": "OMR", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Panamanian Balboa", "id": 117, "name": "PAB", "updateDate": "2023-10-06T13:11:45.267"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Peruvian Sol", "id": 33, "name": "PEN", "updateDate": "2023-10-06T13:11:54.71"}, {"createDate": "2021-11-16T13:51:13.607", "extendedName": "Papua New Guinean Kina", "id": 140, "name": "PGK", "updateDate": "2021-11-16T13:51:20.977"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Philippine Peso", "id": 29, "name": "PHP", "updateDate": "2023-10-06T13:12:31.657"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Pakistani Rupee", "id": 45, "name": "PKR", "updateDate": "2023-10-06T13:12:45.58"}, {"createDate": "2023-10-06T13:12:59.437", "extendedName": "Polish z\u0142oty", "id": 155, "name": "PLN", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Paraguayan Guaran\u00ed", "id": 118, "name": "PYG", "updateDate": "2023-10-06T13:13:08.133"}, {"createDate": "2023-10-06T13:14:01.817", "extendedName": "Romanian Leu", "id": 156, "name": "RON", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Russian Ruble", "id": 102, "name": "RUB", "updateDate": "2023-10-06T13:13:29.22"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Rwandan Franc", "id": 77, "name": "RWF", "updateDate": "2023-10-06T13:14:15.373"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Saudi Riyal", "id": 103, "name": "SAR", "updateDate": "2023-10-06T13:14:24.197"}, {"createDate": "2022-09-09T10:23:48.027", "extendedName": "Solomon Islands Dollar", "id": 150, "name": "SBD", "updateDate": "2023-10-06T13:14:30.883"}, {"createDate": "2023-10-06T13:14:55.84", "extendedName": "Seychelles Rupee", "id": 157, "name": "SCR", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Sudanese Pound", "id": 75, "name": "SDG", "updateDate": "2023-10-06T13:15:03.55"}, {"createDate": "2023-10-06T13:15:21.86", "extendedName": "Swedish Krona ", "id": 158, "name": "SEK", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Sierra Leonean Leone ", "id": 53, "name": "SLL", "updateDate": "2023-10-06T13:15:44.363"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Somaliland Shilling", "id": 81, "name": "SLS", "updateDate": "2020-05-13T19:08:07.153"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Somali Shilling", "id": 79, "name": "SOS", "updateDate": "2023-10-06T13:15:54.223"}, {"createDate": "2021-09-03T16:47:19.25", "extendedName": "Surinamese dollar", "id": 137, "name": "SRD", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "South Sudanese Pound", "id": 83, "name": "SSP", "updateDate": "2023-10-06T13:16:09.307"}, {"createDate": "2021-11-16T13:54:49.843", "extendedName": "S\u00e3o Tom\u00e9 and Pr\u00edncipe Dobra", "id": 142, "name": "STN", "updateDate": "2022-02-04T18:49:22.997"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Syrian Pound", "id": 78, "name": "SYP", "updateDate": "2023-10-06T13:16:20.727"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Swazi Lilangeni", "id": 23, "name": "SZL", "updateDate": "2023-10-06T13:16:32.907"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Thai Baht", "id": 119, "name": "THB", "updateDate": "2023-10-06T13:16:43.66"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Tajikistani Somoni", "id": 49, "name": "TJS", "updateDate": "2023-10-06T13:16:53.313"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Turkmenistan Manat", "id": 105, "name": "TMT", "updateDate": "2023-10-06T13:17:03.19"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Tunisian Dinar", "id": 104, "name": "TND", "updateDate": "2023-10-06T13:17:16.303"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Turkish Lira", "id": 88, "name": "TRY", "updateDate": "2023-10-06T13:17:27.8"}, {"createDate": "2021-11-16T13:55:49.043", "extendedName": "Trinidad and Tobago dollar", "id": 143, "name": "TTD", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Tanzanian Shilling", "id": 22, "name": "TZS", "updateDate": "2023-10-06T13:17:41.38"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Ukrainian Hryvnia", "id": 93, "name": "UAH", "updateDate": "2023-10-06T13:17:49.587"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Ugandan Shilling", "id": 39, "name": "UGX", "updateDate": "2023-10-06T13:18:00.927"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "United States Dollar", "id": 28, "name": "USD", "updateDate": "2023-10-06T13:18:14.463"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Uruguayan Peso", "id": 120, "name": "UYU", "updateDate": "2022-02-04T19:02:54.16"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Uzbekistan Sum", "id": 121, "name": "UZS", "updateDate": "2023-10-06T13:18:39.537"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": null, "id": 98, "name": "VEF", "updateDate": null}, {"createDate": "2021-08-27T15:20:05.343", "extendedName": "Venezuelan Bolivar", "id": 135, "name": "VES", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Vietnamese Dong", "id": 122, "name": "VND", "updateDate": "2023-10-06T13:19:04.453"}, {"createDate": "2022-09-09T10:27:13.38", "extendedName": "Vanuatu Vatu", "id": 151, "name": "VUV", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Samoan Tala", "id": 123, "name": "WST", "updateDate": "2023-10-06T13:19:15.853"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "CFA franc BEAC", "id": 48, "name": "XAF", "updateDate": "2023-10-06T13:19:28.203"}, {"createDate": "2021-08-02T18:17:10.363", "extendedName": "East Caribbean dollar", "id": 129, "name": "XCD", "updateDate": null}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "CFA franc BCEAO", "id": 26, "name": "XOF", "updateDate": "2023-10-06T13:19:46.72"}, {"createDate": "2020-04-22T22:02:26.937", "extendedName": "Yemeni Rial", "id": 31, "name": "YER", "updateDate": "2023-10-06T13:19:55.923"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "South African Rand", "id": 124, "name": "ZAR", "updateDate": "2023-10-06T13:20:04.47"}, {"createDate": "2024-05-10T16:34:21.023", "extendedName": "Zimbabwe Gold", "id": 160, "name": "ZiG", "updateDate": "2024-05-16T20:03:21.057"}, {"createDate": "2020-04-22T22:02:26.94", "extendedName": "Zambian Kwacha", "id": 94, "name": "ZMW", "updateDate": "2022-09-09T10:19:57.007"}, {"createDate": "2020-04-22T22:02:26.943", "extendedName": "Zimbabwean Dollar", "id": 125, "name": "ZWL", "updateDate": "2024-05-10T16:34:31.017"}], "page": 1, "totalItems": 127}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"items": [], "page": 2, "totalItems": 127}
|