Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Hermes Device Manager (hermes-dm)

License: Zlib

CI Documentation Status

PyPI version Python Versions PyPI Wheel

pre-commit Ruff

Hermes-DM is a lightweight, high-performance, and asynchronous device manager that provides a native, modern software interface for classic test and measurement hardware.

By leveraging ZeroMQ (ZMQ) for swift, non-blocking message passing and SCPI (Standard Commands for Programmable Instruments) for hardware communication, Hermes allows you to seamlessly control, monitor, and log data from generic lab instruments.


Features

  • Asynchronous Architecture: Built on top of ZeroMQ for high-throughput, low-latency telemetry logging.
  • Generic SCPI Support: Easily extensible to any programmable instrument (Power supplies, Oscilloscopes, DMMs, etc.).
  • Decoupled Logging: Devices stream data asynchronously, isolating measurement constraints from data storage layers.
  • Lightweight Footprint: Avoids heavy industrial middleware framework bloat.

Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│ BACKGROUND DAEMON (hermes-daemon)                           │
│                                                             │
│  [ SCPI Instruments ] ◄──── (PyVISA) ────► [ Async Server ] │
│                                                 │     │     │
│  [ SQLite DB Logs ] ◄────── (Database) ─────────┘     │     │
└───────────────────────────────────────────────────────┼─────┘
                                                        │
                      (ZeroMQ: Ports 5555 REP & 5556 PUB)
                                                        │
┌───────────────────────────────────────────────────────▼─────┐
│ USER ENVIRONMENT (hermes_dm.client)                         │
│                                                             │
│  [ HermesClient Library ]                                   │
│            │                                                │
│            ▼                                                │
│  [ Standalone Scripts | Jupyter Notebooks | GUI App ]       │
└─────────────────────────────────────────────────────────────┘

Installation

pip install hermes-dm

Quick Start

Hermes operates on a robust Client-Server architecture to ensure your hardware polling never blocks your user interfaces or scripts.

1. Start the Background Daemon

Run this in your terminal to start the background hardware manager:

hermes-daemon --db-dir ./lab_data --cmd-port 5555

2. Control via Python Script

In a separate terminal, Jupyter notebook, or GUI, use the client library to issue commands to the daemon:

from hermes_dm.client import HermesClient

# Connect to the background daemon
client = HermesClient(host="localhost", port=5555)

# Connect the hardware (driver logic is handled by the daemon)
client.connect_device(
    name="Main_PSU",
    model="Keithley2410",
    identifier="TCPIP::111.222.33.44::INSTR"
)

# Configure the instrument
client.configure_device("Main_PSU", {"source_mode": "VOLT", "output_enabled": True})

# Start continuous asynchronous logging to SQLite
client.start_logging()

Developer Guide

Welcome! This section covers everything you need to know to set up a local development environment, understand the underlying architecture, and contribute to hermes-dm.

System Architecture Overview

hermes-dm uses a decoupled, event-driven, client-server architecture designed for high-performance, non-blocking laboratory hardware control.

  • The Hermes Client: A lightweight, synchronous Python API exposed to user scripts or notebooks. It handles telemetry requests, sends command packets over ZeroMQ, and translates backend JSON error states back into native Python exceptions.
  • The Hermes Daemon: A persistent, asynchronous background process (asyncio) handling incoming network traffic via ZeroMQ.
  • Isolated Thread Pools: To prevent slow hardware I/O (like instrument connection scans or legacy GPIB commands) from locking up the main asynchronous network event loop, the daemon uses dedicated OS thread pools (asyncio.to_thread and custom ThreadPoolExecutor instances) to isolate synchronous PyVISA drivers.

Environment Setup

Follow these steps to set up an isolated development environment running your code in editable mode with all developer tools active.

  1. Clone the repository and navigate to the root directory:

    git clone [https://github.com/cbeiraod/hermes-dm.git](https://github.com/cbeiraod/hermes-dm.git)
    cd hermes-dm
    
  2. Create a virtual environment:

    python -m venv .venv
    
  3. Activate the environment:

    • Linux / macOS: source .venv/bin/activate
    • Windows (Cmd): .venv\Scripts\activate.bat
    • Windows (PowerShell): .venv\Scripts\Activate.ps1
  4. Install the package in editable mode with development extras:

    pip install -e ".[dev]"
    

    Note: If you are using Zsh, make sure to wrap the target in quotes: pip install -e ".[dev]"

    Optionally, install the package in editable mode with development, testing, and documentation extras:

    pip install -e ".[dev,docs]"
    
  5. Install the local Git hooks:

    python -m pre_commit install
    

Development Tools Stack

We use a modern, consolidated tool stack to enforce code quality, verify async test patterns, and automate package distribution.

Tool Purpose Standalone Command
Pytest Test runner for client, server routing, and database logs pytest
Ruff Lightning-fast linter, formatter, and import sorter ruff check (lint)
ruff format (style)
Pre-commit Framework managing local Git hooks and code safety python -m pre_commit run --all-files
Sphinx Documentation generator extracting structural Python docstrings sphinx-build -b html docs/ docs/_build/html
Bump-my-version Automated single-source-of-truth version bumping bump-my-version bump [patch|minor|major]
Build Creates standard PEP 517 source archives and wheels python -m build
Twine Securely uploads distribution wheels to PyPI twine upload dist/*

Running Tools Standalone

  • Running the Test Suite: To execute all test suites with verbose execution details:

    pytest -v
    
  • Running Linter/Formatter Manually: While pre-commit intercepts formatting issues during git tracking, you can trigger individual sweeps manually:

    ruff check --fix     # Evaluates code quality rules and auto-fixes violations
    ruff format          # Enforces your project's code style rules across all files
    
  • Simulating a Pre-commit Run: If you want to evaluate all files against the entire pre-commit stack (including trailing whitespace, end-of-file fixers, and forgotten debug statements) without committing code:

    python -m pre_commit run --all-files
    
  • Building Documentation Locally: To compile your .rst design layout and extract code docstrings via Sphinx into a responsive, dark-mode-ready static HTML site using the Furo theme:

    python -m sphinx -b html docs/ docs/_build/html
    

    After compilation, open docs/_build/html/index.html in your browser to preview the output.

  • Executing a Release Version Bump: To safely increment versions across your pyproject.toml and package __init__.py while auto-generating tracking commits and release candidate tags:

    bump-my-version bump minor
    

CI/CD Infrastructure (GitHub Actions)

Automation pipelines are tracked inside .github/workflows/. They isolate compute footprints to keep automation efficient and free.

1. Continuous Integration (ci.yml)

Triggers automatically on every push to main, pull request tracking, or creation of version tags (v*.*.*).

  • Fail-Fast Lint Gate: Automatically triggers a clean cloud environment to test the full codebase against pre-commit. If formatting is irregular or a stray breakpoint() is exposed, the job drops immediately.
  • Linux Test Core: Executes the complete async test matrix under an optimized caching system to evaluate package installs in seconds.
  • Extended Multi-OS Testing: To control costs, tests targeting Windows and macOS runners are restricted. They execute only when a formal version release tag (e.g., v0.2.0) is discovered or when manually requested via the GitHub Actions UI.

2. PyPI Package Deployment (Coming Soon)

  • Triggers exclusively on published GitHub Releases.
  • Automatically triggers the build pipeline, verifies package architecture integrity via twine check, and deploys clean production wheels securely onto the Python Package Index (PyPI).

License

This project is licensed under the zlib/libpng License - see the LICENSE file for details.

Metadata

Release files for hermes-dm 0.0.1a1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hermes-dm 0.0.1a1
File Size Uploaded
hermes_dm-0.0.1a1.tar.gz 25.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hermes-dm 0.0.1a1
File Interpreter ABI Platform
hermes_dm-0.0.1a1-py3-none-any.whl Python 3 none any Details

Total release size: 49.4 kB

Release files / hermes_dm-0.0.1a1.tar.gz

Download URL hermes_dm-0.0.1a1.tar.gz
Size 25.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c0cc8c35375f9da7048b82d136eb4af1433b6ba11a7b68416a5d5d3278ca6e5c
BLAKE2b-256 checksum
How to use checksums
4e80489904858752c633556986fa2b4db0e8c8deaaeed2a43a8e63cba09bdf4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 4, 2026.

Transparency log

Release files / hermes_dm-0.0.1a1-py3-none-any.whl

Download URL hermes_dm-0.0.1a1-py3-none-any.whl
Size 24.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4389ac1255037cd90929e386dca0aca464b88a1527a4c08ff78980a87928c0da
BLAKE2b-256 checksum
How to use checksums
b54868a7f5e0c8b7488f0c8e60b1d2b175b50800abc731012664b4666c44a1ce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.1a1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page