A lightweight Python library for writing events to EventStore, compatible with .NET micro-plumberd
Project description
py-micro-plumberd
A lightweight Python library for writing events to EventStore, designed for seamless interoperability with the .NET micro-plumberd framework. This library ensures that events written from Python can be read and processed by C# applications using micro-plumberd.
Features
- Simple event definition with automatic ID generation (lowercase UUID with dashes)
- Stream naming convention:
{Category}-{StreamId} - Automatic metadata enrichment (Created timestamp, ClientHostName)
- EventStore client for appending events
- Full compatibility with C# micro-plumberd event format
Installation
pip install py-micro-plumberd
Quick Start
Define an Event
from py_micro_plumberd import Event
from datetime import datetime
import uuid
class RecordingFinished(Event):
def __init__(self, recording_id: str, duration: float, file_path: str):
super().__init__()
self.recording_id = recording_id
self.duration = duration
self.file_path = file_path
Append Events to EventStore
from py_micro_plumberd import EventStoreClient, StreamName
# Create client
client = EventStoreClient("esdb://localhost:2113?tls=false")
# Create an event
event = RecordingFinished(
recording_id="rec-123",
duration=120.5,
file_path="/recordings/rec-123.mp4"
)
# Define stream
stream = StreamName(category="Recording", stream_id="b27f9322-7d73-4d98-a605-a731a2c373c6")
# Append event
client.append_to_stream(stream, event)
Core Concepts
Events
All events must inherit from the Event base class, which automatically:
- Generates a unique ID (UUID) for each event instance
- Provides serialization support
- Enables metadata enrichment
Stream Naming
Streams follow the pattern {Category}-{StreamId}:
- Category: Logical grouping of events (e.g., "Recording", "User", "Order")
- StreamId: Unique identifier for the stream instance (typically a UUID)
Example: Recording-b27f9322-7d73-4d98-a605-a731a2c373c6
Metadata
Each event is automatically enriched with metadata:
- Created: ISO 8601 timestamp of when the event was created
- ClientHostName: Hostname of the machine creating the event
- $correlationId: Same as TEvent.Id
- $causationId: Same as TEvent.Id
Advanced Usage
Custom Metadata
from py_micro_plumberd import Event, Metadata
class UserRegistered(Event):
def __init__(self, email: str, username: str):
super().__init__()
self.email = email
self.username = username
client.append_to_stream(stream, event)
Reading Events in C#
Events written by py-micro-plumberd can be read using the .NET micro-plumberd framework:
using MicroPlumberd;
// Define matching event class
public record RecordingFinished(string RecordingId, double Duration, string FilePath);
// Read events using micro-plumberd
var plumber = serviceProvider.GetRequiredService<IPlumber>();
var events = await plumber.ReadStream("Recording-b27f9322-7d73-4d98-a605-a731a2c373c6");
foreach (var evt in events)
{
if (evt.Event is RecordingFinished recording)
{
Console.WriteLine($"Recording {recording.RecordingId} finished");
Console.WriteLine($"Duration: {recording.Duration} seconds");
Console.WriteLine($"Created: {evt.Metadata.Created}");
}
}
Configuration
Connection String
The EventStore connection string supports various formats:
# Insecure connection
client = EventStoreClient("esdb://localhost:2113?tls=false")
# Secure connection
client = EventStoreClient("esdb://localhost:2113")
# With credentials
client = EventStoreClient("esdb://admin:changeit@localhost:2113")
Client Options
client = EventStoreClient(
connection_string="esdb://localhost:2113",
default_deadline=30, # seconds
keep_alive_interval=10, # seconds
keep_alive_timeout=10 # seconds
)
Examples
Complete Example: Task Management System
from py_micro_plumberd import Event, EventStoreClient, StreamName
from datetime import datetime
# Define events
class TaskCreated(Event):
def __init__(self, title: str, description: str):
super().__init__()
self.title = title
self.description = description
class TaskCompleted(Event):
def __init__(self, completed_by: str, completion_notes: str = None):
super().__init__()
self.completed_by = completed_by
self.completion_notes = completion_notes
def main():
# Setup client
client = EventStoreClient("esdb://localhost:2113?tls=false")
# Create task stream
task_id = "7d73-4d98-a605-a731a2c373c6"
stream = StreamName(category="Task", stream_id=task_id)
# Create task
created_event = TaskCreated(
title="Implement py-micro-plumberd",
description="Create Python version of micro-plumberd"
)
client.append_to_stream(stream, created_event)
# Complete task
completed_event = TaskCompleted(
completed_by="developer@example.com",
completion_notes="Successfully implemented core functionality"
)
client.append_to_stream(stream, completed_event)
print(f"Events written to stream: {stream}")
print("These events can now be read using C# micro-plumberd")
if __name__ == "__main__":
main()
Requirements
- Python 3.8+
- EventStore 20.6+
- esdbclient
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Integration Testing
The library includes integration tests to ensure compatibility between Python and C#:
# Run Python tests
pytest tests/
# Run C# integration tests (requires .NET SDK)
cd tests/csharp
dotnet test
Event Format Compatibility
To ensure C# compatibility, events written by py-micro-plumberd follow these conventions:
- Event ID: Lowercase UUID with dashes (e.g.,
"3fa85f64-5717-4562-b3fc-2c963f66afa6") - Metadata Format: JSON object with:
Created: ISO 8601 timestamp (e.g.,"2025-07-13T18:22:19.2192669+02:00")ClientHostName: Machine hostname (e.g.,"MARS")
- Event Data: JSON serialized with property names in PascalCase to match C# conventions
Links
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 py_micro_plumberd-0.1.8.tar.gz.
File metadata
- Download URL: py_micro_plumberd-0.1.8.tar.gz
- Upload date:
- Size: 25.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2bed449f0158454842493924798f4e307edd834ef3abcace431aaec79a0f7122
|
|
| MD5 |
fb5c62304a06d5e31df9e01c0fd7c8d2
|
|
| BLAKE2b-256 |
8f08d26d277be023aa6d11542c8e8b30e4e2cf8649f89b321b14b6fe15455606
|
File details
Details for the file py_micro_plumberd-0.1.8-py3-none-any.whl.
File metadata
- Download URL: py_micro_plumberd-0.1.8-py3-none-any.whl
- Upload date:
- Size: 11.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a74d9085d54f28c715d1041cf23cca53ea19035ef549b5844991444cad9e68b3
|
|
| MD5 |
662f711e86319116ca6d86cd7021c149
|
|
| BLAKE2b-256 |
f157222216d010488d60a742da6d88f0de09f8357eda4e03eb343f1b622b59c4
|