The self-heal commit (a00f967) inserted the _research method INSIDE __init__ at
method-body indent, truncating it so _change_signal/_backtest_lock/_backtest_
cache never got set -> AttributeError on backtest. Moved _research to a sibling
method; __init__ now sets all attrs. Two chart/sparkline tests updated: a None
research_con now REOPENS lazily, so 'no research db attached' is reached only
when the reopen also fails (they monkeypatch open to fail). 22 api tests green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
"""Standalone dashboard sparklines: the fix is a NON-None research reader
|
|
(plan 007 step 5). Without it bars() short-circuits; with one it runs the query
|
|
(an empty array on a bare DB is still a PASS)."""
|
|
|
|
import pandas as pd
|
|
|
|
from api.main import DashboardState
|
|
|
|
|
|
class _FakeResult:
|
|
def df(self):
|
|
return pd.DataFrame()
|
|
|
|
def fetchone(self):
|
|
return [None]
|
|
|
|
|
|
class _FakeResearchCon:
|
|
def execute(self, *args, **kwargs):
|
|
return _FakeResult()
|
|
|
|
|
|
def test_bars_without_reader_reports_missing_db(monkeypatch):
|
|
# self-heal (2026-07-20): None con reopens lazily; "missing db" only when
|
|
# the reopen also fails.
|
|
import api.main as m
|
|
monkeypatch.setattr(m, "open_research_db", lambda name: (_ for _ in ()).throw(RuntimeError("db down")))
|
|
out = DashboardState("momentum", research_con=None).bars("AAPL")
|
|
assert out["bars"] == []
|
|
assert out.get("reason") == "no research db attached"
|
|
|
|
|
|
def test_bars_with_reader_runs_query():
|
|
out = DashboardState("momentum", research_con=_FakeResearchCon()).bars("AAPL")
|
|
# the reader path ran (empty DB -> empty array, but NOT the "no db" short-circuit)
|
|
assert out["bars"] == []
|
|
assert "reason" not in out
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
import pytest
|
|
pytest.main([__file__, "-q"])
|