Skip to content

fix(deps): the [ros2] extra installs a wheel on every supported Python - #3601

Merged
cagataycali merged 1 commit into
strands-labs:mainfrom
cagataycali:ros2-extra-locks-a-wheel
Sep 13, 2026
Merged

cagataycali merged 1 commit into
strands-labs:mainfrom
cagataycali:ros2-extra-locks-a-wheel

Conversation

@cagataycali

Copy link
Copy Markdown
Member

pip install 'strands-robots[ros2]' installed on no interpreter this project supports. Closes #3599.

ros2 extra wheel matrix

What

requires-python is >=3.12; the extra declared cyclonedds>=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:

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 remove. The RTPS transport is the rclpy-free half of ROS 2 -- use_rtps, HardwareRtpsBridge and docs/rtps-integration.md all offer it as "a self-contained pip wheel", no sourced distro. Ceiling now <12 (major-capped per the manifest's convention); uv.lock records 11.0.1 with its cp312/cp313 wheels.

Why the test lives in the lockfile gate

uv lock --check exits 0 on the broken lock: the sdist it resolved is a resolution inside the declared bounds, which is what --check grades. So this is a third offline drift class in tests/test_lockfile_parity_gate.py beside 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.py 96 passed on 11.0.1; a two-participant DDS loopback round-trips exactly. ruff + mypy clean (2010 files); uv lock --check exit 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.

`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.
@cagataycali
cagataycali enabled auto-merge (squash) September 13, 2026 16:25

@yinsong1986 yinsong1986 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 --check cannot 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.

@cagataycali
cagataycali merged commit cc9b387 into strands-labs:main Sep 13, 2026
9 checks passed
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.

[ros2] extra pins cyclonedds<1.0.0, which has no wheel for Python >=3.12

3 participants