Skip to content

ENH: Add JupyterLite CI/CD infrastructure#13925

Draft
natinew77-creator wants to merge 21 commits into
mne-tools:mainfrom
natinew77-creator:jupyterlite-gh-actions
Draft

ENH: Add JupyterLite CI/CD infrastructure#13925
natinew77-creator wants to merge 21 commits into
mne-tools:mainfrom
natinew77-creator:jupyterlite-gh-actions

Conversation

@natinew77-creator

@natinew77-creator natinew77-creator commented May 27, 2026

Copy link
Copy Markdown
Contributor

Tracking Issue: #13929

What does this implement/fix?
This PR integrates JupyterLite into the MNE-Python documentation build, allowing users to run tutorials interactively directly in their browser without a local Python environment.

Key technical implementations:

  • Integrates jupyterlite-sphinx into the Sphinx-Gallery pipeline, automatically generating "Try in JupyterLite" buttons for tutorials and examples.
  • Injects a hidden setup cell into the generated notebooks via conf.py to automatically handle Pyodide-specific browser quirks:
    • Installs mne and pyodide-http natively via micropip.
    • Patches Pyodide networking (pyodide_http.patch_all()) so MNE's pooch downloader can successfully fetch datasets from the browser.
    • Monkey-patches mne.viz.utils.plt_show to correctly render MNE's Matplotlib figures inline within the WebAssembly environment.

Additional information

  • This represents the completion of the first major GSoC milestone.
  • CircleCI will now automatically build the JupyterLite assets and provide a live preview link in the CI checks.
  • Note on limitations: During testing, I identified two architectural edge cases for future discussion: browser RAM limitations when tutorials attempt to download massive (>1GB) datasets, and occasional PyPI vs. main branch version mismatches since JupyterLite currently pulls the stable MNE release.
A28CDACE-D867-491E-8B11-013DD1635D4A 16D95C3F-B372-47D1-AFE3-D5E10395F775 0F9F0048-D585-4B8C-BE90-1E4D34BF1EEF

@natinew77-creator natinew77-creator marked this pull request as draft May 27, 2026 15:03
@natinew77-creator

natinew77-creator commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Hi @teonbrooks, Status Update: This PR is now ready for your review!

As the first step in my GSoC roadmap, this PR successfully introduces the core JupyterLite infrastructure to the MNE-Python documentation. Here is what has been achieved:

  • Integrated jupyterlite-sphinx to automatically build interactive JupyterLite instances for the examples/tutorials.
  • Added a GitHub Actions CI/CD workflow to build and deploy the JupyterLite site.
  • Patched MNEBrowseFigure by fixing the pyodide_plt_show argument signature to accept multiple positional arguments.

I also looked deeply into the [Errno 26] Operation in progress error we hit during the 10_overview tutorial. It turns out this is a fundamental limitation with Pyodide and JupyterLite. The 10_overview tutorial uses mne.datasets.sample.data_path() to download a 1.45 GB dataset from osf.io. First, osf.io has strict CORS headers that completely block browser-based WebAssembly fetches. Second, even if we were able to bypass the CORS restrictions, downloading a 1.45 GB file directly into browser RAM via Pyodide causes the browser tab to instantly crash with an Out-Of-Memory error.

To gracefully handle this and prevent user confusion, I've written a custom pooch.Pooch.fetch interceptor in our doc/conf.py configuration. Now, whenever a JupyterLite user tries to download these massive OSF datasets natively in the browser, it intercepts the request and prints a polite error message advising them to download the dataset locally and upload it directly into the JupyterLite file browser!

For smaller datasets that are CORS-friendly, it automatically falls back to Pyodide's native pyfetch via urllib so they work seamlessly without any patching needed in the tutorial code itself.

(Note: The ubuntu-latest and mne-tools.mne-python test matrix CI jobs are currently failing, but this is entirely unrelated to this PR. They are failing due to a global repository issue where the newly released pytest 9.1.0 is raising a "duplicate parametrization of 'epochs_to_split'" syntax error in mne/tests/test_epochs.py).

I think this is the best architectural approach for handling the massive tutorials. I'm ready to mark this PR as complete so we can move down the GSoC checklist and start tackling xeus-python and the 3D PyVista rendering! Let me know what you think! Looking forward to your feedback!

@natinew77-creator

Copy link
Copy Markdown
Contributor Author

Quick Follow-up:
I also tracked down and fixed the bug that prevented the notebooks from loading correctly in the JupyterLite UI.

It turned out to be a race condition during the Sphinx build-finished event—jupyterlite_sphinx was executing before sphinx_gallery had finished generating the example notebooks. I've reordered the extensions in conf.py so they execute in the correct sequence, and all the notebooks are now successfully populating!

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.

1 participant