diff --git a/crates/hiroz-py/pyproject.toml b/crates/hiroz-py/pyproject.toml index 8aedb5298..78a6870ae 100644 --- a/crates/hiroz-py/pyproject.toml +++ b/crates/hiroz-py/pyproject.toml @@ -27,6 +27,13 @@ dependencies = [ "hiroz-msgs-py>=0.1.0", ] +[project.optional-dependencies] +# numpy backs the tests that prove it can consume ZPayloadView's exported +# buffer without adding a copy. This file declares numpy. The test script does +# not install it imperatively. That keeps `pip install -e ".[test]"` a true +# instruction, which is what the tests' own failure message points at. +test = ["numpy>=1.21"] + [tool.maturin] features = ["pyo3/extension-module", "jazzy"] python-source = "python" diff --git a/crates/hiroz-py/tests/test_payload_view.py b/crates/hiroz-py/tests/test_payload_view.py index 8a814e4dc..ec412476c 100644 --- a/crates/hiroz-py/tests/test_payload_view.py +++ b/crates/hiroz-py/tests/test_payload_view.py @@ -163,12 +163,32 @@ def test_recv_raw_view_timeout(self, byte_array_pubsub): class TestZPayloadViewNumpy: - """Test ZPayloadView with numpy (if available).""" + """Test that numpy can consume ZPayloadView without adding a copy. + + numpy is a declared test dependency. Its absence is a failure, not a skip. + These tests previously guarded with ``importorskip``. No job installed + numpy, so both tests had *always* skipped. The summary line shows a + permanently skipped test and a passing test in the same way. + + Scope, precisely: ``arr.flags["OWNDATA"] is False`` proves that numpy + borrowed the buffer ZPayloadView exported. It does *not* prove that the + transport was zero-copy. ``ZPayloadView::new`` falls back to + ``PayloadBytes::Owned`` for a fragmented payload. numpy borrows that owned + copy in the same way. ``test_payload_view_is_zero_copy`` asserts + ``payload.is_zero_copy_py``, which is the transport-level check. + """ @pytest.fixture(autouse=True) def check_numpy(self): - """Skip tests if numpy is not available.""" - pytest.importorskip("numpy") + """Fail the test when numpy is missing. Do not skip silently.""" + try: + import numpy # noqa: F401 + except ImportError: # pragma: no cover - env misconfiguration + pytest.fail( + "numpy is a declared test dependency but is not installed, so " + "the ZPayloadView zero-copy assertions cannot run. Install it " + "with the test extra; do not restore importorskip here." + ) def test_numpy_frombuffer(self, byte_array_pubsub): """Test that numpy.frombuffer works with ZPayloadView.""" diff --git a/scripts/test-python.nu b/scripts/test-python.nu index 7a21507af..6eef66df1 100755 --- a/scripts/test-python.nu +++ b/scripts/test-python.nu @@ -42,6 +42,14 @@ def setup-venv [] { run-cmd "cd crates/hiroz-py; source .venv/bin/activate && pip install -e ../hiroz-msgs/python/" --shell bash --distro (get-distro) print " Installed hiroz-msgs-py (message types)" + # Test-only dependency. `TestZPayloadViewNumpy` checks that numpy consumes + # ZPayloadView's exported buffer without adding a copy. Plain `python -m + # venv` creates this venv, so it inherits no package from the surrounding + # devShell. Without this install the tests skip. The suite then still + # reports success. See #266. + run-cmd "cd crates/hiroz-py; source .venv/bin/activate && pip install -e '.[test]'" --shell bash --distro (get-distro) + print " Installed the test extra (numpy, for the zero-copy assertions)" + # Install hiroz-py in editable mode using maturin run-cmd "cd crates/hiroz-py; source .venv/bin/activate && RUSTFLAGS='-D warnings' maturin develop" --shell bash --distro (get-distro) print " Installed hiroz-py (Rust bindings)"