mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-03 07:51:49 +00:00
* merge branch develop with main * bump desktop version * fix the merge * sync Cargo.lock to desktop 2.0.0 * fix cli conftest.py --------- Co-authored-by: deeleeramone <>
207 lines
6.4 KiB
Python
207 lines
6.4 KiB
Python
from openbb_ecb.utils.helpers import (
|
|
parse_sdmx_csv,
|
|
parse_sdmx_json,
|
|
parse_sdmx_period,
|
|
parse_series_keys,
|
|
period_end,
|
|
)
|
|
|
|
|
|
def test_parse_sdmx_csv():
|
|
text = (
|
|
"KEY,FREQ,OBS_VALUE,TIME_PERIOD,EXTRA\n"
|
|
"EXR.D.USD,D,1.5,2024-01-01,\n"
|
|
"OTHER,M,,2024-02,keep\n"
|
|
"ZZZ.A.B,A,bad,2024,x\n"
|
|
)
|
|
rows = parse_sdmx_csv(text, "EXR")
|
|
assert rows[0]["series_key"] == "D.USD"
|
|
assert rows[0]["FREQ"] == "D" and rows[0]["OBS_VALUE"] == 1.5
|
|
assert "EXTRA" not in rows[0] and "KEY" not in rows[0]
|
|
assert rows[0]["date"] == "2024-01-01"
|
|
assert rows[1]["series_key"] == "OTHER" and rows[1]["OBS_VALUE"] is None
|
|
assert rows[1]["EXTRA"] == "keep"
|
|
assert rows[2]["series_key"] == "ZZZ.A.B" and rows[2]["OBS_VALUE"] is None
|
|
|
|
|
|
def test_parse_sdmx_period_all_formats():
|
|
assert parse_sdmx_period("2024-06-23") == "2024-06-23"
|
|
assert parse_sdmx_period("2024-06") == "2024-06-01"
|
|
assert parse_sdmx_period("2024-Q2") == "2024-04-01"
|
|
assert parse_sdmx_period("2024-S1") == "2024-01-01"
|
|
assert parse_sdmx_period("2024-S2") == "2024-07-01"
|
|
assert parse_sdmx_period("2024-W23") == "2024-06-03"
|
|
assert parse_sdmx_period("2024") == "2024-01-01"
|
|
assert (
|
|
parse_sdmx_period("2024-06", start="2024-06-30T00:00:00+02:00") == "2024-06-30"
|
|
)
|
|
|
|
|
|
def test_parse_sdmx_period_fallbacks():
|
|
assert parse_sdmx_period("") == ""
|
|
assert parse_sdmx_period("garbage-Q9") == "garbage-Q9"
|
|
|
|
|
|
def test_period_end_all_formats():
|
|
assert period_end("2024-Q3") == "2024-09-30"
|
|
assert period_end("2024-02") == "2024-02-29"
|
|
assert period_end("2023") == "2023-12-31"
|
|
assert period_end("2024-06-15", end="2024-06-30T00:00:00") == "2024-06-30"
|
|
|
|
|
|
def test_period_end_fallbacks():
|
|
assert period_end("") == ""
|
|
assert period_end("2024-W10") == parse_sdmx_period("2024-W10")
|
|
assert period_end("bad-Q9") == "bad-Q9"
|
|
|
|
|
|
def test_parse_sdmx_json_empty():
|
|
assert parse_sdmx_json({}) == []
|
|
assert parse_sdmx_json({"dataSets": []}) == []
|
|
|
|
|
|
def test_parse_sdmx_json_dimensions_and_attributes():
|
|
message = {
|
|
"dataSets": [
|
|
{
|
|
"series": {
|
|
"0": {
|
|
"attributes": [0, None, 9],
|
|
"observations": {"0": [2.0, 0, None]},
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"structure": {
|
|
"dimensions": {
|
|
"series": [{"id": "FREQ", "values": [{"id": "D", "name": "Daily"}]}],
|
|
"observation": [
|
|
{"id": "TIME_PERIOD", "values": [{"id": "2024-01-01"}]}
|
|
],
|
|
},
|
|
"attributes": {
|
|
"series": [
|
|
{"id": "UNIT", "values": [{"id": "EUR", "name": "Euro"}]},
|
|
{"id": "EMPTY", "values": []},
|
|
{"id": "OOR", "values": []},
|
|
],
|
|
"observation": [
|
|
{"id": "OBS_STATUS", "values": [{"id": "A", "name": "Normal"}]}
|
|
],
|
|
},
|
|
},
|
|
}
|
|
rows = parse_sdmx_json(message)
|
|
assert len(rows) == 1
|
|
row = rows[0]
|
|
assert row["FREQ"] == "D"
|
|
assert row["FREQ__label"] == "Daily"
|
|
assert row["series_key"] == "D"
|
|
assert row["_dim_ids"] == ["FREQ"]
|
|
assert row["UNIT"] == "EUR"
|
|
assert row["OBS_STATUS"] == "A"
|
|
assert row["OBS_VALUE"] == 2.0
|
|
|
|
|
|
def test_parse_sdmx_json_plain_values_and_no_obs_dims():
|
|
message = {
|
|
"dataSets": [{"series": {"0": {"observations": {"0": [1.0]}}}}],
|
|
"structure": {"dimensions": {"series": [{"id": "FREQ", "values": ["D"]}]}},
|
|
}
|
|
rows = parse_sdmx_json(message)
|
|
assert rows[0]["FREQ"] == "D"
|
|
assert rows[0]["OBS_VALUE"] == 1.0
|
|
|
|
|
|
def test_parse_sdmx_json_edge_branches():
|
|
message = {
|
|
"dataSets": [
|
|
{
|
|
"series": {
|
|
"0:0:0": {"observations": {}},
|
|
"0:5": {
|
|
"observations": {
|
|
"0": [],
|
|
"1": [2.0, 9],
|
|
}
|
|
},
|
|
}
|
|
}
|
|
],
|
|
"structure": {
|
|
"dimensions": {
|
|
"series": [
|
|
{"id": "FREQ", "values": [{"id": "D", "name": "Daily"}]},
|
|
{"id": "CURRENCY", "values": [{"id": "USD", "name": "US dollar"}]},
|
|
],
|
|
"observation": [
|
|
{
|
|
"id": "TIME_PERIOD",
|
|
"values": [{"id": "2024-01-01"}, "2024-01-02"],
|
|
}
|
|
],
|
|
},
|
|
"attributes": {
|
|
"series": [],
|
|
"observation": [
|
|
{"id": "OBS_STATUS", "values": [{"id": "A", "name": "Normal"}]}
|
|
],
|
|
},
|
|
},
|
|
}
|
|
rows = parse_sdmx_json(message)
|
|
out_of_range = [r for r in rows if r["FREQ"] == "D" and r["CURRENCY"] is None]
|
|
assert out_of_range
|
|
assert out_of_range[0]["series_key"] == "D"
|
|
assert any(r["OBS_VALUE"] is None for r in out_of_range)
|
|
assert all("OBS_STATUS" not in r for r in out_of_range)
|
|
|
|
|
|
def test_parse_series_keys_empty():
|
|
assert parse_series_keys({}) == []
|
|
assert parse_series_keys({"dataSets": []}) == []
|
|
|
|
|
|
def test_parse_series_keys_decodes_records():
|
|
message = {
|
|
"dataSets": [
|
|
{
|
|
"series": {
|
|
"0:0": {},
|
|
"0:1:0": {},
|
|
"0:5": {},
|
|
"": {},
|
|
}
|
|
}
|
|
],
|
|
"structure": {
|
|
"dimensions": {
|
|
"series": [
|
|
{"id": "FREQ", "values": [{"id": "D", "name": "Daily"}]},
|
|
{
|
|
"id": "CURRENCY",
|
|
"values": [{"id": "USD", "name": "US dollar"}, "JPY"],
|
|
},
|
|
]
|
|
}
|
|
},
|
|
}
|
|
by_key = {r["series_key"]: r for r in parse_series_keys(message)}
|
|
|
|
full = by_key["D.USD"]
|
|
assert full["FREQ"] == "D"
|
|
assert full["CURRENCY"] == "USD"
|
|
assert full["FREQ__label"] == "Daily"
|
|
assert full["name"] == "Daily — US dollar"
|
|
|
|
plain = by_key["D.JPY"]
|
|
assert plain["CURRENCY"] == "JPY"
|
|
assert plain["CURRENCY__label"] is None
|
|
assert plain["name"] == "Daily"
|
|
|
|
out_of_range = by_key["D"]
|
|
assert out_of_range["CURRENCY"] is None
|
|
|
|
empty = by_key[""]
|
|
assert empty["name"] == ""
|