fix(deps): the [ros2] extra installs a wheel on every supported Python - #3601
Conversation
`pip install 'strands-robots[ros2]'` could not install on any interpreter this
project supports. The extra declared `cyclonedds>=0.10.2,<1.0.0` while
`requires-python` is `>=3.12`; cyclonedds publishes wheels for cp37-cp310 up to
0.10.5 and for cp310-cp313 from 11.0.1, so nothing that ceiling admitted had a
wheel for a supported Python and the install fell through to the sdist:
Failed to build `cyclonedds==0.10.5`
Could not locate cyclonedds. Try to set CYCLONEDDS_HOME or CMAKE_PREFIX_PATH
That C install is the one thing the extra exists to make unnecessary - the RTPS
transport is the rclpy-free half of the ROS 2 story, offered by `use_rtps`,
`HardwareRtpsBridge` and docs/rtps-integration.md as "a self-contained pip
wheel" needing no sourced distro.
The ceiling now admits the wheel-bearing series (`<12`, capping the major per
the manifest's bound convention) and uv.lock records 11.0.1 with its cp312 and
cp313 wheels. The RTPS suites (96 tests) and a two-participant DDS loopback
pass unchanged on it; the API the package uses is the same in both series.
`uv lock --check` cannot report this, because the sdist it resolved is a
resolution inside the declared bounds - which is what `--check` grades. So
tests/test_lockfile_parity_gate.py gains it as a third offline drift class,
beside the below-floor and missing-from-the-lock rules it already covers, with
a non-vacuity pin so a renamed extra cannot green it silently.
cyclonedds has published no linux-aarch64 wheel in any release, so an aarch64
host still builds from source; the rule is phrased over the artifact kind
rather than per-platform coverage for that reason.
yinsong1986
left a comment
There was a problem hiding this comment.
Summary
Widens the [ros2] extra's cyclonedds ceiling from <1.0.0 to <12 so the extra resolves to a version that actually publishes wheels for a supported interpreter, relocks to 11.0.1, and adds an offline artifact-kind rule to tests/test_lockfile_parity_gate.py (a wheel-only extra whose only locked artifact is an sdist) plus a non-vacuity pin so a renamed extra cannot green the rule silently. The diagnosis checks out independently: PyPI's wheel matrix confirms 0.10.5 ships cp37-cp310 wheels only and 11.0.1 ships cp310-cp313, so under requires-python = ">=3.12" the old ceiling admitted no wheel at all and every install fell to the sdist's CycloneDDS C build - the exact toolchain the RTPS extra exists to avoid. Every wheel/sdist hash in the new uv.lock entry matches PyPI byte-for-byte, and only cp312/cp313 wheels are recorded, consistent with the lock resolving under the project's own requires-python. The cyclonedds surfaces the package imports (domain, qos, pub, sub, topic, idl, idl.annotations, idl.types) match the compatibility claim in the description.
What's good
- The pre-fix/post-fix claim reproduces exactly: the new rule reads 1 failed, 8 passed against
main's manifest+lock and 9 passed against this branch's. - The rationale for why
uv lock --checkcannot catch this class (an in-bounds sdist resolution is a valid resolution) is correct and now recorded in three places that will survive the PR: the manifest comment, the test module docstring, and the changelog fragment. - Changelog fragment correctly named
3601-<slug>.md; new strings are plain ASCII; the rule is deliberately phrased over artifact kind rather than per-platform coverage, which keeps it from refusing a lock that is already as good as the index allows (no aarch64 wheel exists in any cyclonedds release).
Verification suggestions
curl -s https://pypi.org/pypi/cyclonedds/json | jq '[.releases["0.10.5"][], .releases["11.0.1"][]] | map(.filename)'reproduces the wheel-matrix claim the whole fix rests on.- A fresh-venv smoke of the fixed path:
uv pip install 'strands-robots[ros2] @ .'on py3.12 should install a cyclonedds 11.0.1 wheel with no compiler invoked.
pip install 'strands-robots[ros2]'installed on no interpreter this project supports. Closes #3599.What
requires-pythonis>=3.12; the extra declaredcyclonedds>=0.10.2,<1.0.0. cyclonedds wheels are cp37-cp310 up to 0.10.5 and cp310-cp313 from 11.0.1, so that ceiling admitted no wheel for any supported Python and the install fell to the sdist:That C install is the one thing the extra exists to remove. The RTPS transport is the rclpy-free half of ROS 2 --
use_rtps,HardwareRtpsBridgeanddocs/rtps-integration.mdall offer it as "a self-contained pip wheel", no sourced distro. Ceiling now<12(major-capped per the manifest's convention);uv.lockrecords 11.0.1 with its cp312/cp313 wheels.Why the test lives in the lockfile gate
uv lock --checkexits 0 on the broken lock: the sdist it resolved is a resolution inside the declared bounds, which is what--checkgrades. So this is a third offline drift class intests/test_lockfile_parity_gate.pybeside the below-floor and missing-from-the-lock rules, plus a non-vacuity pin so a renamed extra cannot green it silently.Tests
New rule pre-fix 1 failed, 8 passed -> 9 passed.
tests/*.py+tests/rtps/11473 passed, 58 skipped;tests/rtps/+test_hardware_rtps_bridge.py96 passed on 11.0.1; a two-participant DDS loopback round-trips exactly. ruff + mypy clean (2010 files);uv lock --checkexit 0.Unchanged and upstream's to fix: cyclonedds ships no linux-aarch64 wheel in any release, so aarch64 still builds from source -- which is why the rule is phrased over the artifact kind, not per-platform coverage.