Skip to main content

Async/sync event bus with optional Pydantic integration, persistence, and priority handlers

Project description

domubus

A type-safe, async/sync event bus for Python with optional Pydantic integration, persistence, and priority handlers. Zero required dependencies.

Features

  • Async & Sync - Both async and sync handlers, emit from either context
  • Zero Dependencies - Core package uses only Python stdlib
  • Optional Pydantic - Type-safe events when Pydantic is installed
  • Priority Handlers - Control execution order with priority values
  • Wildcard Subscriptions - Subscribe to all events with *
  • One-time Handlers - Auto-unsubscribe after first execution
  • Event Filters - Conditionally execute handlers
  • JSONL Persistence - WAL-style event persistence
  • Fully Typed - PEP 561 compatible with py.typed marker

Installation

pip install domubus

# With Pydantic support
pip install domubus[pydantic]

Quick Start

import asyncio
from domubus import EventBus

bus = EventBus()

@bus.on("device.light.on")
async def handle_light_on(event):
    print(f"Light turned on: {event.data}")

@bus.on("device.light.on", priority=100)
def high_priority_handler(event):
    print("This runs first (sync handler)")

async def main():
    await bus.emit_async("device.light.on", {"brightness": 100})

asyncio.run(main())

Typed Events with Pydantic

from typing import ClassVar
from domubus import EventBus, BaseEvent

class DeviceStateChanged(BaseEvent):
    event_type: ClassVar[str] = "device.state.changed"
    device_id: str
    new_state: str

bus = EventBus()

@bus.on("device.state.changed")
async def handle_state_change(event: DeviceStateChanged):
    print(f"Device {event.device_id} -> {event.new_state}")

await bus.emit_async(DeviceStateChanged(device_id="light1", new_state="on"))

Persistence

from domubus import EventBus

# Events are persisted to JSONL file
async with EventBus(persistence_path="~/.myapp/events.jsonl") as bus:
    await bus.emit_async("user.login", {"user_id": "123"})
    
    # History is automatically loaded on context enter
    history = bus.get_history(event_type="user.login")

Wildcard Subscriptions

@bus.on("*")
def log_all_events(event):
    print(f"Event: {event.event_type}")

One-time Handlers

@bus.once("system.ready")
async def on_ready(event):
    print("System ready! (only runs once)")

Event Filters

def only_important(event):
    return event.data.get("priority") == "high"

@bus.on("notification", filter_fn=only_important)
def handle_important(event):
    print(f"Important: {event.data}")

Error Handling

def on_error(exception, event, handler):
    print(f"Handler {handler.__name__} failed: {exception}")

bus = EventBus(error_callback=on_error)

API Reference

EventBus

  • subscribe(event_type, handler, priority=0, once=False, filter_fn=None) - Subscribe handler
  • unsubscribe(handler_id) - Unsubscribe by ID
  • on(event_type, ...) - Decorator for subscribing
  • once(event_type, ...) - Decorator for one-time handler
  • emit_async(event, data=None) - Emit event asynchronously
  • emit(event, data=None) - Emit (async from sync context)
  • emit_sync(event, data=None) - Emit synchronously (sync handlers only)
  • get_history(event_type=None, limit=None) - Get event history
  • clear_history() - Clear in-memory history
  • clear_handlers() - Remove all handlers

Events

  • BaseEvent - Pydantic-based event (or dataclass fallback)
  • StringEvent - Simple string-based event with data dict

License

MIT

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

domubus-0.1.0.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

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

domubus-0.1.0-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

Details for the file domubus-0.1.0.tar.gz.

File metadata

  • Download URL: domubus-0.1.0.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for domubus-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a05a1c436c148307f04c13bef1947866279998fe99287038a48612d5b33f38cb
MD5 65d17347b5bb0da4375a51943e4d02d5
BLAKE2b-256 024af525e6d9788438184ff877d3727772707f711774da705138b8c08861acca

See more details on using hashes here.

Provenance

The following attestation bundles were made for domubus-0.1.0.tar.gz:

Publisher: publish.yml on lensator/domubus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file domubus-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: domubus-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for domubus-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 581a4884e14d58e07132321c13bc70281dd10e9379f9960b4b832e3f186d1a9d
MD5 8873707aca3d08dede2722bc861d7f8f
BLAKE2b-256 fc3c0a2a504b1e4bc6c829b761ad80dcde7b3a88e1c389c2386ef6f075f0179c

See more details on using hashes here.

Provenance

The following attestation bundles were made for domubus-0.1.0-py3-none-any.whl:

Publisher: publish.yml on lensator/domubus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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