Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ jobs:
python-version: "3.14"

- name: Install package with dev and ced dependencies
# The [ced] extra pulls sonpipe from its git URL. Same install as
# `python -m ndr.setup.sonpipe`; downstream packages (NDI-python) use
# the module entry point in their own CI so they don't have to know
# the git URL themselves.
# The [ced] extra pulls sonpipe from its GitHub archive URL (plain
# HTTPS, no git needed). Same install as `python -m ndr.setup.sonpipe`;
# downstream packages (NDI-python) use the module entry point in their
# own CI so they don't have to know the URL themselves.
run: pip install -e ".[dev,ced]"

- name: Verify sonpipe and sonpy are usable
Expand Down
12 changes: 9 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,17 @@ formats = [
# unconditionally would put every install of ndr behind a second repository
# and a narrow Python. Opt in with `pip install ndr[ced]`, or run
# `python -m ndr.setup.sonpipe` after installing ndr -- both land on the same
# git URL. Without either the CED reader raises SonpipeNotFoundError.
ced = ["sonpipe @ git+https://github.com/VH-Lab/sonpipe.git"]
# URL. Without either the CED reader raises SonpipeNotFoundError.
# The URL is GitHub's zip archive of sonpipe's main branch, fetched over plain
# HTTPS, rather than a git+ URL: pip and uv shell out to a system `git` for
# git+ URLs, and many end-user machines (and installers built on
# `uv tool install`) have none. Archive URLs of a branch are cached, so picking
# up a newer sonpipe needs `--upgrade --force-reinstall` (pip) or
# `--reinstall` (uv).
ced = ["sonpipe @ https://github.com/VH-Lab/sonpipe/archive/refs/heads/main.zip"]

[tool.hatch.metadata]
# The [ced] extra points at sonpipe's git URL; PEP 508 direct references
# The [ced] extra points at sonpipe's archive URL; PEP 508 direct references
# need this opt-in to appear in optional-dependencies.
allow-direct-references = true

Expand Down
3 changes: 2 additions & 1 deletion src/ndr/ndr_matlab_python_bridge.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ project_metadata:
# so the CED reader can drive CED's sonpy. Also
# available as the [ced] optional extra in
# pyproject.toml; both entry points install the
# same git URL.
# same URL (a GitHub archive zip over HTTPS,
# so no system git is needed).
#
# Not ported (MATLAB-only tooling, no Python counterpart is meaningful):
# +ndr/+docs/build.m - builds MATLAB markdown docs
Expand Down
18 changes: 15 additions & 3 deletions src/ndr/setup/sonpipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@
builds (CPython 3.14 on Linux at the time of writing). Both facts are why
this is a runtime step rather than a declared dependency, and why the same
install is also exposed as the ``[ced]`` optional extra in pyproject.toml --
that extra points at the same git URL this module installs, so which entry
point a caller uses does not change what lands.
that extra points at the same URL this module installs, so which entry
point a caller uses does not change what lands. (Keep the two strings
identical: if both forms were installed into one environment with different
URLs, pip and uv would see conflicting direct references.)

The URL is GitHub's zip archive of sonpipe's main branch rather than a
``git+`` URL, because pip and uv shell out to a system ``git`` for ``git+``
URLs and many end-user machines have none; the archive is fetched over plain
HTTPS. pip caches a branch archive, so ``--upgrade`` alone may not pick up a
newer sonpipe -- reinstall with ``pip install --upgrade --force-reinstall``.

Usage::

Expand All @@ -28,7 +36,11 @@
import subprocess
import sys

SONPIPE_GIT_URL = "sonpipe @ git+https://github.com/VH-Lab/sonpipe.git"
# Historical name: this was once a git+ URL. It is now a plain-HTTPS archive
# URL so that installing sonpipe does not need git; the name is kept because
# callers (tests, downstream code) import it. Must match the [ced] extra in
# pyproject.toml exactly.
SONPIPE_GIT_URL = "sonpipe @ https://github.com/VH-Lab/sonpipe/archive/refs/heads/main.zip"


class SonpipeInstallError(RuntimeError):
Expand Down
20 changes: 19 additions & 1 deletion tests/test_setup_sonpipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

from __future__ import annotations

import re
import subprocess
import sys
from pathlib import Path
from unittest import mock

import pytest
Expand All @@ -18,7 +20,7 @@


class TestInstall:
def test_invokes_pip_with_the_git_url(self, monkeypatch):
def test_invokes_pip_with_the_sonpipe_url(self, monkeypatch):
seen: dict[str, object] = {}

def fake_run(argv, **kwargs):
Expand Down Expand Up @@ -55,6 +57,22 @@ def fake_run(argv, **kwargs):
setup_sonpipe.install()


class TestUrl:
def test_url_needs_no_git(self):
# pip and uv shell out to a system git for git+ URLs; end-user
# installers cannot assume one exists.
assert "git+" not in setup_sonpipe.SONPIPE_GIT_URL
assert "https://" in setup_sonpipe.SONPIPE_GIT_URL

def test_matches_the_ced_extra(self):
# Both entry points must name the same URL, or an environment with
# both would hold conflicting direct references for sonpipe.
pyproject = Path(__file__).resolve().parents[1] / "pyproject.toml"
match = re.search(r"^ced = \[\"(.+?)\"\]$", pyproject.read_text(), re.MULTILINE)
assert match is not None, "[ced] extra not found in pyproject.toml"
assert match.group(1) == setup_sonpipe.SONPIPE_GIT_URL


class TestCli:
def test_check_reports_when_sonpipe_is_reachable(self, monkeypatch, capsys):
with mock.patch("ndr.format.ced.sonpipe.executable", return_value=["/opt/sonpipe"]):
Expand Down
Loading