diff --git a/mkdocs.yml b/mkdocs.yml index b4dc22d..d9539e0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,7 +1,7 @@ INHERIT: docs/mkdocs-base.yml site_name: pycharting -site_description: Add your description here. +site_description: High-performance financial charting library for OHLC data visualization with technical indicators site_url: https://alihaskar.github.io/pycharting/ repo_url: https://github.com/alihaskar/pycharting repo_name: alihaskar/pycharting diff --git a/src/pycharting/api/interface.py b/src/pycharting/api/interface.py index efa4283..e1dc87c 100644 --- a/src/pycharting/api/interface.py +++ b/src/pycharting/api/interface.py @@ -24,7 +24,7 @@ from pycharting.api.routes import _data_managers from pycharting.core.lifecycle import ChartServer -from pycharting.data.ingestion import DataManager, SubplotSpec +from pycharting.data.ingestion import DataManager, DataValidationError, SubplotSpec logger = logging.getLogger(__name__) @@ -259,12 +259,27 @@ def plot( _notify("\n⚠️ Interrupted - stopping server...") _active_server.stop_server() + except DataValidationError as e: + # Input data failed validation — the user can fix this by correcting + # their arrays before calling plot() again. + logger.error(f"Invalid input data: {e}", exc_info=True) + _notify(f"\n✗ Invalid input data: {e}\n") + + return { + "status": "error", + "stage": "validation", + "error": str(e), + "session_id": session_id, + } except Exception as e: + # Server startup, browser launch, or other runtime failure — not + # something the caller's data can fix. logger.error(f"Error creating chart: {e}", exc_info=True) _notify(f"\n✗ Error creating chart: {e}\n") return { "status": "error", + "stage": "server", "error": str(e), "session_id": session_id, } diff --git a/tests/pycharting/api/test_interface.py b/tests/pycharting/api/test_interface.py index 3e35a42..295c867 100644 --- a/tests/pycharting/api/test_interface.py +++ b/tests/pycharting/api/test_interface.py @@ -119,6 +119,24 @@ def test_plot_with_invalid_data(): assert result["status"] == "error" assert "error" in result + # A validation failure must be reported as such, distinct from server/runtime errors. + assert result["stage"] == "validation" + + +def test_plot_server_startup_failure_reported_as_server_stage(): + """A non-validation failure (e.g. server startup) is reported with stage='server'.""" + n = 20 + data = np.random.randn(n) + 100 + index = np.arange(n) + + # Valid data passes validation, so the error must come from a later stage. + with patch("pycharting.api.interface.ChartServer") as mock_server: + mock_server.side_effect = RuntimeError("boom: could not start server") + result = plot(index, close=data, open_browser=False, block=False) + + assert result["status"] == "error" + assert result["stage"] == "server" + assert "boom" in result["error"] @patch("webbrowser.open")