Skip to content

Add CI testing of axis convention remapping#54

Draft
nickswalker wants to merge 8 commits into
JakubAndrysek:masterfrom
nickswalker:nick/axis-convention-tests
Draft

Add CI testing of axis convention remapping#54
nickswalker wants to merge 8 commits into
JakubAndrysek:masterfrom
nickswalker:nick/axis-convention-tests

Conversation

@nickswalker

@nickswalker nickswalker commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Add tests that round-trip every AxisConvention through HID and verify mappings are preserved

Add a small dataclass slots=True compatibility shim so the package imports on Python 3.8/3.9 during CI

Also added Python 3.14 as well

Meant to be considered after #52

Summary by Sourcery

Add richer axis convention support, including new ROS and Unity frames, and validate these mappings via dedicated tests, while broadening Python version support and documenting the updated usage.

New Features:

  • Introduce ROS and Unity axis conventions and allow devices to be converted between any named axis conventions via HID-normalized mappings.
  • Expose more flexible axis remapping in modify_device_info() using explicit remap_axes mappings alongside optional axis inversion.

Enhancements:

  • Track the axis convention on DeviceInfo instances and normalize specs through HID when applying conventions to ensure consistent round-tripping.
  • Refine config and callback dataclasses with a Python-version-aware slots shim so the package imports cleanly on Python 3.8 and 3.9.
  • Improve documentation and examples to highlight built-in axis conventions and explicit axis remapping for custom coordinate frames.

Build:

  • Advertise Python 3.14 support in project metadata.

CI:

  • Add a test job to the CI matrix covering Python 3.8 through 3.14 and running the axis convention test suite.

Documentation:

  • Document the new ROS and Unity axis conventions and update usage examples to show axis_convention selection and explicit axis remapping for custom frames.

Tests:

  • Add tests that verify each axis convention round-trips through HID and that non-HID conventions round-trip correctly between each other.

nickswalker and others added 8 commits June 29, 2026 15:57
apply_axis_convention converts between any named conventions (normalize to HID first)
modify_device_info gains remap_axes; mutually exclusive with invert_axes
# Conflicts:
#	docs/mouseApi/examples.md
Co-authored-by: Peter Mitrano (AR) <peter.mitrano@agile-robots.com>
Co-authored-by: Peter Mitrano (AR) <peter.mitrano@agile-robots.com>
@nickswalker nickswalker changed the title Nick/axis convention tests Add CI testing of axis convention remapping Jul 7, 2026
@sourcery-ai

sourcery-ai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds explicit, invertible axis convention mappings (including new ROS and UNITY frames), tracks the convention on DeviceInfo, generalizes modify_device_info for arbitrary remaps, adds compatibility shims for dataclass slots on Python 3.8/3.9, wires conventions into docs and API text, extends CI to run axis-convention tests across Python 3.8–3.14, and verifies all AxisConvention variants round-trip through HID mappings.

File-Level Changes

Change Details Files
Introduce explicit HID↔named axis remapping infrastructure and use it to convert between AxisConvention frames.
  • Define AxisRemap type and _HID_TO_CONVENTION mapping that describes HID→LEGACY/HID_Z_UP/ROS/UNITY axis/sign remaps.
  • Add helper functions _parse_axis_remap, _copy_axis_spec, and _normalize_to_hid to validate axis names, apply signs, and normalize DeviceInfo specs to HID convention.
  • Refactor apply_axis_convention to normalize any named-convention DeviceInfo to HID and then apply the appropriate HID→target remap, instead of hardcoding legacy/HID_Z_UP logic.
pyspacemouse/config_helpers.py
Extend DeviceInfo and helper APIs to track conventions and support explicit axis remapping/inversion.
  • Add a convention field to DeviceInfo with default AxisConvention.LEGACY and thread this through create_device_info and apply_axis_convention.
  • Update create_device_info to accept an optional convention argument and propagate it into the constructed DeviceInfo.
  • Redesign modify_device_info to support remap_axes (output←source mapping plus optional sign) and stricter invert_axes validation, make remap_axes and invert_axes mutually exclusive, and clear convention to None whenever axes are modified.
pyspacemouse/config_helpers.py
pyspacemouse/types.py
docs/mouseApi/index.md
docs/README.md
docs/troubleshooting.md
README.md
Add ROS and UNITY axis conventions and document their semantics.
  • Extend AxisConvention enum with ROS and UNITY members and update its docstring to describe handedness and frames.
  • Update mouse API documentation to include ROS and UNITY rows in the axis convention table and examples of using axis_convention=AxisConvention.ROS/UNITY.
  • Clarify API docstrings in open and open_by_path to mention ROS and UNITY as recommended conventions for those ecosystems.
pyspacemouse/types.py
docs/mouseApi/index.md
pyspacemouse/api.py
README.md
docs/README.md
docs/troubleshooting.md
Introduce a Python-version-aware dataclass slots shim so code imports on Python 3.8/3.9 while still using slots on 3.10+.
  • Add _DATACLASS_SLOTS helper based on sys.version_info to conditionally pass slots=True only on Python ≥3.10.
  • Apply the shim to AxisSpec, ButtonSpec, SpaceMouseState, DeviceInfo, and callback-related dataclasses instead of hardcoding slots=True.
pyspacemouse/types.py
pyspacemouse/callbacks.py
Add CI coverage and targeted tests to ensure axis conventions round-trip correctly through HID mappings.
  • Add a dedicated GitHub Actions test job running pytest on Python 3.8–3.14, installing libhidapi-dev and the package in editable mode.
  • Create tests/test_axis_conventions.py that constructs a synthetic HID DeviceInfo and asserts all AxisConvention variants round-trip to HID and that non-HID conventions (e.g., ROS) round-trip correctly when composed.
.github/workflows/ci.yaml
tests/test_axis_conventions.py
Refresh examples and docs to prefer built-in conventions and the new remap_axes API.
  • Simplify config_helpers usage example to show in-place Y inversion using modify_device_info on a built-in spec instead of create_device_info.
  • Update README/docs examples and troubleshooting guidance to demonstrate passing AxisConvention.ROS to open() and using remap_axes (with (axis, sign) tuples) for custom frames instead of only invert_axes examples.
pyspacemouse/config_helpers.py
README.md
docs/README.md
docs/mouseApi/index.md
docs/troubleshooting.md

Possibly linked issues

  • ## axis conventions: PR formalizes HID↔axis mappings, adds ROS/Unity conventions, docs, and tests, directly addressing the axis convention clarification issue.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

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.

1 participant