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.1.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.1-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: domubus-0.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 0779dfbf312940fb937dbcfad64914e69fa7e8cd4e43d915d82af58c5d097034
MD5 e86195fb353ec1607103890975b9958f
BLAKE2b-256 b8b8f6e6d01ce13366ef5f3580f78bd7e3af33077a439ebf47b2656b07e9f9a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for domubus-0.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: domubus-0.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d8e52e4ee26e6922bfad9fae25bb1d141e3144aac43b064bc99d45eb3d725dff
MD5 df9ed3e2def9ddfbdc40d50225baaea3
BLAKE2b-256 9b2e2d86d6e28a5d9a3b3a1790f42c79b931eb464dfa90166dcfb80f9843c0fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for domubus-0.1.1-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