Skip to main content

Qt integration for ezmsg with direct topic-based pub/sub

Project description

ezmsg-qt

Qt-native pub/sub runtime for connecting GUIs to ezmsg graphs.

Overview

ezmsg-qt lets Qt widgets publish to and subscribe from ezmsg topics using a familiar signal/slot style while keeping ezmsg runtime ownership explicit.

  • EzSession owns the ezmsg runtime thread, GraphContext, and sidecar pipelines
  • EzSubscriber and EzPublisher attach to a session
  • ProcessorChain compiles processing stages into a sidecar runtime owned by the session

Quick Start

from enum import Enum, auto
from qtpy import QtWidgets

from ezmsg.qt import EzPublisher, EzSession, EzSubscriber


class VelocityTopic(Enum):
    INPUT_SETTINGS = auto()
    OUTPUT_DATA = auto()


class VelocityWidget(QtWidgets.QWidget):
    def __init__(self, session: EzSession):
        super().__init__()

        self.slider = QtWidgets.QSlider()
        self.label = QtWidgets.QLabel("Waiting for data...")

        self.data_sub = EzSubscriber(
            VelocityTopic.OUTPUT_DATA,
            parent=self,
            session=session,
        )
        self.settings_pub = EzPublisher(
            VelocityTopic.INPUT_SETTINGS,
            parent=self,
            session=session,
        )

        self.data_sub.connect(self.on_data)
        self.slider.valueChanged.connect(self.on_slider)

    def on_data(self, msg):
        self.label.setText(f"Received: {msg}")

    def on_slider(self, value):
        self.settings_pub.emit({"gain": value})


def main() -> None:
    app = QtWidgets.QApplication([])
    session = EzSession()
    window = VelocityWidget(session)
    window.show()

    with session:
        app.exec()

Runtime Topic Switching

EzSubscriber can retarget to a new topic at runtime without reconnecting Qt slots.

class TopicSwitcher(QtWidgets.QWidget):
    def __init__(self, session: EzSession):
        super().__init__()
        self.sub = EzSubscriber(MyTopic.A, parent=self, session=session)
        self.sub.connect(self.on_data)

    def switch_to_b(self) -> None:
        self.sub.set_topic(MyTopic.B)

    def pause_updates(self) -> None:
        self.sub.clear_topic()
  • set_topic(...) blocks until the running session applies the switch
  • clear_topic() disconnects the subscriber from all topics
  • topic reflects the currently active topic
  • topic switching requires the subscriber to be attached to a running session
  • signals available for UI state: switch_started, topic_changed, topic_cleared, switch_failed

Local Processing

Use ProcessorChain when widget-facing data needs ezmsg processing off the UI thread.

from ezmsg.qt import EzSession, ProcessorChain

session = EzSession()

chain = (
    ProcessorChain(MyTopic.RAW, parent=widget)
    .parallel(LowPassFilter)
    .local(ThresholdDetector)
    .connect(widget.on_processed)
    .attach(session)
)
  • .parallel(...) runs a stage group in its own sidecar process
  • .local(...) runs a stage group in the shared sidecar process
  • neither mode runs on the Qt UI thread

External Graphs

Point a session at an existing GraphRunner or GraphServer by providing graph_address.

runner.start()
session = EzSession(graph_address=runner.graph_address)
try:
    with session:
        app.exec()
finally:
    if runner.running:
        runner.stop()

API Reference

EzSession

session = EzSession(graph_address=None)
with session:
    app.exec()
  • graph_address: Optional GraphServer address
  • attach(obj): Attach an EzSubscriber, EzPublisher, or ProcessorChain
  • detach(obj): Detach an EzSubscriber or EzPublisher
  • running: Whether the session runtime is active

EzSubscriber

EzSubscriber(
    topic: Enum | str | None = None,
    parent: QObject = None,
    *,
    session: EzSession | None = None,
    leaky: bool = False,
    max_queue: int | None = None,
    throttle_hz: float | None = None,
)
  • session: The session that owns this subscriber
  • connect(slot): Connect a handler to receive messages
  • set_topic(topic): Switch to a new topic on a running session
  • clear_topic(): Unsubscribe from the current topic on a running session
  • received: Qt signal emitted when a message arrives
  • switch_started, topic_changed, topic_cleared, switch_failed: lifecycle signals for runtime switching

EzPublisher

EzPublisher(
    topic: Enum | str | None = None,
    parent: QObject = None,
    *,
    session: EzSession | None = None,
    queue_policy: QueuePolicy = "unbounded",
    max_pending: int | None = None,
)
  • session: The session that owns this publisher
  • emit(message): Send a message to the topic
  • set_topic(topic): Switch to a new topic on a running session
  • clear_topic(): Unpublish from the current topic on a running session
  • switch_started, topic_changed, topic_cleared, switch_failed: lifecycle signals for runtime switching

Installation

Install from PyPI:

pip install ezmsg-qt

You also need a Qt binding — pick one:

pip install ezmsg-qt[pyqt6]   # or
pip install ezmsg-qt[pyside6]

Or install the latest development version:

pip install git+https://github.com/ezmsg-org/ezmsg-qt@main

Development

We use uv for development.

  1. Install uv if not already installed.
  2. Fork this repository and clone your fork locally.
  3. Open a terminal and cd to the cloned folder.
  4. Run uv sync --extra pyside6 to create a .venv and install dependencies.
  5. (Optional) Install pre-commit hooks: uv run pre-commit install
  6. After making changes, run the test suite: uv run pytest tests

License

MIT License - see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ezmsg_qt-0.2.1.tar.gz (38.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ezmsg_qt-0.2.1-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file ezmsg_qt-0.2.1.tar.gz.

File metadata

  • Download URL: ezmsg_qt-0.2.1.tar.gz
  • Upload date:
  • Size: 38.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for ezmsg_qt-0.2.1.tar.gz
Algorithm Hash digest
SHA256 114e4e887dc22627f3978c4439a3e4179cb562d79ce02df681038e52d900482d
MD5 90d5905de1ec06f302a8f8d6918efec6
BLAKE2b-256 f680adcfdabd9cc6c6d2eb7f3eff9ef2359b41d5297b5afe56bfa4ae1135ff83

See more details on using hashes here.

File details

Details for the file ezmsg_qt-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: ezmsg_qt-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 23.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for ezmsg_qt-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7f3013d055d8799dab7a649b2a7c7f90da7e38797dff35f05842031bcee4d153
MD5 ab2237d3a8c9c68f9a64dc4446dc838a
BLAKE2b-256 f5112f10136a35b3d1b8c480b08c5016a61ac090ad38b4acb0915cb5c68a818a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page