A type-safe event bus library for Python that provides reliable publish-subscribe messaging with automatic memory management and full type safety.
Project description
StrongBus
A type-safe event bus library for Python that provides reliable publish-subscribe messaging with automatic memory management and full type safety.
Features
- Type Safety: Full type checking with generics ensures callbacks receive the correct event types
- Memory Management: Automatic cleanup of dead references using weak references for methods
- Subscription Management: Easy subscription tracking and bulk cleanup via the Enrollment pattern
- Event Isolation: Events don't propagate to parent/child types - each event type is handled independently
- Zero Dependencies: Pure Python implementation with no external dependencies
Installation
pip install strongbus
For development:
pip install -e .
Quick Start
from dataclasses import dataclass
from strongbus import Event, EventBus, Enrollment
# Define your events
@dataclass(frozen=True)
class UserLoginEvent(Event):
username: str
# Create subscribers using Enrollment
class NotificationService(Enrollment):
def __init__(self, event_bus: EventBus):
super().__init__(event_bus)
self.subscribe(UserLoginEvent, self.on_user_login)
def on_user_login(self, event: UserLoginEvent) -> None:
print(f"Welcome {event.username}!")
# Usage
event_bus = EventBus()
service = NotificationService(event_bus)
event_bus.publish(UserLoginEvent(username="Alice"))
# Output: Welcome Alice!
# Cleanup
service.clear() # Automatically unsubscribes from all events
Core Concepts
Events
Events are simple data classes that inherit from the Event base class:
@dataclass(frozen=True)
class OrderCreatedEvent(Event):
order_id: str
customer_id: str
total: float
EventBus
The central hub for publishing and subscribing to events:
event_bus = EventBus()
# Subscribe to events
event_bus.subscribe(OrderCreatedEvent, handle_order)
# Publish events
event_bus.publish(OrderCreatedEvent(
order_id="12345",
customer_id="user123",
total=99.99
))
Enrollment
A base class that simplifies subscription management:
class OrderProcessor(Enrollment):
def __init__(self, event_bus: EventBus):
super().__init__(event_bus)
self.subscribe(OrderCreatedEvent, self.process_order)
self.subscribe(PaymentReceivedEvent, self.confirm_payment)
def process_order(self, event: OrderCreatedEvent) -> None:
# Handle order processing
pass
def confirm_payment(self, event: PaymentReceivedEvent) -> None:
# Handle payment confirmation
pass
Memory Management
StrongBus automatically manages memory to prevent leaks:
- Method callbacks use weak references and are automatically cleaned up when the object is garbage collected
- Function callbacks use strong references and persist until explicitly unsubscribed
- Enrollment pattern provides easy bulk cleanup with
clear()
Testing
Using tox (recommended)
Install tox with uv support:
uv tool install tox --with tox-uv
Run all tests across multiple Python versions:
tox
Manual testing
Run the test suite directly:
python -m unittest src/strongbus/tests.py
Slightly larger example
from dataclasses import dataclass
from strongbus import Event, EventBus, Enrollment
@dataclass(frozen=True)
class UserLoginEvent(Event):
username: str
@dataclass(frozen=True)
class UserLogoutEvent(Event):
username: str
@dataclass(frozen=True)
class DataUpdatedEvent(Event):
data_id: str
new_value: str
@dataclass(frozen=True)
class TestEvent(Event):
message: str
class PackageManager(Enrollment):
def __init__(self, event_bus: EventBus):
super().__init__(event_bus)
# Type-safe subscription - callback must accept UserLoginEvent
self.subscribe(UserLoginEvent, self.on_user_login)
self.subscribe(DataUpdatedEvent, self.on_data_updated)
def on_user_login(self, event: UserLoginEvent) -> None:
# Can access event.username with full type safety
print(f"PackageManager: User {event.username} logged in")
def on_data_updated(self, event: DataUpdatedEvent) -> None:
print(f"PackageManager: Data {event.data_id} updated to {event.new_value}")
class ContainerManager(Enrollment):
def __init__(self, event_bus: EventBus):
super().__init__(event_bus)
self.subscribe(UserLoginEvent, self.on_user_login)
self.subscribe(UserLogoutEvent, self.on_user_logout)
def on_user_login(self, event: UserLoginEvent) -> None:
print(f"ContainerManager: User {event.username} logged in")
def on_user_logout(self, event: UserLogoutEvent) -> None:
print(f"ContainerManager: User {event.username} logged out")
if __name__ == "__main__":
# Usage
event_bus = EventBus()
manager0 = PackageManager(event_bus)
manager1 = ContainerManager(event_bus)
# Publish events - type-safe with proper event objects
event_bus.publish(UserLoginEvent(username="Alice"))
# Output:
# PackageManager: User Alice logged in
# ContainerManager: User Alice logged in
event_bus.publish(UserLogoutEvent(username="Alice"))
# Output:
# ContainerManager: User Alice logged out
event_bus.publish(DataUpdatedEvent(data_id="123", new_value="new data"))
# Output:
# PackageManager: Data 123 updated to new data
# List all available event types
print("\nAvailable event types:")
for event_class in Event.__subclasses__():
print(f" - {event_class.__name__}")
# Cleanup
manager0.clear()
manager1.clear()
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
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 strongbus-0.1.0.tar.gz.
File metadata
- Download URL: strongbus-0.1.0.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e45a77f9c38bccf19c8c55419d317b5f7e8df3d40f41349209d7536cf5c873a
|
|
| MD5 |
d98dad551b7cfd5bdf5355a3a81074ff
|
|
| BLAKE2b-256 |
3ba11ac5091b9dd30a7a9d17bc7ee2e1cd1884eb8338ff7a50f78c86b8eeef50
|
File details
Details for the file strongbus-0.1.0-py3-none-any.whl.
File metadata
- Download URL: strongbus-0.1.0-py3-none-any.whl
- Upload date:
- Size: 5.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1eb91be573ac64bb2501a48b28121f34b017090350dfe47584adfb591d3cdb6
|
|
| MD5 |
8944964438cc9dc2270bebf816651946
|
|
| BLAKE2b-256 |
7b33573f6090d929c93a19c95d8558dc9c25d95b89070ba3fcc9588b07378b72
|