Skip to content

Run the harness headlessly for plotly and matplotlib; un-exclude 001170 - #209

Merged
bendichter merged 1 commit into
masterfrom
reimerlab-headless-plotly
Aug 23, 2026
Merged

Run the harness headlessly for plotly and matplotlib; un-exclude 001170#209
bendichter merged 1 commit into
masterfrom
reimerlab-headless-plotly

Conversation

@bendichter

Copy link
Copy Markdown
Member

001170/ReimerLab/public_demo/001170_demo.ipynb has been excluded from CI with this note:

# Calls webbrowser.open(), which raises "could not locate runnable browser"
# in headless CI. Works in Colab.

It never calls webbrowser.open. What it does is build a plotly express figure and call fig.show(). Outside a Jupyter kernel, plotly resolves its default renderer to browser, and that renderer is what calls webbrowser.open:

plain python default:     'browser'
terminal ipython default: 'browser'

Matplotlib has the same shape of problem pointing the other way. On a machine with a display it selects a GUI backend, so running the harness locally opens plot windows; on a Linux runner it falls back to Agg by itself, which is why CI never showed it.

Neither is a property of a notebook, so both are fixed in the harness rather than in notebook content. run_notebook.py now sets PLOTLY_RENDERER=json and MPLBACKEND=Agg for the ipython subprocess it launches, with both respecting an existing value from the environment. The kernel path added in #205 is deliberately untouched, since Colab and JupyterLab inside the notebook image select inline rendering on their own and the executed PR previews need their figures. Any future notebook that uses plotly gets this for free.

What that unblocks

With the harness fixed, the notebook runs headlessly, so its exclusion is removed. It is the only notebook in the repo that carried a Colab badge but no image, and it now gets both. It also picks up two things it was missing:

  • a requirements.in, which the submission contract expects and which the directory did not have (it still carries an environment.yml from before the contract). Re-locking against it moves the notebook onto the 3.13 pin set; its install cell header still said Python 3.12, since the Re-lock every notebook for Colab's Python 3.13 runtime #206 sweep only covered notebooks that were not excluded.
  • a remfile.DiskCache, matching the other notebooks that read one file repeatedly.

Verification

Run through the CI harness on Python 3.13, in the same fresh-environment mode CI uses: green, and 43 s against 826 s before the disk cache, since the notebook reads overlapping regions of the same file for each of its plots.

🤖 Generated with Claude Code

https://claude.ai/code/session_011NuStoQykizhQCx2KBrMCN

The ReimerLab notebook was excluded from CI with the note that it calls
webbrowser.open. It does not: it builds a plotly express figure and
calls fig.show(), and outside a Jupyter kernel plotly resolves its
default renderer to "browser", which is what reaches webbrowser.open and
raises on a headless runner. Matplotlib has the same shape of problem in
the other direction: on a machine with a display it picks a GUI backend,
so running the harness locally opens plot windows that CI never sees.

Both are properties of the environment rather than of any notebook, so
the harness now sets PLOTLY_RENDERER and MPLBACKEND for the ipython path
it controls. Colab and JupyterLab inside the notebook image run a real
kernel, which selects inline rendering for both by itself, and the
kernel path used for PR previews is deliberately left alone so its
figures still appear in the executed copy.

With that, the notebook runs headlessly, so its exclusion is removed and
it gains a container image. It also gets the requirements.in the
submission contract expects, which re-locks it onto the 3.13 pin set,
and streams through a remfile.DiskCache like the other notebooks that
read one file repeatedly. Verified locally on Python 3.13: it now runs
in 43 s, where before the cache it took 826 s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011NuStoQykizhQCx2KBrMCN
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Preview for this PR has been removed (PR closed).

github-actions Bot added a commit that referenced this pull request Aug 23, 2026
github-actions Bot added a commit that referenced this pull request Aug 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Executed notebooks

CI executes the notebooks changed in this PR through a Jupyter kernel and publishes each one, with its outputs, as soon as it finishes. Links appear below as notebooks complete; an hourglass means the notebook is still running.

1 of 1 finished. Commit 584f3ee. The executed copies live only in the preview and are removed when the PR closes; nothing is committed to the branch.

@bendichter
bendichter merged commit 088cc87 into master Aug 23, 2026
6 checks passed
github-actions Bot added a commit that referenced this pull request Aug 23, 2026
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