Skip to content

Add ndi.update: check for and install a newer NDI-python (mirrors NDI-matlab#1038) - #337

Merged
stevevanhooser merged 4 commits into
mainfrom
claude/amazing-clarke-a34o5c
Oct 18, 2026
Merged

stevevanhooser merged 4 commits into
mainfrom
claude/amazing-clarke-a34o5c

Conversation

@stevevanhooser

@stevevanhooser stevevanhooser commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds the NDI-python half of VH-Lab/NDI-matlab#1038 (merged): checking for and installing a newer NDI-python. NDI-python has no releases, so every kind of install is compared with the latest commit on main.

ndi.update (new package, MATLAB names):

  • check():
    • Git clones: git fetch origin main, then the commits behind and ahead. It also checks the clones ndi_install.py makes in ~/.ndi/tools, and records the user's own changed files, new files and local commits (Modifications).
    • Installer installs: compares the commit in ~/.ndi/install.json with main through GitHub's compare API. If the receipt has no commit, it counts the commits made since the install time.
    • pip installs: reported as "unknown".
    • The result is a dict with MATLAB's field names.
  • install():
    • Refuses a clone that is not on main.
    • Lists the user's own changes and asks before touching them, with No as the default. With Confirm=False it raises UpdateError unless AllowModified=True.
    • Git clones: git pull --ff-only (changed files are stashed and restored), then ndi_install.py --update.
    • Installer installs: re-runs the NDI installer. On Windows it runs in its own window and starts after NDI exits, because a running ndi.exe can't be replaced.
    • Clears caches afterwards.
  • Also modificationSummary, installType and checkOnStartup.
  • git is never allowed to wait for input: empty stdin, no credential prompt, no pager or editor.

Installer (install-ndi.sh / install-ndi.ps1):

  • Asks GitHub which commit main is at, installs exactly that commit's archive, and records it with the install time in ~/.ndi/install.json.
  • If GitHub's API can't be reached, it installs main as before and records "commit": null.
  • --uninstall removes the receipt.
  • NDI-matlab's ndi.update.checkPython reads the same file.
  • installer.yml gains a step checking that ndi.update reads the receipt from a real install.

Elsewhere:

  • New terminal commands: ndi update and ndi update --check [--json].
  • An Update button in the navigator's NDI pane. The dialog decisions are in a pure update_dialog(), so they're tested without Qt.
  • The navigator runs the once-a-day check on a background thread when it opens. Importing ndi never touches the network.
  • Preferences: Update.CheckOnStartup and Update.CheckIntervalDays use the same keys as NDI-matlab, so one setting covers both. Update.Python.LastCheckTime is separate from MATLAB's Update.MATLAB.LastCheckTime, so a check in one language doesn't postpone the other's.
  • Symmetry test change: the preferences read-artifacts test no longer expects keys in a Python subcategory to appear in MATLAB's file. They're Python's own by design. Every other key is still checked, and Python's own file must still have all of its keys.
  • ndi.version() reports the receipt's commit for an installer install.

Bridge contract (please review):

  • New src/ndi/update/ndi_matlab_python_bridge.yaml:
    • check, install, installType, modificationSummary and checkOnStartup are ported.
    • checkPython, runGit and githubApi are ported_differently.
    • compareVersions, latestRelease and toolboxIdentifier are matlab_only; they concern releases and the toolbox, which NDI-python doesn't have.
  • src/ndi/update is added to the completeness guard's PACKAGES list.
  • Re-synced to NDI-matlab commits, all now on NDI-matlab main:
    • ndiPane, preferences and version: f9ced4bcd
    • checkPython: e2a3d8e57
    • runGit: 42f532167

Merge order

VH-Lab/NDI-matlab#1038 has merged, with a merge commit, so every recorded sync hash is in NDI-matlab main's history. The temporary matlab_branch markers have been removed. This PR now checks against NDI-matlab main like any other.

Testing

  • black --check and ruff check are clean.
  • pytest tests/ --ignore=tests/symmetry: 6092 passed, 609 skipped, run with NDI-matlab at the matching branch. This includes the bridge checks run in strict mode.
  • After #1038 merged, the bridge checks were re-run against NDI-matlab main, including the new +ndi/+update completeness check: 210 passed.
  • New tests:
    • tests/test_update_check_git.py (13): builds local bare repos and clones. It covers behind and ahead, dependencies, modifications, the guards, a pull plus ndi_install.py --update, and an edited file surviving the update.
    • tests/test_update_installer.py (10): uses a fake ~/.ndi and a fake GitHub API.
    • tests/test_update_misc.py (18): the summary text, the startup check, preferences, the command line, and the dialog decisions.
  • Updated test_gui_nav_pane.py for the wider pane (MATLAB's 156 pixels).
  • The symmetry fix was reproduced locally against MATLAB's preferences file as CI printed it.

Not run locally:

  • The installer scripts. sh -n passes; installer.yml exercises them in CI.
  • The Qt dialogs. CI has no Qt.

🤖 Generated with Claude Code

https://claude.ai/code/session_017Ni686VRCwcmMfvCVcLypp

Mirrors VH-Lab/NDI-matlab#1038 (branch claude/amazing-clarke-a34o5c).

ndi.update.check compares this copy with the latest commit on main:
- git clones: git fetch origin main, commits behind/ahead, the
  ~/.ndi/tools clones ndi_install.py makes, and the user's own changed
  files, new files and local commits (Modifications);
- installer installs: the commit in ~/.ndi/install.json against main via
  GitHub's compare API, or the commits since the install time;
- pip installs: reported as unknown.

ndi.update.install refuses a clone not on main, lists the user's changes
and asks (default No; with Confirm=False it errors unless AllowModified),
then pulls --ff-only with changed files stashed and restored and runs
ndi_install.py --update, or re-runs the NDI installer (on Windows in its
own window, after this process exits). Caches are cleared afterwards.
Also modificationSummary, installType and checkOnStartup.

- install-ndi.sh / .ps1 install the exact commit main is at and record
  it, with the install time, in ~/.ndi/install.json (removed by
  uninstall); NDI-matlab's ndi.update.checkPython reads the same file.
  The installer workflow checks the receipt.
- `ndi update` and `ndi update --check [--json]`.
- An Update button in the navigator's NDI pane; the dialog decisions are
  in a pure update_dialog() so they are tested without Qt.
- The navigator runs the once-a-day check on a thread when it opens.
- Preferences Update.CheckOnStartup and Update.CheckIntervalDays (shared
  with NDI-matlab) and Update.Python.LastCheckTime (NDI-matlab keeps
  Update.MATLAB.LastCheckTime).
- ndi.version() reports the receipt's commit for an installer install.
- Bridge: new src/ndi/update bridge (matlab_branch markers until the
  MATLAB branch merges); ndiPane, preferences and version re-synced.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ni686VRCwcmMfvCVcLypp
…file

The preferences read-artifacts test requires every key NDI-python
registers to be in the other language's NDI_Preferences.json.
Update.Python.LastCheckTime is deliberately per-language (NDI-matlab
keeps Update.MATLAB.LastCheckTime), so MATLAB never writes it. Keys in
a "Python" subcategory are no longer expected in matlabArtifacts; the
pythonArtifacts check still requires every key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ni686VRCwcmMfvCVcLypp
…2f532167

NDI-matlab's runGit now gives git an empty stdin and disables credential
prompts, the pager and the editor. run_git does the same, and the bridge
entry records the new commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ni686VRCwcmMfvCVcLypp
…erged

VH-Lab/NDI-matlab#1038 merged with a merge commit, so +ndi/+update is on
NDI-matlab main and every recorded sync hash (f9ced4bcd, e2a3d8e57,
42f532167) is in main's history. The eleven matlab_branch markers come
off, as section 8 of the bridge spec requires, and src/ndi/update joins
the completeness guard's PACKAGES.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ni686VRCwcmMfvCVcLypp
@stevevanhooser
stevevanhooser merged commit 50f18fe into main Oct 18, 2026
26 of 27 checks passed
@stevevanhooser
stevevanhooser deleted the claude/amazing-clarke-a34o5c branch October 18, 2026 23:38
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.

2 participants