Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cb25a42
MAINT: Switch to pip for macOS jobs
larsoner May 1, 2026
91bf042
FIX: More
larsoner May 1, 2026
22f6f7b
FIX: arm64 can run slow ones now
larsoner May 1, 2026
8fe639b
FIX: Bash
larsoner May 1, 2026
90a88f1
FIX: Escapes
larsoner May 1, 2026
f124275
FIX: Kind
larsoner May 1, 2026
58dc371
FIX: Cleaner
larsoner May 1, 2026
9bab071
FIX: Simplify
larsoner May 1, 2026
d8e276e
FIX: Better
larsoner May 1, 2026
a2a22b3
FIX: Simplify
larsoner May 1, 2026
01539a3
FIX: Verify
larsoner May 1, 2026
d7d6847
FIX: Cleanup
larsoner May 1, 2026
ac1f9ef
FIX: Py ver
larsoner May 1, 2026
6a2a48e
FIX: Move
larsoner May 1, 2026
11b31b9
FIX: Move
larsoner May 1, 2026
bf7c8ae
FIX: Move
larsoner May 1, 2026
e53a486
FIX: noqt
larsoner May 1, 2026
39df8bf
FIX: Clean
larsoner May 1, 2026
86cc184
FIX: Clean
larsoner May 1, 2026
c7116c6
FIX: Names
larsoner May 1, 2026
0484054
FIX: Revert
larsoner May 2, 2026
02f70a4
WIP: Try
larsoner May 2, 2026
2f1fd11
FIX: Both
larsoner May 2, 2026
a0ea25c
TST: Try
larsoner May 2, 2026
257396f
FIX: Which
larsoner May 2, 2026
31e5c59
Merge remote-tracking branch 'upstream/main' into pip
larsoner May 2, 2026
aa00244
FIX: No need
larsoner May 2, 2026
8688367
FIX: Try again [skip circle] [skip azp]
larsoner May 2, 2026
77fde19
FIX: Check
larsoner May 2, 2026
add35b7
FIX: More
larsoner May 2, 2026
3498aae
FIX: Restore
larsoner May 2, 2026
c5befee
FIX: Simplify
larsoner May 2, 2026
0f960a9
FIX: Names
larsoner May 2, 2026
e5effb4
FIX: Clean
larsoner May 2, 2026
629329c
FIX: Ubuntu
larsoner May 2, 2026
22f29d7
Bash
larsoner May 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 15 additions & 31 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
persist-credentials: false
- uses: actions/setup-python@v6
with:
python-version: '3.13'
python-version: '3.14'
- uses: pre-commit/action@v3.0.1
- run: pip install mypy numpy scipy vulture
- run: mypy
Expand Down Expand Up @@ -76,15 +76,12 @@ jobs:
- os: ubuntu-latest
python: '3.13'
kind: conda
- os: macos-latest # arm64 (Apple Silicon): Sequoia
python: '3.13'
kind: mamba
- os: macos-15-intel # intel: Sequoia
- os: macos-latest # arm64
python: '3.14'
kind: pip
- os: macos-15-intel # Intel
python: '3.13'
kind: mamba
- os: windows-latest
python: '3.11'
kind: mamba
kind: pip
- os: ubuntu-latest
python: '3.12'
kind: minimal
Expand Down Expand Up @@ -122,36 +119,21 @@ jobs:
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python }}
if: startswith(matrix.kind, 'pip')
if: startswith(matrix.kind, 'pip') || matrix.kind == 'minimal'
id: setup-python
# Workaround macOS path behavior with login shells (which puts system Python first)
- run: echo "export PATH=\"$(dirname ${{ steps.setup-python.outputs.python-path }}):$PATH\"" | tee -a ~/.bash_profile # zizmor: ignore[template-injection]
if: startswith(matrix.kind, 'pip') && startswith(matrix.os, 'macos')
# Python (if conda)
- name: Fixes for conda
run: |
# For some reason on Linux we get crashes
if [[ "$RUNNER_OS" == "Linux" ]]; then
sed -i "/numba/d" environment.yml
fi
# And on Windows and macOS PySide6.9.0 segfaults
if [[ "$RUNNER_OS" == "macOS" ]]; then
sed -i "" "s/ - PySide6 .*/ - PySide6 =6.9.2/g" environment.yml
sed -i "" "s/ - vtk .*/ - vtk =9.5.1/g" environment.yml

else
sed -i "s/ - PySide6 .*/ - PySide6 =6.9.2/g" environment.yml
sed -i "s/ - vtk .*/ - vtk =9.5.1/g" environment.yml
if [[ "$RUNNER_OS" == "Windows" ]]; then
echo "MNE_IS_OSMESA=true" | tee -a $GITHUB_ENV
fi
fi
if: matrix.kind == 'conda' || matrix.kind == 'mamba'
- uses: mamba-org/setup-micromamba@v3
with:
environment-file: ${{ env.CONDA_ENV }}
environment-name: mne
log-level: ${{ runner.debug == '1' && 'debug' || 'info' }}
log-level: 'info'
create-args: >-
python=${{ env.PYTHON_VERSION }}
-v
if: matrix.kind == 'conda' || matrix.kind == 'mamba'
if: matrix.kind == 'conda'
timeout-minutes: 20
# Python (if old)
- uses: astral-sh/setup-uv@v8.1.0
Expand All @@ -162,7 +144,9 @@ jobs:
**/pylock.ci-old.toml
python-version: ${{ matrix.python }}
if: matrix.kind == 'old'
- run: bash ./tools/github_actions_verify_python.sh "${{ matrix.python }}"
- run: bash ./tools/github_actions_dependencies.sh
timeout-minutes: 10
- run: python ./tools/github_actions_check_old_env.py
if: matrix.kind == 'old'
# Minimal commands on Linux (macOS stalls)
Expand Down
49 changes: 11 additions & 38 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ stages:
variables:
AZURE_CI: 'true'
jobs:
- job: Ultraslow_PG
- job: Linux_Ultraslow_PG
pool:
vmImage: 'ubuntu-22.04'
vmImage: 'ubuntu-latest'
variables:
DISPLAY: ':99'
OPENBLAS_NUM_THREADS: '1'
Expand All @@ -93,7 +93,7 @@ stages:
MNE_BROWSER_PRECOMPUTE: 'false'
steps:
- bash: |
set -e
set -eo pipefail
./tools/setup_xvfb.sh
sudo apt install -yq tcsh
displayName: 'Install Ubuntu dependencies'
Expand All @@ -112,19 +112,19 @@ stages:
addToPath: true
displayName: 'Get Python'
- bash: |
set -e
set -eo pipefail
python -m pip install --progress-bar off --upgrade pip
python -m pip install --progress-bar off "mne-qt-browser[opengl] @ git+https://github.com/mne-tools/mne-qt-browser.git" pyvista scikit-learn python-picard qtpy nibabel sphinx-gallery "PySide6!=6.8.0,!=6.8.0.1,!=6.8.1.1,!=6.9.1" pandas neo pymatreader antio defusedxml curryreader pymef
python -m pip uninstall -yq mne
python -m pip install --progress-bar off --upgrade -e . --group=test
displayName: 'Install dependencies with pip'
- bash: |
set -e
set -eo pipefail
mne sys_info -pd
mne sys_info -pd | grep "qtpy .*(PySide6=.*)$"
displayName: Print config
- bash: |
set -e
set -eo pipefail
LD_DEBUG=libs python -c "from PySide6.QtWidgets import QApplication, QWidget; app = QApplication([]); import matplotlib; matplotlib.use('QtAgg'); import matplotlib.pyplot as plt; plt.figure()"
- bash: source tools/get_testing_version.sh
displayName: 'Get testing version'
Expand All @@ -141,19 +141,10 @@ stages:
- bash: bash <(curl -s https://codecov.io/bash)
displayName: 'Codecov'
condition: succeededOrFailed()
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/junit-*.xml'
testRunTitle: 'Publish test results for $(Agent.JobName)'
failTaskOnFailedTests: true
condition: succeededOrFailed()
- task: PublishCodeCoverageResults@2
inputs:
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'

- job: Qt
- job: Linux_Qt_Bindings
pool:
vmImage: 'ubuntu-22.04'
vmImage: 'ubuntu-latest'
variables:
DISPLAY: ':99'
OPENBLAS_NUM_THREADS: '1'
Expand All @@ -169,7 +160,7 @@ stages:
addToPath: true
displayName: 'Get Python'
- bash: |
set -e
set -eo pipefail
python -m pip install --progress-bar off --upgrade pip
python -m pip install --progress-bar off --upgrade --pre --only-binary=\"numpy,scipy,matplotlib,vtk\" numpy scipy matplotlib vtk
python -c "import vtk"
Expand Down Expand Up @@ -223,15 +214,6 @@ stages:
- bash: bash <(curl -s https://codecov.io/bash)
displayName: 'Codecov'
condition: succeededOrFailed()
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/junit-*.xml'
testRunTitle: 'Publish test results for $(Agent.JobName)'
failTaskOnFailedTests: true
condition: succeededOrFailed()
- task: PublishCodeCoverageResults@2
inputs:
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'

- job: Windows
pool:
Expand All @@ -250,9 +232,9 @@ stages:
strategy:
maxParallel: 4
matrix:
3.10 pip:
3.11 pip:
TEST_MODE: 'pip'
PYTHON_VERSION: '3.10'
PYTHON_VERSION: '3.11'
3.13 pip pre:
TEST_MODE: 'pip-pre'
PYTHON_VERSION: '3.13'
Expand Down Expand Up @@ -292,12 +274,3 @@ stages:
- bash: bash <(curl -s https://codecov.io/bash)
displayName: 'Codecov'
condition: succeededOrFailed()
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/junit-*.xml'
testRunTitle: 'Publish test results for $(Agent.JobName) $(TEST_MODE) $(PYTHON_VERSION)'
failTaskOnFailedTests: true
condition: succeededOrFailed()
- task: PublishCodeCoverageResults@2
inputs:
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
8 changes: 5 additions & 3 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ channels:
dependencies:
- python >=3.10
- antio >=0.5.0
- conda
- curryreader >=0.1.2
- darkdetect
- decorator >=5.1
Expand All @@ -29,9 +30,11 @@ dependencies:
- matplotlib >=3.8
- mffpy >=0.5.7
- mne-qt-browser
- nest-asyncio2
- nibabel >=2.0
- nilearn
- nomkl
- noqt5
- numba >=0.35
- numpy >=1.26,<3
- openmeeg >=2.5.7
Expand All @@ -43,7 +46,7 @@ dependencies:
- pyarrow
- pybv
- pymatreader
- PySide6 !=6.9.1
- PySide6 ==6.10.2
- python-neo
- python-picard >=0.4
- pyvista >=0.43
Expand All @@ -61,9 +64,8 @@ dependencies:
- trame
- trame-vtk
- trame-vuetify
- vtk >=9.2
- vtk ==9.6.0
- xlrd
- pip:
- nest-asyncio2
- pymef
- pyobjc-framework-Cocoa >=5.2.0;platform_system=='Darwin'
1 change: 1 addition & 0 deletions mne/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ def pytest_configure(config: pytest.Config):
# VTK <-> NumPy 2.5 (https://gitlab.kitware.com/vtk/vtk/-/merge_requests/12796)
# nitime <-> NumPy 2.5 (https://github.com/nipy/nitime/pull/236)
ignore:Setting the shape on a NumPy array has been deprecated.*:DeprecationWarning
ignore:Implicitly cleaning up.*:ResourceWarning
""" # noqa: E501
for warning_line in warning_lines.split("\n"):
warning_line = warning_line.strip()
Expand Down
2 changes: 1 addition & 1 deletion mne/tests/test_source_estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1983,7 +1983,7 @@ def test_scale_morph_labels(kind, scale, monkeypatch, tmp_path):
min_, max_ = 0.72, 0.76
else:
# min_, max_ = 0.84, 0.855 # zooms='auto' values
min_, max_ = 0.46, 0.63
min_, max_ = 0.44, 0.63
assert min_ < corr <= max_, scale
else:
assert_allclose(label_tc, label_tc_to_morph, atol=1e-12, rtol=1e-12)
Expand Down
1 change: 1 addition & 0 deletions mne/viz/tests/test_evoked.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ def test_plot_white_rank():
evoked.plot_white(cov, rank=rank)


@pytest.mark.slowtest
def test_plot_white():
"""Test plot_white."""
cov = read_cov(cov_fname)
Expand Down
15 changes: 0 additions & 15 deletions tools/environment_minimal.yml

This file was deleted.

1 change: 0 additions & 1 deletion tools/get_minimal_commands.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,3 @@ which mne_surf2bem
mne_surf2bem --version
which mri_average
mri_average --version
set +x
37 changes: 17 additions & 20 deletions tools/github_actions_dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,27 @@
set -eo pipefail

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
ONLY_BINARY_ARG="--only-binary=numpy,scipy,matplotlib,numba,llvmlite,antio"
STD_ARGS="--progress-bar off --upgrade"
INSTALL_ARGS="-e"
if [ ! -z "$CONDA_ENV" ]; then
echo "Uninstalling MNE for CONDA_ENV=${CONDA_ENV}"
# This will fail if mne-base is not in the env (like in our minimal env, so ||true them):
echo "::group::Uninstalling MNE"
conda remove -c conda-forge --force -yq mne-base || true
python -m pip uninstall -y mne || true
conda remove -c conda-forge --force -y mne-base
echo "::endgroup::"
# If using bare environment.yml and not on windows, do a non-editable install
if [[ "${RUNNER_OS}" != "Windows" ]] && [[ "${CONDA_ENV}" != "environment_"* ]]; then
# If not on windows, do a non-editable install
if [[ "${CI_OS_NAME}" != "windows"* ]]; then
INSTALL_ARGS=""
fi
# If on minimal, just install testing deps
if [[ "${MNE_CI_KIND}" == "minimal" ]]; then
GROUP="test"
EXTRAS=""
STD_ARGS="--progress-bar off ${MNE_QT_BACKEND}"
echo "::group::Upgrading pip installation"
python -m pip install --upgrade pip # upgrade pip to support --group
echo "::endgroup::"
else
GROUP="test_extra"
EXTRAS="[hdf5]"
fi
GROUP="test_extra"
EXTRAS="[hdf5]"
elif [[ "${MNE_CI_KIND}" == "minimal" ]]; then
GROUP="test"
EXTRAS=""
STD_ARGS="--progress-bar off ${MNE_QT_BACKEND}"
echo "::group::Upgrading pip installation"
python -m pip install --upgrade pip setuptools
echo "::endgroup::"
elif [[ "${MNE_CI_KIND}" == "old" ]]; then
GROUP="" # group "test" already included when pylock file generated
EXTRAS=""
Expand All @@ -39,10 +35,12 @@ elif [[ "${MNE_CI_KIND}" == "old" ]]; then
elif [[ "${MNE_CI_KIND}" == "pip" ]]; then
GROUP="test_extra"
EXTRAS="[full-pyside6]"
python -m pip install --upgrade pip setuptools
else
test "${MNE_CI_KIND}" == "pip-pre"
python -m pip install $STD_ARGS pip setuptools
STD_ARGS="$STD_ARGS --pre"
${SCRIPT_DIR}/install_pre_requirements.sh || exit 1
${SCRIPT_DIR}/install_pre_requirements.sh
GROUP="test_extra"
EXTRAS=""
fi
Expand All @@ -61,6 +59,5 @@ else
echo "::group::Installing MNE in development mode using pip"
fi
set -x
python -m pip install $STD_ARGS $INSTALL_ARGS .$EXTRAS $GROUP_ARG
set +x
python -m pip install $STD_ARGS $ONLY_BINARY_ARG $INSTALL_ARGS .$EXTRAS $GROUP_ARG
echo "::endgroup::"
Loading
Loading