From 2d80241bab55677d273db255ff8d57e8c7bffb9d Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Mon, 20 Jul 2026 11:33:33 +0400 Subject: [PATCH 1/2] fix: real mkdocs description and staged error handling in plot() (#56, #50) - mkdocs.yml: replace placeholder site_description with the real description from pyproject.toml (#56) - interface.py: split the broad except in plot() so DataValidationError is reported with stage="validation" (fixable input) separately from server/runtime failures reported with stage="server" (#50) - test_interface.py: assert the validation stage is reported Co-Authored-By: Claude Opus 4.8 (1M context) --- mkdocs.yml | 2 +- src/pycharting/api/interface.py | 17 ++++++++++++++++- tests/pycharting/api/test_interface.py | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) 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..ff22aec 100644 --- a/tests/pycharting/api/test_interface.py +++ b/tests/pycharting/api/test_interface.py @@ -119,6 +119,8 @@ 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" @patch("webbrowser.open") From 85446b343d85534917e10547d34f8d9ac724c604 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Mon, 20 Jul 2026 12:06:56 +0400 Subject: [PATCH 2/2] test: cover server-stage failure branch in plot() (#50) Splitting the broad except in plot() left the generic (server/runtime) except branch unexercised once validation errors took their own branch, dropping interface.py coverage below 100%. Add a test that forces a ChartServer startup failure and asserts stage="server". Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/pycharting/api/test_interface.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/pycharting/api/test_interface.py b/tests/pycharting/api/test_interface.py index ff22aec..295c867 100644 --- a/tests/pycharting/api/test_interface.py +++ b/tests/pycharting/api/test_interface.py @@ -123,6 +123,22 @@ def test_plot_with_invalid_data(): 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") def test_plot_opens_browser(mock_browser): """Test that plot opens browser when requested."""