Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

CI blind spot: interactive ipywidgets callbacks aren't exercised (slider-state bugs slip through) #441

Open

Description

Problem

CI runs notebooks via jupyter nbconvert --execute — each cell once, top-to-bottom, with no widget interaction. So bugs that only appear when a user interacts with an ipywidgets control (moves a slider), or that depend on shared global state mutated by later cells, are invisible to CI.

Concrete example (just fixed in 60_linear_algebra_2/200)

The Power Method arrow-slider callback show_iterate(step) read the global n. Cells 49/52/58 (lam, vecX, n = power_method(...)) overwrite n99999 for the non-converging "What if" matrices. After running those cells, moving the slider raised:

ValueError: shape mismatch ... (99999,) vs (2,) # ax.bar(range(99999), vec[2])

CI passed cleanly because:

  • the interact callback only fires once, at creation, when n was still correct;
  • nbconvert never moves the slider, and never re-fires the callback after n is clobbered;
  • the if os.getenv('CI'): show_iterate(last) guard renders one static frame — by design, to keep CI green — which also means the interactive path is never exercised.

(Fixed by capturing the dimension locally: dim = vec_array.shape[1], independent of the mutable global n.)

Options

  1. Convention (cheapest): widget callbacks must capture all needed state locally in their own cell, never reading mutable globals that later cells reassign. Make it a review/lint checklist item.
  2. Exercise callbacks in a test: for notebooks containing interact(...), after executing all cells, call the callback across its full slider range and assert no exception. Non-trivial to wire generically.
  3. Static check: flag a widget callback that references a module-level name reassigned elsewhere in the same notebook. Hard to do reliably (needs data-flow analysis).

Related

Same family as #440 and the "missing Colab clone cell" gap — CI executes the repo, non-interactive path, not the interactive/Colab path.

🤖 Filed via Claude Code after fixing the 200 slider crash.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        AltStyle によって変換されたページ (->オリジナル) /