Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
de70d2f
ENH: Add JupyterLite GitHub Actions workflow
natinew77-creator May 27, 2026
e4e3e5f
FIX: Install jupyter-server for jupyterlite build
natinew77-creator May 27, 2026
7c382d4
Merge upstream main to fix out-of-date branch
natinew77-creator May 27, 2026
9900ee7
FIX: Add towncrier changelog and fix yamllint truthy error
natinew77-creator May 27, 2026
0af3e0a
FIX: Address pre-commit style and security checks
natinew77-creator May 27, 2026
8cba9a0
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator May 27, 2026
f1544c4
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator May 27, 2026
df8656d
ENH: Integrate jupyterlite-sphinx for examples
natinew77-creator Jun 11, 2026
cc8b6e0
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator Jun 11, 2026
89072af
MAINT: explicitly import mne.viz.utils in jupyterlite cell to prevent…
natinew77-creator Jun 11, 2026
f5bbad2
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator Jun 12, 2026
325d5a1
MAINT: fix pyodide_plt_show argument signature to accept multiple pos…
natinew77-creator Jun 12, 2026
241e67e
ENH: Patch pooch and MNEBrowseFigure for JupyterLite compatibility
natinew77-creator Jun 15, 2026
1e40137
MAINT: Fix ruff E501 line too long in doc/conf.py jupyterlite setup
natinew77-creator Jun 15, 2026
173e129
MAINT: Hotfix jupyterlite contents so notebooks are copied to build
natinew77-creator Jun 15, 2026
eb18fde
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator Jun 15, 2026
25a3818
MAINT: Add .gitkeep to jupyterlite_contents to fix sphinx race condition
natinew77-creator Jun 15, 2026
f521571
FIX: Ensure jupyterlite_sphinx runs after sphinx_gallery in build-fin…
natinew77-creator Jun 15, 2026
1dd9232
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator Jun 15, 2026
14fd683
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator Jun 15, 2026
e275e48
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator Jun 15, 2026
e9d6142
MAINT: Build local wheel for JupyterLite environments to fix PyPI out…
natinew77-creator Jun 18, 2026
6eb96f0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 18, 2026
b008ce4
Merge branch 'main' into jupyterlite-gh-actions
natinew77-creator Jun 18, 2026
60ac122
FIX: Restore accidentally broken meas_info.py and fix conf.py ruff li…
natinew77-creator Jun 18, 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: 46 additions & 0 deletions .github/workflows/jupyterlite.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Build JupyterLite

on: # yamllint disable-line rule:truthy
push:
branches:
- jupyterlite-gh-actions

permissions:
contents: read

jobs:
build:
name: Build JupyterLite Site
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install JupyterLite & Build Tools
run: |
python -m pip install --upgrade pip
pip install jupyterlite-core jupyterlite-pyodide-kernel build jupyter-server

- name: Build MNE-Python Wheel
run: |
python -m build --wheel
mkdir -p lite-wheels
cp dist/*.whl lite-wheels/

- name: Build JupyterLite Site
# We pass the local wheel to JupyterLite so the browser environment uses the exact code from this branch!
run: |
jupyter lite build --contents examples/ --output-dir dist_lite/ --piplite-wheel lite-wheels/*.whl

- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: jupyterlite-build
path: dist_lite/
1 change: 1 addition & 0 deletions doc/changes/dev/13925.newfeature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a JupyterLite GitHub Actions workflow to automatically build a Wasm-compatible interactive documentation site by Natneal Belete.
88 changes: 86 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@
# contrib
"matplotlib.sphinxext.plot_directive",
"numpydoc",
"sphinxcontrib.bibtex",
"sphinx_gallery.gen_gallery",
"jupyterlite_sphinx",
"sphinx_copybutton",
"sphinx_design",
"sphinx_gallery.gen_gallery",
"sphinxcontrib.bibtex",
"sphinxcontrib.youtube",
"sphinxcontrib.towncrier.ext",
# homegrown
Expand Down Expand Up @@ -472,7 +473,90 @@
compress_images = ()

sphinx_gallery_parallel = int(os.getenv("MNE_DOC_BUILD_N_JOBS", "1"))
jupyterlite_contents = ["jupyterlite_contents"]
jupyterlite_bind_ipynb_suffix = False

# Build the local MNE wheel so JupyterLite can use the current development version
dist_lite_dir = os.path.join(
os.path.abspath(os.path.dirname(__file__)), "_build", "dist_lite"
)
os.makedirs(dist_lite_dir, exist_ok=True)
subprocess.run(
[sys.executable, "-m", "pip", "wheel", "..", "--no-deps", "-w", dist_lite_dir],
check=True,
)

jupyterlite_build_command_options = {"piplite-wheels": dist_lite_dir}

sphinx_gallery_conf = {
"jupyterlite": {
"use_jupyter_lab": True,
"jupyterlite_contents": "jupyterlite_contents",
},
"first_notebook_cell": (
"# 💡 This cell is automatically added to the start of each notebook.\n"
"import piplite\n"
"await piplite.install(['mne'])\n"
"\n"
"# Mock lzma since it is missing in Pyodide but required by pooch\n"
"import sys\n"
"import types\n"
"if 'lzma' not in sys.modules:\n"
" sys.modules['lzma'] = types.ModuleType('lzma')\n"
"\n"
"# 1. Patch networking so pooch can download datasets\n"
"import pooch\n"
"import requests\n"
"import urllib.request\n"
"import urllib.error\n"
"import io\n"
"\n"
"orig_send = requests.Session.send\n"
"def pyodide_send(self, request, **kwargs):\n"
" try:\n"
" resp = urllib.request.urlopen(request.url)\n"
" content = resp.read()\n"
" status = resp.status\n"
" except urllib.error.HTTPError as e:\n"
" content = e.read()\n"
" status = e.code\n"
" except Exception:\n"
" return orig_send(self, request, **kwargs)\n"
" response = requests.Response()\n"
" response.status_code = status\n"
" response.url = request.url\n"
" response.raw = io.BytesIO(content)\n"
" return response\n"
"requests.Session.send = pyodide_send\n"
"\n"
"# Intercept pooch to provide helpful errors for large OSF datasets\n"
"orig_pooch_fetch = pooch.Pooch.fetch\n"
"def pyodide_pooch_fetch(self, fname, processor=None, downloader=None):\n"
" url = self.get_url(fname)\n"
" if 'osf.io' in url or 'files.osf.io' in url:\n"
" raise RuntimeError(\n"
" f'Cannot download {fname} natively in JupyterLite '\n"
" 'due to browser CORS restrictions on OSF and '\n"
" 'memory limits. Please download the dataset locally '\n"
" 'and upload it into the JupyterLite file browser.'\n"
" )\n"
" return orig_pooch_fetch(\n"
" self, fname, processor=processor, downloader=downloader\n"
" )\n"
"pooch.Pooch.fetch = pyodide_pooch_fetch\n"
"\n"
"# 2. Patch MNEBrowseFigure to auto-display in Pyodide's inline backend\n"
"import mne\n"
"import matplotlib.pyplot as plt\n"
"import importlib\n"
"viz_utils = importlib.import_module('mne.viz.utils')\n"
"orig_plt_show = viz_utils.plt_show\n"
"def pyodide_plt_show(fig=None, **kwargs):\n"
" orig_plt_show(fig, **kwargs)\n"
" import IPython.display\n"
" IPython.display.display(plt.gcf())\n"
"viz_utils.plt_show = pyodide_plt_show\n"
),
"doc_module": ("mne",),
"reference_url": dict(mne=None),
"examples_dirs": examples_dirs,
Expand Down
Empty file.
16 changes: 0 additions & 16 deletions mne/_fiff/meas_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -1298,22 +1298,6 @@ class Info(ValidatedDict, SetChannelsMixin, MontageMixin, ContainsMixin):
modified by various MNE-Python functions or methods (which have
safeguards to ensure all fields remain in sync).

Some common methods that safely modify the ``info`` object include:

* :meth:`mne.io.Raw.add_proj`, :meth:`mne.Epochs.add_proj`,
:meth:`mne.Evoked.add_proj`
* :meth:`mne.io.Raw.del_proj`, :meth:`mne.Epochs.del_proj`,
:meth:`mne.Evoked.del_proj`
* :meth:`mne.io.Raw.rename_channels`,
:meth:`mne.Epochs.rename_channels`,
:meth:`mne.Evoked.rename_channels`
* :meth:`mne.io.Raw.set_channel_types`,
:meth:`mne.Epochs.set_channel_types`,
:meth:`mne.Evoked.set_channel_types`
* :meth:`mne.io.Raw.set_meas_date`,
:meth:`mne.Epochs.set_meas_date`,
:meth:`mne.Evoked.set_meas_date`

Parameters
----------
*args : list
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ doc = [
"graphviz",
"intersphinx_registry >= 0.2405.27",
"ipython != 8.7.0", # also in "full-no-qt" and "test"
"jupyterlite-pyodide-kernel",
"jupyterlite-sphinx",
"memory_profiler >= 0.16",
"mne-bids",
"mne-connectivity",
Expand Down
Loading