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.typedmarker
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 handlerunsubscribe(handler_id)- Unsubscribe by IDon(event_type, ...)- Decorator for subscribingonce(event_type, ...)- Decorator for one-time handleremit_async(event, data=None)- Emit event asynchronouslyemit(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 historyclear_history()- Clear in-memory historyclear_handlers()- Remove all handlers
Events
BaseEvent- Pydantic-based event (or dataclass fallback)StringEvent- Simple string-based event with data dict
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0779dfbf312940fb937dbcfad64914e69fa7e8cd4e43d915d82af58c5d097034
|
|
| MD5 |
e86195fb353ec1607103890975b9958f
|
|
| BLAKE2b-256 |
b8b8f6e6d01ce13366ef5f3580f78bd7e3af33077a439ebf47b2656b07e9f9a6
|
Provenance
The following attestation bundles were made for domubus-0.1.1.tar.gz:
Publisher:
publish.yml on lensator/domubus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
domubus-0.1.1.tar.gz -
Subject digest:
0779dfbf312940fb937dbcfad64914e69fa7e8cd4e43d915d82af58c5d097034 - Sigstore transparency entry: 909604911
- Sigstore integration time:
-
Permalink:
lensator/domubus@7c6f9c72505e6c84d1c2a0192be6a0b637ce64a7 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/lensator
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7c6f9c72505e6c84d1c2a0192be6a0b637ce64a7 -
Trigger Event:
release
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8e52e4ee26e6922bfad9fae25bb1d141e3144aac43b064bc99d45eb3d725dff
|
|
| MD5 |
df9ed3e2def9ddfbdc40d50225baaea3
|
|
| BLAKE2b-256 |
9b2e2d86d6e28a5d9a3b3a1790f42c79b931eb464dfa90166dcfb80f9843c0fb
|
Provenance
The following attestation bundles were made for domubus-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on lensator/domubus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
domubus-0.1.1-py3-none-any.whl -
Subject digest:
d8e52e4ee26e6922bfad9fae25bb1d141e3144aac43b064bc99d45eb3d725dff - Sigstore transparency entry: 909604915
- Sigstore integration time:
-
Permalink:
lensator/domubus@7c6f9c72505e6c84d1c2a0192be6a0b637ce64a7 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/lensator
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7c6f9c72505e6c84d1c2a0192be6a0b637ce64a7 -
Trigger Event:
release
-
Statement type: