Skip to main content

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:

  1. Event ID: Lowercase UUID with dashes (e.g., "3fa85f64-5717-4562-b3fc-2c963f66afa6")
  2. 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")
  3. Event Data: JSON serialized with property names in PascalCase to match C# conventions

Links

Release files for py-micro-plumberd 0.1.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-micro-plumberd 0.1.9
File Size Uploaded
py_micro_plumberd-0.1.9.tar.gz 26.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for py-micro-plumberd 0.1.9
File Interpreter ABI Platform
py_micro_plumberd-0.1.9-py3-none-any.whl Python 3 none any Details

Total release size: 37.7 kB

Release files / py_micro_plumberd-0.1.9.tar.gz

Download URL py_micro_plumberd-0.1.9.tar.gz
Size 26.1 kB
Tags Source
SHA-256 checksum
How to use checksums
bb7228664bd2c15ac0255711b90a6acb0a1922614dca4f101127d32e03786f97
BLAKE2b-256 checksum
How to use checksums
2d918e9216e2a364c4bccf0c613288a9c96686fcb584364303fd42dc5f8c248f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release files / py_micro_plumberd-0.1.9-py3-none-any.whl

Download URL py_micro_plumberd-0.1.9-py3-none-any.whl
Size 11.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c8fe8ac470ce696b2d024a8abad6484d5a22f2c6d1c3d56f306f710f44eaf5f7
BLAKE2b-256 checksum
How to use checksums
1574597e8721f8b773a080c3496ae40dbf7a6572f903d3104afefcb9af41fee0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.1.9 This release

2 release files

0.1.8

2 release files

0.1.6

2 release files

0.1.5

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page