From 600a1efd3f8ed320fc329147cbfafc2699b2c1f9 Mon Sep 17 00:00:00 2001 From: Mayank Lavania Date: Thu, 16 Jul 2026 09:21:39 +0530 Subject: [PATCH] fix(bench): treat pandas as optional in correctness_precheck test_correctness_precheck_runs hard-failed with ModuleNotFoundError when pandas was absent, taking the whole benchmark harness self-test down with it. python_comparisons.py already treats every other comparison dependency as optional -- _tail_sma_talib returns None on ImportError -> "not_installed", _tail_sma_quantwave returns None -> "skipped", and _collect_versions records "not_installed" for talib/pandas_ta. Only _tail_sma_pandas hard-imported, making pandas the sole mandatory dep in a module built to tolerate missing ones. _tail_sma_pandas now returns None on ImportError and correctness_precheck records "pandas_rolling": "not_installed", matching the talib branch exactly. Deliberately NOT pytest.importorskip("pandas") on the test: that would skip the entire precheck and discard the quantwave_ta correctness check -- the one comparison that actually guards this library. The precheck now still runs and reports quantwave_ta: ok without pandas installed. Polars remains the reference (_tail_sma_polars), so a missing pandas costs one cross-check, not the precheck. tests/python/test_benchmark_harness.py: 4 passed (was 3 passed, 1 failed). Co-Authored-By: Claude Opus 4.8 --- benchmarks/python_comparisons.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/benchmarks/python_comparisons.py b/benchmarks/python_comparisons.py index 0236ededd..776b26036 100644 --- a/benchmarks/python_comparisons.py +++ b/benchmarks/python_comparisons.py @@ -33,8 +33,11 @@ def _library_versions() -> dict[str, str]: return versions -def _tail_sma_pandas(close: np.ndarray, period: int) -> np.ndarray: - import pandas as pd +def _tail_sma_pandas(close: np.ndarray, period: int) -> np.ndarray | None: + try: + import pandas as pd + except ImportError: + return None return pd.Series(close).rolling(period).mean().to_numpy() @@ -80,12 +83,15 @@ def correctness_precheck(df: pl.DataFrame) -> dict[str, Any]: checks: dict[str, str] = {} pd_sma = _tail_sma_pandas(close, SMA_PERIOD) - mask = ~np.isnan(ref) & ~np.isnan(pd_sma) - if mask.any(): - ok = np.allclose(ref[mask], pd_sma[mask], rtol=TOLERANCE, atol=TOLERANCE) - checks["pandas_rolling"] = "ok" if ok else "mismatch" + if pd_sma is not None: + mask = ~np.isnan(ref) & ~np.isnan(pd_sma) + if mask.any(): + ok = np.allclose(ref[mask], pd_sma[mask], rtol=TOLERANCE, atol=TOLERANCE) + checks["pandas_rolling"] = "ok" if ok else "mismatch" + else: + checks["pandas_rolling"] = "insufficient_warmup" else: - checks["pandas_rolling"] = "insufficient_warmup" + checks["pandas_rolling"] = "not_installed" qw = _tail_sma_quantwave(small, SMA_PERIOD) if qw is not None: