From c31bed1ddc8511e4dbcce1bc904d66c2101a145d Mon Sep 17 00:00:00 2001 From: Lukas Heumos Date: Wed, 10 Jun 2026 17:10:04 +0200 Subject: [PATCH 1/4] fix: resolve test-suite warnings Clean up the warnings emitted while running the test suite, without changing any behavior. Fixed at the source: - Augur logistic regression no longer passes the `penalty` argument that scikit-learn 1.8 deprecated; the L1/L2 mix is now expressed via `l1_ratio` (l2 -> 0.0, identical coefficients to the old default) and the unregularized case via `C=np.inf`, with `saga` for the L1 paths. - The statsmodels DGE test sets the negative-binomial `alpha=1.0` explicitly (the previous implicit default), removing the dispersion warning raised at collection time. - The perturbation-space test wraps the intentional `ensure_consistency=False` calls in `pytest.warns`, asserting the expected UserWarning instead of letting it leak into the summary. Filtered as unavoidable third-party noise (consistent with the existing filterwarnings entries): - pydeseq2 dispersion-trend / residual-degrees-of-freedom warnings on the small synthetic data used by the Milo and compare_groups tests. - jaxopt maintenance notice, joblib loky worker notice, and the formulaic DataMismatchWarning from no-intercept contrast handling. Co-Authored-By: Claude Opus 4.8 --- pertpy/tools/_augur.py | 7 ++++++- pyproject.toml | 9 ++++++++- .../_differential_gene_expression/test_statsmodels.py | 2 +- .../test_simple_perturbation_space.py | 6 ++++-- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/pertpy/tools/_augur.py b/pertpy/tools/_augur.py index 41590653..9f1573fd 100644 --- a/pertpy/tools/_augur.py +++ b/pertpy/tools/_augur.py @@ -230,7 +230,12 @@ def create_estimator( random_state=random_state, ) elif classifier == "logistic_regression_classifier": - return LogisticRegression(penalty=penalty, random_state=random_state) + # scikit-learn 1.8 deprecated `penalty` in favor of `l1_ratio` (the L1/L2 mix) and `C` (no penalty via C=inf). + if penalty in (None, "none"): + return LogisticRegression(C=np.inf, random_state=random_state) + l1_ratio = {"l2": 0.0, "l1": 1.0, "elasticnet": 0.5}[penalty] + solver = "saga" if l1_ratio > 0.0 else "lbfgs" + return LogisticRegression(l1_ratio=l1_ratio, solver=solver, random_state=random_state) else: raise ValueError("Invalid classifier") diff --git a/pyproject.toml b/pyproject.toml index ed86d47c..2d646bd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -175,7 +175,14 @@ filterwarnings = [ "ignore:'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning", "ignore:In the future, the default backend for leiden will be igraph instead of leidenalg:FutureWarning", "ignore:Transforming to str index:anndata.ImplicitModificationWarning", - "ignore:Failed to correctly find n_neighbors for some samples:UserWarning" + "ignore:Failed to correctly find n_neighbors for some samples:UserWarning", + # pydeseq2 emits these on the small synthetic data used by the Milo and compare_groups tests; they are not actionable in pertpy. + "ignore:The dispersion trend curve fitting did not converge:UserWarning", + "ignore:As the residual degrees of freedom is less than 3:UserWarning", + # Third-party deprecation and runtime notices that pertpy cannot resolve at the source. + "ignore:JAXopt is no longer maintained:DeprecationWarning", + "ignore:A worker stopped while some jobs were given to the executor:UserWarning", + "ignore:Data has categories outside of the nominated levels" ] [tool.hatch.envs.default] diff --git a/tests/tools/_differential_gene_expression/test_statsmodels.py b/tests/tools/_differential_gene_expression/test_statsmodels.py index f5ea1264..bdb8d19c 100644 --- a/tests/tools/_differential_gene_expression/test_statsmodels.py +++ b/tests/tools/_differential_gene_expression/test_statsmodels.py @@ -8,7 +8,7 @@ pytestmark = pytest.mark.skip(reason="formulaic_contrasts and formulaic not available") -@pytest.mark.parametrize("kwargs", [{}, {"regression_model": sm.GLM, "family": sm.families.NegativeBinomial()}]) +@pytest.mark.parametrize("kwargs", [{}, {"regression_model": sm.GLM, "family": sm.families.NegativeBinomial(alpha=1.0)}]) def test_statsmodels(test_adata, kwargs): """Check that the method can be initialized and fitted, and perform basic checks on the result of test_contrasts.""" from pertpy.tools._differential_gene_expression import Statsmodels diff --git a/tests/tools/_perturbation_space/test_simple_perturbation_space.py b/tests/tools/_perturbation_space/test_simple_perturbation_space.py index 8a1a1627..1396dc55 100644 --- a/tests/tools/_perturbation_space/test_simple_perturbation_space.py +++ b/tests/tools/_perturbation_space/test_simple_perturbation_space.py @@ -199,12 +199,14 @@ def test_linear_operations(): # Input that has already been differenced — opt out of the auto-diff with ensure_consistency=False. ps_adata = ps.compute_control_diff(psadata) - ps_adata2 = ps.add(ps_adata, perturbations=["target1", "target2"], ensure_consistency=False) + with pytest.warns(UserWarning, match="Combining perturbations without"): + ps_adata2 = ps.add(ps_adata, perturbations=["target1", "target2"], ensure_consistency=False) test = ps_adata["control"].X + ps_adata["target1"].X + ps_adata["target2"].X np.testing.assert_allclose(test, ps_adata2["target1+target2"].X, rtol=1e-4) - ps_adata2 = ps.subtract(ps_adata, reference_key="target1", perturbations=["target1"], ensure_consistency=False) + with pytest.warns(UserWarning, match="Combining perturbations without"): + ps_adata2 = ps.subtract(ps_adata, reference_key="target1", perturbations=["target1"], ensure_consistency=False) ps_vector = ps_adata2["target1-target1"].X np.testing.assert_allclose(ps_adata2["control"].X, ps_adata2["target1-target1"].X, rtol=1e-4) From 3cbe9019693f6510f666725334b1cf55b549fec6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Jun 2026 15:12:04 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/tools/_differential_gene_expression/test_statsmodels.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/tools/_differential_gene_expression/test_statsmodels.py b/tests/tools/_differential_gene_expression/test_statsmodels.py index bdb8d19c..05b76983 100644 --- a/tests/tools/_differential_gene_expression/test_statsmodels.py +++ b/tests/tools/_differential_gene_expression/test_statsmodels.py @@ -8,7 +8,9 @@ pytestmark = pytest.mark.skip(reason="formulaic_contrasts and formulaic not available") -@pytest.mark.parametrize("kwargs", [{}, {"regression_model": sm.GLM, "family": sm.families.NegativeBinomial(alpha=1.0)}]) +@pytest.mark.parametrize( + "kwargs", [{}, {"regression_model": sm.GLM, "family": sm.families.NegativeBinomial(alpha=1.0)}] +) def test_statsmodels(test_adata, kwargs): """Check that the method can be initialized and fitted, and perform basic checks on the result of test_contrasts.""" from pertpy.tools._differential_gene_expression import Statsmodels From bfe61c5a63fa40a3f265cd5ca441719bffc97398 Mon Sep 17 00:00:00 2001 From: Lukas Heumos Date: Wed, 10 Jun 2026 17:31:54 +0200 Subject: [PATCH 3/4] chore: bump tutorials submodule to the milo runtime fix Points the tutorials submodule at scverse/pertpy-tutorials#65, which speeds up the miloDE section of the Milo notebook to run in well under 15 minutes (it had regressed to ~90 minutes). Co-Authored-By: Claude Opus 4.8 --- docs/tutorials/notebooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/notebooks b/docs/tutorials/notebooks index 5c93d2c2..ed35f78a 160000 --- a/docs/tutorials/notebooks +++ b/docs/tutorials/notebooks @@ -1 +1 @@ -Subproject commit 5c93d2c2dc686da7c78d1c79f7b299d35e22edf2 +Subproject commit ed35f78a02de86ccac6b45ddb8d9ddac8185a534 From 113563dfe05e08402bcf0fd33dfeac7347c56054 Mon Sep 17 00:00:00 2001 From: Lukas Heumos Date: Thu, 11 Jun 2026 09:52:04 +0200 Subject: [PATCH 4/4] chore: bump tutorials submodule to merged miloDE speedup scverse/pertpy-tutorials#65 is merged; point the submodule at the squashed commit on tutorials main. Co-Authored-By: Claude Opus 4.8 --- docs/tutorials/notebooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/notebooks b/docs/tutorials/notebooks index ed35f78a..42d7ee0f 160000 --- a/docs/tutorials/notebooks +++ b/docs/tutorials/notebooks @@ -1 +1 @@ -Subproject commit ed35f78a02de86ccac6b45ddb8d9ddac8185a534 +Subproject commit 42d7ee0fb8ede8167d65b577526af895e78a2436