Skip to content

Commit

Permalink
[MAINT] Implement deprecation warnings-as-errors in prerelease test u…
Browse files Browse the repository at this point in the history
…sing pytest fixture (#3936)

* Add fixture

* Add dependencies

* TODO

* Add monthly workflow config

* Numpy deprecation

* Update workflow

* Update

* Add to readme
  • Loading branch information
ymzayek committed Oct 5, 2023
1 parent 3b9e093 commit 7739f95
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 2 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ Artifacts hosting and deployment of development docs use CircleCI. See [.circlec
On a pull request, only the "host" job is run. Then the artifacts can be accessed from the `host_and_deploy_doc` workflow seen under the checks list. Click on "Details" and then on the "host_docs" link on the page that opens. From there you can click on the artifacts tab to see all the html files. If you click on any of them you can then normally navigate the pages from there.
With a merge on main, both "host" and "deploy" jobs are run.

## DeprecationWarnings as errors

### check_deprecations.yml

Checks external core dependencies for deprecation warnings so they can be caught and resolved before causing a failure.
Runs once a month and can be run manually from Github Actions.
It works by calling pytest with an environment variable that will trigger a pytest fixture (``warnings_as_errors``) defined in [nilearn/conftest.py](/nilearn/conftest.py).

## Check spelling errors

### codespell.yml
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/check_deprecations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
name: check deprecations

# Runs once a month.
# Checks for deprecations of core dependencies of nilearn
# Turns deprecation warnings into errors so we can handle
# them before an actual failure happens.

on:

# Uses the cron schedule for github actions
#
# https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#scheduled-events
#
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# │ │ │ │ │
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
schedule:
- cron: 0 0 25 * * # on the 25th of every month

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

jobs:
deprecations:
if: github.repository == 'nilearn/nilearn'
runs-on: ubuntu-latest
env:
PIP_FLAGS: --pre
WARN_DEPRECATION_ERRORS: true

defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4

- name: Setup python
uses: actions/setup-python@v4
with:
python-version: 3.12

- name: Display Python version
run: python -c "import sys; print(sys.version)"

- name: Install dependencies
run: ./build_tools/github/dependencies.sh

- name: Install nilearn
run: ./build_tools/github/install.sh

- name: Run tests
run: python -m pytest --pyargs nilearn
32 changes: 32 additions & 0 deletions nilearn/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""Configuration and extra fixtures for pytest."""
import os
import warnings

import nibabel
import numpy as np
import pytest
Expand Down Expand Up @@ -79,6 +82,35 @@ def close_all():
plt.close("all") # takes < 1 us so just always do it


@pytest.fixture(autouse=True)
def warnings_as_errors():
"""Raise errors on deprecations from external library prereleases."""
flag = os.environ.get("WARN_DEPRECATION_ERRORS")
if flag == "true":
with warnings.catch_warnings():
warnings.filterwarnings(
"error",
message=".*numpy.*|.*scipy.*|.*nibabel.*|"
".*joblib.*|.*pandas.*|.*scikit-learn.*",
category=DeprecationWarning,
)
if matplotlib is not None:
warnings.filterwarnings(
"error",
category=matplotlib.MatplotlibDeprecationWarning,
)
# Ignore internal DeprecationWarnings that reference a dependency
pattern = '.*The "C" parameter.*'
warnings.filterwarnings(
"ignore",
message=pattern,
category=DeprecationWarning,
)
yield
else:
yield


# ------------------------ RNG ------------------------#


Expand Down
4 changes: 2 additions & 2 deletions nilearn/mass_univariate/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def get_tvalue_with_alternative_library(tested_vars, target_vars, covars=None):
current_tested_mask[j] = True
current_design_matrix = design_matrix[:, current_tested_mask]
ols_fit = OLS(current_target, current_design_matrix).fit()
t_values[i, j] = np.ravel(ols_fit.t_test(test_matrix).tvalue)
t_values[i, j] = np.squeeze(ols_fit.t_test(test_matrix).tvalue)

except ImportError: # use linalg if statsmodels is not available
from numpy import linalg
Expand Down Expand Up @@ -83,7 +83,7 @@ def get_tvalue_with_alternative_library(tested_vars, target_vars, covars=None):
/ float(n_samples - lost_dof)
* t_val_denom_aux
)
t_values[j, i] = np.ravel(t_val_num / t_val_denom)
t_values[j, i] = np.squeeze(t_val_num / t_val_denom)

t_values = t_values.T
assert t_values.shape == (n_regressors, n_descriptors)
Expand Down

0 comments on commit 7739f95

Please sign in to comment.