Skip to content

Commit 3afd1cd

Browse files
fix: raise error for missing explicit exogenous columns (#441)
Squash-merged from #441 by @Saloni-0465. Co-authored-by: Saloni-0465 <Saloni-0465@users.noreply.github.com>
1 parent 6a7262e commit 3afd1cd

2 files changed

Lines changed: 91 additions & 2 deletions

File tree

src/sktime_mcp/data/base.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,15 @@ def to_sktime_format(self, data: pd.DataFrame) -> tuple[pd.Series, pd.DataFrame
102102

103103
# Get exogenous variables if specified
104104
if exog_cols:
105-
valid_exog_cols = [col for col in exog_cols if col in data.columns]
106-
X = data[valid_exog_cols] if valid_exog_cols else None
105+
missing_exog_cols = [col for col in exog_cols if col not in data.columns]
106+
if missing_exog_cols:
107+
available_columns = ", ".join(repr(col) for col in data.columns)
108+
raise ValueError(
109+
f"Exogenous column(s) not found in data: {missing_exog_cols!r}. "
110+
f"Available columns: [{available_columns}]"
111+
)
112+
113+
X = data[exog_cols]
107114
else:
108115
# Use all columns except target as exogenous
109116
other_cols = [col for col in data.columns if col != target_col]
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""Tests for explicit exogenous column validation in data adapters."""
2+
3+
import sys
4+
from pathlib import Path
5+
6+
import pytest
7+
8+
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
9+
10+
from sktime_mcp.data.adapters.pandas_adapter import PandasAdapter
11+
from sktime_mcp.runtime.executor import Executor
12+
13+
14+
def test_to_sktime_format_rejects_missing_explicit_exog_column():
15+
"""Explicit exog_columns should fail if any requested column is absent."""
16+
adapter = PandasAdapter(
17+
{
18+
"type": "pandas",
19+
"data": {
20+
"date": ["2020-01-01", "2020-01-02", "2020-01-03"],
21+
"value": [1, 2, 3],
22+
"promo": [0, 1, 0],
23+
},
24+
"time_column": "date",
25+
"target_column": "value",
26+
"exog_columns": ["promo", "holiday"],
27+
}
28+
)
29+
data = adapter.load()
30+
31+
with pytest.raises(ValueError, match="Exogenous column\\(s\\) not found"):
32+
adapter.to_sktime_format(data)
33+
34+
35+
def test_load_data_source_returns_error_for_missing_explicit_exog_column():
36+
"""Executor should surface missing exog columns as a structured tool error."""
37+
executor = Executor()
38+
39+
result = executor.load_data_source(
40+
{
41+
"type": "pandas",
42+
"data": {
43+
"date": ["2020-01-01", "2020-01-02", "2020-01-03"],
44+
"value": [1, 2, 3],
45+
"promo": [0, 1, 0],
46+
},
47+
"time_column": "date",
48+
"target_column": "value",
49+
"exog_columns": ["promo", "holiday"],
50+
}
51+
)
52+
53+
assert result["success"] is False
54+
assert result["error_type"] == "ValueError"
55+
assert "Exogenous column(s) not found" in result["error"]
56+
assert "holiday" in result["error"]
57+
assert "promo" in result["error"]
58+
59+
60+
def test_to_sktime_format_keeps_all_valid_explicit_exog_columns():
61+
"""Valid exog_columns should be preserved exactly when all columns exist."""
62+
adapter = PandasAdapter(
63+
{
64+
"type": "pandas",
65+
"data": {
66+
"date": ["2020-01-01", "2020-01-02", "2020-01-03"],
67+
"value": [1, 2, 3],
68+
"promo": [0, 1, 0],
69+
"price": [10, 11, 12],
70+
},
71+
"time_column": "date",
72+
"target_column": "value",
73+
"exog_columns": ["promo", "price"],
74+
}
75+
)
76+
data = adapter.load()
77+
78+
y, X = adapter.to_sktime_format(data)
79+
80+
assert y.name == "value"
81+
assert list(X.columns) == ["promo", "price"]
82+

0 commit comments

Comments
 (0)