From 7d28cac861118cae743517fd594e9244e6796165 Mon Sep 17 00:00:00 2001 From: "mne[bot]" <50266005+mne-bot@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:07:02 +0000 Subject: [PATCH 1/3] mne[bot]: Update pre-commit hook versions --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 28247f9ed9c..8dd9d5b3d36 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: # ty (type checking); deps installed by pre-commit(.ci), see [tool.ty] in # pyproject.toml for the checked modules and silenced rules - repo: https://github.com/astral-sh/ty-pre-commit - rev: v0.0.78 + rev: v0.0.79 hooks: - id: ty additional_dependencies: @@ -98,7 +98,7 @@ repos: # zizmor - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.30.0 + rev: v1.30.1 hooks: - id: zizmor args: [--fix] From fc46d2794d5f2a43c44ffa31e3e7afbbaeab25d4 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Wed, 9 Sep 2026 08:14:02 -0400 Subject: [PATCH 2/3] Fix caching --- .circleci/config.yml | 4 ++-- mne/datasets/utils.py | 4 +++- tools/circleci_download.sh | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 64baa19e79d..f882f3edc25 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -176,7 +176,7 @@ jobs: # Load tiny cache so that ~/.mne does not need to be created below - restore_cache: keys: - - data-cache-tiny-v1-{{ checksum "misc_version.txt" }}-{{ checksum "cache_keys/tiny.txt" }} + - data-cache-tiny-v2-{{ checksum "misc_version.txt" }}-{{ checksum "cache_keys/tiny.txt" }} # Look at what we have and fail early if there is some library conflict - run: @@ -300,7 +300,7 @@ jobs: condition: *full_build steps: - save_cache: - key: data-cache-tiny-v1-{{ checksum "misc_version.txt" }}-{{ checksum "cache_keys/tiny.txt" }} # the small ones, combined + key: data-cache-tiny-v2-{{ checksum "misc_version.txt" }}-{{ checksum "cache_keys/tiny.txt" }} # the small ones, combined paths: - ~/.mne - ~/mne_data/MNE-kiloword-data # (28 M) diff --git a/mne/datasets/utils.py b/mne/datasets/utils.py index a744af9c9ee..bef7102ecad 100644 --- a/mne/datasets/utils.py +++ b/mne/datasets/utils.py @@ -368,8 +368,10 @@ def _download_all_example_data(verbose=True): ) from .erp_core import fetch_file as fetch_erp_core_file - eegbci.load_data(subjects=1, runs=[6, 10, 14], update_path=True) + # keep in sync with the eegbci.load_data calls in examples/ and tutorials/ + eegbci.load_data(subjects=range(1, 11), runs=[1], update_path=True) eegbci.load_data(subjects=range(1, 5), runs=[3], update_path=True) + eegbci.load_data(subjects=1, runs=[2, 6, 10, 14], update_path=True) logger.info("[done eegbci]") fetch_erp_core_file("sub-001/eeg/sub-001_task-N170_eeg.fdt") diff --git a/tools/circleci_download.sh b/tools/circleci_download.sh index c2b01c2140e..ae4efbd2327 100755 --- a/tools/circleci_download.sh +++ b/tools/circleci_download.sh @@ -30,7 +30,7 @@ else hcp_mmp_parcellation) python -c "import mne; print(mne.datasets.fetch_hcp_mmp_parcellation(subjects_dir=mne.datasets.sample.data_path() / 'subjects', accept=True))";; eegbci) - python -c "import mne; print([mne.datasets.eegbci.load_data(subject, runs, update_path=True) for subject, runs in [(1, [3, 6, 10, 14]), (2, [3]), (3, [3]), (4, [3])]])";; + python -c "import mne; print([mne.datasets.eegbci.load_data(subjects, runs, update_path=True) for subjects, runs in [(range(1, 11), [1]), (range(1, 5), [3]), (1, [2, 6, 10, 14])]])";; sleep_physionet) python -c "import mne; print(mne.datasets.sleep_physionet.age.fetch_data([0, 1], recording=[1]))";; bst_*) From fa5304c2fa87e635e4d2cde09bf1a96be83a5b57 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Wed, 9 Sep 2026 08:20:45 -0400 Subject: [PATCH 3/3] Fix credit --- doc/sphinxext/credit_tools.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/doc/sphinxext/credit_tools.py b/doc/sphinxext/credit_tools.py index 116810bbcd5..7d61d161da1 100644 --- a/doc/sphinxext/credit_tools.py +++ b/doc/sphinxext/credit_tools.py @@ -23,6 +23,10 @@ adds one pointing at the contributor's GitHub profile where we know it; anything left over is an error, since the badge would have nowhere to point. +Errors are reported rather than raised when running with ``--report`` (again, +the monthly action), so that its PR still opens with them in the body for a +maintainer to fix there; the doc build then fails on them until they are. + Two names that look like the same person are also an error: it usually means an address is missing from .mailmap, so someone is credited twice under slightly different spellings. Genuinely distinct people go in DISTINCT_NAMES below. @@ -396,14 +400,15 @@ def generate_credit_rst( stats, commits, ignores, unresolved, logins = _load_pr_stats(mailmap) else: added = [] + errors = [] problems = _report_problems(mailmap, unresolved) if problems: - raise RuntimeError(problems) + errors.append(problems) all_names = {name for these in stats.values() for name in these} duplicates = _similar_names(all_names) if duplicates: - raise RuntimeError( + errors.append( f"{len(duplicates)} possible duplicate contributor(s):\n" + "\n".join(duplicates) ) @@ -426,7 +431,7 @@ def generate_credit_rst( urls = _load_names_inc() missing_anchors = _check_names_inc(all_names, urls) if missing_anchors: - raise RuntimeError( + errors.append( f"{len(missing_anchors)} credited name(s) have no link in " "doc/changes/names.inc, which the code credit page needs to link " "their badge. Add a line for each of them (the file is sorted " @@ -436,7 +441,15 @@ def generate_credit_rst( + "\n".join(f".. _{name}: https://..." for name in missing_anchors) ) if report_file is not None: - _write_report(report_file, added, anchors_added) + _write_report(report_file, added, anchors_added, errors) + if errors: + # --report means the credit action is running: let it open its PR with + # the problems in the body and leave the failure to the doc build + for error in errors: + sphinx_logger.warning(error) + if report_file is None: + raise RuntimeError("\n\n".join(errors)) + return logger.info("Biggest included commits/PRs:") biggest = sorted(commits, key=lambda key: commits[key], reverse=True) @@ -510,9 +523,19 @@ def _github_website(login): return website or None -def _write_report(report_file, added, anchors_added): +def _write_report(report_file, added, anchors_added, errors): """Write a Markdown summary for the credit GitHub Action's PR body.""" lines = ["## Contributor name resolution", ""] + if errors: + lines += [ + "> [!IMPORTANT]", + "> The doc build will fail until these are fixed in this PR:", + "", + "```", + *"\n\n".join(errors).splitlines(), + "```", + "", + ] if added: lines += [ f"{len(added)} new contributor(s) were added to `.mailmap`, named " @@ -529,7 +552,7 @@ def _write_report(report_file, added, anchors_added): if website is not None: links.append(f"[website]({website})") lines.append(f"- `{un.mailmap_entry}` — {', '.join(links)}") - else: + elif not errors: lines += ["All contributor names resolved cleanly."] if anchors_added: lines += [