Skip to content

ENH: build the dev MNE wheel for JupyterLite (JupyterLite split 2/5) - #14135

Merged
larsoner merged 31 commits into
mne-tools:mainfrom
natinew77-creator:lite-wheel-build
Aug 25, 2026
Merged

ENH: build the dev MNE wheel for JupyterLite (JupyterLite split 2/5)#14135
larsoner merged 31 commits into
mne-tools:mainfrom
natinew77-creator:lite-wheel-build

Conversation

@natinew77-creator

@natinew77-creator natinew77-creator commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Part 2 of the split of #13925. Part 1 is #14128.

Adds doc/sphinxext/build_lite_wheel.py and a jupyterlite_wheel target that every make html* depends on, so the wheel is built once before Sphinx with no CircleCI change. The piplite addon picks wheels up from doc/pypi, so the browser kernel installs the MNE the surrounding pages are built from rather than the last release on PyPI.

Also moves the browser to Pyodide 314. jupyterlite-sphinx used to cap jupyterlite-core below 0.8, which held the kernel on Pyodide 0.29.3 and its matplotlib 3.8.4, just under the 3.9 MNE declares. 0.23.0 raised that cap to < 0.9, so the two floors now sit in the doc dependency group in pyproject.toml and tools/circleci_uv_overrides.txt is untouched. Pyodide 314 ships matplotlib 3.10.8, scipy 1.18.0 and numpy 2.4.3, all of which satisfy MNE, so the wheel is built from pyproject.toml as it stands with no version patching at all.

Nothing installs the wheel yet. The Sphinx wiring follows in the next PR along with the list of pages that get an "Open in JupyterLite" badge, so badges do not land on pages that cannot run in the browser.

Checked on #13925 before landing it here: a full build is green with every page executed and no sphinx warnings, and the browser specific paths and the pandas 3.0 ones were run by hand.

Adds a script that builds MNE as 9999.0.1 into doc/pypi, where the
jupyterlite-pyodide-kernel piplite addon picks it up, and the CircleCI step
that runs it once before Sphinx.
@natinew77-creator

Copy link
Copy Markdown
Contributor Author

@teonbrooks PR 2 of the split is up. Thanks!

@teonbrooks

Copy link
Copy Markdown
Member

I noticed that the scipy and matplotlib packages should be compatible with MNE https://pyodide.org/en/stable/usage/packages-in-pyodide.html

do you know what version of Pyodide is being used? it may be that we need to bump the version of jupyterlite, which in terms bumps pyodide-kernel. it looks like the latest version of pyodide-kernel uses the 314 version of pyodide, which is built on 3.14 Python
https://github.com/jupyterlite/pyodide-kernel

Pyodide 0.29.3 already ships scipy 1.14.1 and numpy 2.2.5, which satisfy MNE.
Only matplotlib 3.8.4 falls short, so relax that bound and leave the rest.
@natinew77-creator

Copy link
Copy Markdown
Contributor Author

I noticed that the scipy and matplotlib packages should be compatible with MNE https://pyodide.org/en/stable/usage/packages-in-pyodide.html

do you know what version of Pyodide is being used? it may be that we need to bump the version of jupyterlite, which in terms bumps pyodide-kernel. it looks like the latest version of pyodide-kernel uses the 314 version of pyodide, which is built on 3.14 Python https://github.com/jupyterlite/pyodide-kernel

Thanks for flagging. We're on Pyodide 0.29.3 (Python 3.13.2), from
jupyterlite-pyodide-kernel 0.7.2.
It ships scipy 1.14.1 and numpy 2.2.5, both fine for MNE, and
matplotlib 3.8.4, just under 3.9. So you're right on scipy, it never
needed relaxing. Dropped that line, kept matplotlib.

I did try the bump. It builds and loads Pyodide 314.0.1, where
matplotlib is 3.10.8. Since #13925 was verified against 0.29.3
throughout, I'd rather do it as a follow-up. Happy either way.

@natinew77-creator

natinew77-creator commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Tried the bump on #13925. Full build green with all pages executed
and no sphinx warnings, on Python 3.14 with the new scipy, numpy and
matplotlib. Checked the pandas 3.0 paths and the browser specific
ones. I'll move the override into this PR and drop the matplotlib line.

Overrides jupyterlite-sphinx's jupyterlite-core cap so the docs build picks up
pyodide-kernel 0.8.2. Its matplotlib, scipy and numpy all clear MNE's minimums,
so the wheel build no longer patches pyproject.toml at all.
natinew77-creator added a commit to natinew77-creator/mne-python that referenced this pull request Aug 8, 2026
Same content as the PR 2 branch so the two do not conflict when it merges.
Drops the pyproject patching, which Pyodide 314 makes unnecessary.
@natinew77-creator natinew77-creator changed the title ENH: build the dev MNE wheel for JupyterLite (JupyterLite split 2/5) ENH: build the dev MNE wheel for JupyterLite (JupyterLite split 2/4) Aug 8, 2026
@natinew77-creator natinew77-creator changed the title ENH: build the dev MNE wheel for JupyterLite (JupyterLite split 2/4) ENH: build the dev MNE wheel for JupyterLite (JupyterLite split 2/5) Aug 11, 2026
@natinew77-creator
natinew77-creator marked this pull request as ready for review August 11, 2026 13:47
jupyterlite-sphinx 0.23.0 raised its jupyterlite-core cap to < 0.9, so the
resolution reaches Pyodide 314 without help now. The overrides stay as a floor
against falling back to the old kernel, which the comment now says instead.
The 1.17.1 figure came from an early 314.0.1 probe. The 314.0.4 lockfile,
which is what the pinned kernel resolves to, has scipy 1.18.0. Still above
MNE's 1.14 floor, so nothing else changes.

@teonbrooks teonbrooks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added some comment. overall it looks good

Comment thread doc/sphinxext/build_lite_wheel.py Outdated
Comment thread doc/sphinxext/build_lite_wheel.py Outdated
Comment thread doc/sphinxext/build_lite_wheel.py Outdated
Comment thread doc/sphinxext/build_lite_wheel.py Outdated
Comment thread doc/sphinxext/build_lite_wheel.py
Switches to pathlib, which drops the glob import entirely rather than
just narrowing it. The clean step stays, but the comment now says what it
actually does: the version is pinned, so the filename is constant and
wheels never piled up. The point is that the piplite index holds this
build's wheel and nothing else. The failure now names the PyPI release
the browser would otherwise fall back to.

@teonbrooks teonbrooks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. minor some minor suggestions. once those land, then it'll lgtm

Comment thread doc/sphinxext/build_lite_wheel.py Outdated
Comment thread doc/sphinxext/build_lite_wheel.py Outdated
Comment thread doc/sphinxext/build_lite_wheel.py Outdated
Comment thread pyproject.toml Outdated
@larsoner

Copy link
Copy Markdown
Member

Sorry to come late to this PR, but I think a simpler scheme would be:

  1. Add a tools/dev/build_jupyterlite_wheel.sh. This script is only ~6 lines, it 1) checks for doc/pypy/*.whl, short circuiting if one is found. If it's not found, runs python -m pip wheel ...
  2. Modify doc/Makefile so that make html* variants all depend on a new target jupyterlite_wheel that executes ../tools/dev/build_jupyterlite_wheel.sh

I don't think we should need all the version checking etc. .circleci shouldn't need any changes since it calls make html<something>. No need for SETUPTOOLS_SCM_PRETEND_VERSION either I think -- the version should resolve fine when built in CircleCI (both dev versions and stable ones).

But I could be missing something here with this simpler design, thoughts?

@natinew77-creator

Copy link
Copy Markdown
Contributor Author

Sorry to come late to this PR, but I think a simpler scheme would be:

  1. Add a tools/dev/build_jupyterlite_wheel.sh. This script is only ~6 lines, it 1) checks for doc/pypy/*.whl, short circuiting if one is found. If it's not found, runs python -m pip wheel ...
  2. Modify doc/Makefile so that make html* variants all depend on a new target jupyterlite_wheel that executes ../tools/dev/build_jupyterlite_wheel.sh

I don't think we should need all the version checking etc. .circleci shouldn't need any changes since it calls make html<something>. No need for SETUPTOOLS_SCM_PRETEND_VERSION either I think -- the version should resolve fine when built in CircleCI (both dev versions and stable ones).

But I could be missing something here with this simpler design, thoughts?

Not missing anything, you're right on both counts.

SETUPTOOLS_SCM_PRETEND_VERSION is gone. I'd assumed a .dev version would lose to the stable release on PyPI, but piplite returns as soon as it finds the package in the local index and never consults PyPI. Built it unpinned to confirm: mne-1.13.0.dev299+g8926cd4f0, resolves fine.

.circleci is untouched now, identical to main. circleci_download.sh only ever writes html-memory or html-pattern-memory, and both go through the new jupyterlite_wheel target.

I kept it as Python rather than shell for one reason: Teon asked for the error to name the PyPI version the browser would fall back to, which needs the metadata lookup. It's behind a make target now and short-circuits on an existing wheel as you suggested. Happy to go further if you'd still prefer the script.

@larsoner larsoner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay LGTM, marking for merge-when-green. Thanks in advance @natinew77-creator !

@larsoner
larsoner enabled auto-merge (squash) August 25, 2026 11:23
@larsoner
larsoner merged commit 93145a3 into mne-tools:main Aug 25, 2026
31 checks passed
@teonbrooks

Copy link
Copy Markdown
Member

thanks @natinew77-creator!

@natinew77-creator

Copy link
Copy Markdown
Contributor Author

Okay LGTM, marking for merge-when-green. Thanks in advance @natinew77-creator !

You're welcome, and thank you for the review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants