Skip to content

add "read_latest()" API to avoid old/lagging data#53

Draft
peter-mitrano-ar wants to merge 3 commits into
masterfrom
read-latest
Draft

add "read_latest()" API to avoid old/lagging data#53
peter-mitrano-ar wants to merge 3 commits into
masterfrom
read-latest

Conversation

@peter-mitrano-ar

@peter-mitrano-ar peter-mitrano-ar commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Add a new function for reading the latest data, even from a slow loop, without getting old data.

  • remove the "nonblocking" flag, which previous defaulted to "true", and if someone was calling it with "false", then ... TBD whether they will be mad about this. I still am working on this changset and need to think about it.

Also realized that examples/05_discovery.py needs to count devices, since there could be multiple. But that's not related to reading.

@sourcery-ai

sourcery-ai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements proper non-blocking behavior tracking in the device, introduces a new read_latest() API for draining buffered input in non-blocking mode, and updates documentation/examples/CLI to prefer blocking mode for simple loops and read_latest() for slower loops while clarifying device discovery output.

Sequence diagram for nonblocking open and read_latest() behavior

sequenceDiagram
    actor User
    participant pyspacemouse
    participant SpaceMouseDevice as mouse
    participant hid_device

    User->>pyspacemouse: open(nonblocking=True)
    pyspacemouse->>pyspacemouse: _create_and_open_device(nonblocking=True)
    pyspacemouse->>mouse: mouse.open()
    pyspacemouse->>hid_device: set_nonblocking(True)
    pyspacemouse->>mouse: mouse._nonblocking = True
    pyspacemouse-->>User: mouse

    loop slow_loop
        User->>mouse: read_latest()
        alt nonblocking is True
            mouse->>hid_device: read(bytes_to_read)
            opt data available
                mouse->>mouse: _process(data)
                mouse->>hid_device: read(bytes_to_read)
            end
        else nonblocking is False
            mouse-->>User: RuntimeError
        end
        mouse-->>User: SpaceMouseState
    end
Loading

File-Level Changes

Change Details Files
Add read_latest() API to drain buffered HID data when using non-blocking mode and wire nonblocking flag into the device instance.
  • Implement read_latest() on the device that repeatedly reads from the HID until no more data is available, processing each packet and returning the final state.
  • Guard read_latest() to only work when nonblocking=True, raising a RuntimeError otherwise to steer blocking-mode users toward read().
  • Ensure the device instance tracks the nonblocking setting by assigning mouse._nonblocking in the API factory after configuring the HID handle.
pyspacemouse/device.py
pyspacemouse/api.py
Update documentation to explain laggy data when sleeping, introduce read_latest() usage guidance, and switch basic examples to blocking mode for simple read loops.
  • Change README examples to explicitly pass nonblocking=False to open() and open_by_path() in simple read loops, and add a new section describing buffering lag and how read_latest() solves it.
  • Clarify that read() returns one message and that read_latest() should be used when calling into the API at low frequency or with sleeps.
  • Show code samples using read_latest() in a loop with sleep to demonstrate correct behavior.
README.md
Adjust example scripts to use read_latest() where appropriate and prefer nonblocking=False for straightforward streaming examples, while tuning sleep intervals.
  • Switch multi-device example to use read_latest() for each hand and increase sleep to 0.1s to demonstrate low-frequency polling without buffering issues.
  • Update rotation-inversion, basic, callbacks, axis callbacks, buttons, and open-by-path examples to pass nonblocking=False for normal blocking read loops and remove or shorten sleeps that are no longer required.
  • Retain small sleeps only where needed for callback-based examples, tightening them to 0.001s to reduce buffering while still yielding the loop.
examples/01_basic.py
examples/02_callbacks.py
examples/03_multi_device.py
examples/04_open_by_path.py
examples/06_axis_callbacks.py
examples/08_buttons.py
examples/09_invert_rotations.py
Improve CLI and discovery output to reflect multiple connected devices and use blocking mode for simple connectivity tests.
  • Change discovery script to count how many devices of each supported type are connected and print the count instead of a simple checkmark indicator.
  • Update CLI test_connect command to open the device with nonblocking=False and remove the initial sleep before starting the read loop.
examples/05_discovery.py
pyspacemouse/pyspacemouse_cli.py

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

@peter-mitrano-ar peter-mitrano-ar changed the title improve blocking vs non-blocking behavior add "read_latest()" API to avoid old/lagging data Jul 6, 2026
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