Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions eodhd/apiclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ def _rest_get(self, endpoint: str = "", uri: str = "", querystring: str = "") ->
else:
return pd.DataFrame(json_data, index=[0])

def _strip_free_tier_warning(self, df_data: pd.DataFrame) -> pd.DataFrame:
"""Free API keys append a 'warning' column (e.g. data limited to one year)
to historical responses. Surface the message and drop the column so the
downstream fixed-width column relabelling does not raise a confusing
"Length mismatch" pandas error (see issue #66)."""
if "warning" in df_data.columns:
messages = df_data["warning"].dropna()
if not messages.empty:
self.console.log("EODHD API warning:", messages.iloc[-1])
df_data = df_data.drop(columns=["warning"])
return df_data

def get_exchanges(self) -> pd.DataFrame:
"""Get supported exchanges"""

Expand Down Expand Up @@ -313,6 +325,7 @@ def get_historical_data(
sys.exit()

df_data = self._rest_get("eod", symbol, f"&period={interval}&from={str(date_from)}&to={str(date_to)}")
df_data = self._strip_free_tier_warning(df_data)

if len(df_data) == 0:
columns_eod = [
Expand Down Expand Up @@ -424,6 +437,7 @@ def get_historical_data(
sys.exit()

df_data = self._rest_get("intraday", symbol, f"&interval={interval}&from={str(date_from)}&to={str(date_to)}")
df_data = self._strip_free_tier_warning(df_data)

if len(df_data) == 0:
columns_eod = [
Expand Down
65 changes: 65 additions & 0 deletions tests/test_historical_free_tier_warning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Regression test for issue #66.

A free API key requesting more than one year of historical data gets an extra
'warning' column appended to the response. The fixed-width column relabelling in
get_historical_data then raised a confusing pandas "Length mismatch" error.
The warning must be surfaced and the column dropped instead.
"""

from unittest.mock import patch

import pandas as pd
import pytest

from eodhd.apiclient import APIClient


@pytest.fixture
def client():
with patch("eodhd.apiclient.requests.Session"):
yield APIClient(api_key="demo1234567890123456")


def _free_tier_eod_frame():
"""Mimics the EOD response a free key returns for a >1y request: a trailing
'warning' column that is NaN on every row except the last."""
return pd.DataFrame(
{
"date": ["2025-04-22", "2025-04-23"],
"open": [14347.8896, 14404.0498],
"high": [14414.0996, 14645.2598],
"low": [14293.0303, 14403.5498],
"close": [14404.0498, 14549.4199],
"adjusted_close": [14404.0498, 14549.4199],
"volume": [0, 0],
"warning": [None, "Data is limited by one year as you have free subscription."],
}
)


def test_free_tier_warning_does_not_raise(client):
with patch.object(client, "_rest_get", return_value=_free_tier_eod_frame()):
df = client.get_historical_data("BUKAC.INDX", interval="d", results=10000)

# Previously raised: ValueError: Length mismatch: Expected axis has 9 elements...
assert "warning" not in df.columns
assert list(df.columns) == [
"symbol",
"interval",
"open",
"high",
"low",
"close",
"adjusted_close",
"volume",
]
assert len(df) == 2


def test_free_tier_warning_is_logged(client):
with patch.object(client, "_rest_get", return_value=_free_tier_eod_frame()):
with patch.object(client.console, "log") as mock_log:
client.get_historical_data("BUKAC.INDX", interval="d", results=10000)

logged = " ".join(str(a) for call in mock_log.call_args_list for a in call.args)
assert "warning" in logged.lower()