From 832aa16a6771b35aa1ea9e19911e5a6552603b88 Mon Sep 17 00:00:00 2001 From: Tarun Date: Wed, 1 Apr 2026 01:13:03 +0530 Subject: [PATCH 1/2] [BUG] fix bare print on non-convergence and malformed ValueError format - Replace `print("did not converge")` with `warnings.warn()` so that non-convergence is surfaced through Python's warning system instead of printing to stdout. This allows users to filter/capture the message programmatically. - Fix string formatting bug in `_estimate_GCV_UBRE` where `format(gamma)` was passed as a separate argument to `ValueError` instead of being interpolated into the message string, resulting in a confusing tuple error message like `('msg {}', '0.5')`. --- pygam/pygam.py | 9 ++++++--- pygam/tests/test_GAM_methods.py | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/pygam/pygam.py b/pygam/pygam.py index 6f86ae43..6648691f 100644 --- a/pygam/pygam.py +++ b/pygam/pygam.py @@ -818,7 +818,11 @@ def _pirls(self, X, Y, weights): if diff < self.tol: return - print("did not converge") + warnings.warn( + "PIRLS did not converge." + " Try increasing max_iter or decreasing tol.", + stacklevel=2, + ) return def _on_loop_start(self, variables): @@ -1194,8 +1198,7 @@ def _estimate_GCV_UBRE( """ if gamma < 1: raise ValueError( - "gamma scaling should be greater than 1, but found gamma = {}", - format(gamma), + f"gamma scaling should be greater than 1, but found gamma = {gamma}" ) if modelmat is None: diff --git a/pygam/tests/test_GAM_methods.py b/pygam/tests/test_GAM_methods.py index ee29de14..c9273776 100644 --- a/pygam/tests/test_GAM_methods.py +++ b/pygam/tests/test_GAM_methods.py @@ -467,6 +467,31 @@ def test_fit_quantile_NOT_close_enough(head_circumference_X_y): assert np.abs(ratio - quantile) > tol +def test_non_convergence_emits_warning(mcycle_X_y): + """Non-convergence should emit a warning, not print to stdout.""" + X, y = mcycle_X_y + gam = LinearGAM(max_iter=1, tol=1e-100) + import warnings + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + gam.fit(X, y) + convergence_warnings = [ + x for x in w if "did not converge" in str(x.message) + ] + assert len(convergence_warnings) == 1 + + +def test_GCV_UBRE_gamma_error_message(mcycle_X_y, mcycle_gam): + """ValueError for gamma < 1 should have a properly formatted message.""" + with pytest.raises(ValueError, match=r"gamma.*0\.5"): + mcycle_gam._estimate_GCV_UBRE( + y=mcycle_X_y[1], + modelmat=mcycle_gam._modelmat(mcycle_X_y[0]), + gamma=0.5, + ) + + def test_fit_quantile_raises_ValueError(head_circumference_X_y): """see that we DO NOT get fit on bad argument requests""" X, y = head_circumference_X_y From 3ce140aa475cbb3cd4c6a0c3e8aabac8a3cbed84 Mon Sep 17 00:00:00 2001 From: Tarun Date: Wed, 1 Apr 2026 13:39:30 +0530 Subject: [PATCH 2/2] [MNT] fix ruff-format: join strings and inline list comprehension --- pygam/pygam.py | 3 +-- pygam/tests/test_GAM_methods.py | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pygam/pygam.py b/pygam/pygam.py index 6648691f..8e02899d 100644 --- a/pygam/pygam.py +++ b/pygam/pygam.py @@ -819,8 +819,7 @@ def _pirls(self, X, Y, weights): return warnings.warn( - "PIRLS did not converge." - " Try increasing max_iter or decreasing tol.", + "PIRLS did not converge. Try increasing max_iter or decreasing tol.", stacklevel=2, ) return diff --git a/pygam/tests/test_GAM_methods.py b/pygam/tests/test_GAM_methods.py index c9273776..697cd606 100644 --- a/pygam/tests/test_GAM_methods.py +++ b/pygam/tests/test_GAM_methods.py @@ -476,9 +476,7 @@ def test_non_convergence_emits_warning(mcycle_X_y): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") gam.fit(X, y) - convergence_warnings = [ - x for x in w if "did not converge" in str(x.message) - ] + convergence_warnings = [x for x in w if "did not converge" in str(x.message)] assert len(convergence_warnings) == 1