PyEventCloud
CloudEvents SDK for Python - A complete, type-safe implementation of the CloudEvents specification with zero dependencies.
Installation
pip install pyeventcloud
Quick Start
Creating CloudEvents
from pyeventcloud import CloudEvent, create_event
# Create with auto-generated ID
event = create_event(
source="https://example.com/source",
type="com.example.event",
data={"message": "Hello CloudEvents!"}
)
# Create with explicit ID
event = CloudEvent(
id="custom-id-123",
source="https://example.com/source",
type="com.example.event",
specversion="1.0",
datacontenttype="application/json",
data={"key": "value"}
)
# Access attributes directly
print(event.id) # custom-id-123
print(event.source) # https://example.com/source
print(event.data) # {'key': 'value'}
JSON Serialization
from pyeventcloud import to_json, from_json
# Serialize to JSON
json_str = to_json(event)
# Deserialize from JSON
event = from_json(json_str)
# Batch operations
from pyeventcloud import to_json_batch, from_json_batch
events = [event1, event2, event3]
json_str = to_json_batch(events)
events = from_json_batch(json_str)
HTTP Binding
from pyeventcloud import HTTPBinding, JSONFormatter
binding = HTTPBinding()
formatter = JSONFormatter()
# Structured content mode (event in body)
body, headers = binding.to_structured(event, formatter)
# body is bytes, headers is dict[str, str]
# Content-Type: application/cloudevents+json
# Binary content mode (attributes in headers)
body, headers = binding.to_binary(event)
# headers["ce-id"], headers["ce-source"], etc.
# body contains event data
# Parse from HTTP request
event = binding.from_structured(request.body, request.headers, formatter)
event = binding.from_binary(request.body, request.headers)
Kafka Binding
from pyeventcloud import KafkaBinding, JSONFormatter
binding = KafkaBinding()
formatter = JSONFormatter()
# Structured content mode
message = binding.to_structured(event, formatter)
# Returns: KafkaMessage with value, headers, key
# Binary content mode
message = binding.to_binary(event)
# message["value"]: bytes
# message["headers"]: list[tuple[str, bytes]]
# message["key"]: bytes | None
# 'partitionkey' extension maps to Kafka message key
event = CloudEvent(
id="123",
source="app",
type="order.created",
partitionkey="customer-456" # Maps to Kafka partition key
)
message = binding.to_binary(event)
# message["key"] == b"customer-456"
Extensions
from pyeventcloud import CloudEvent, register_extension
# Built-in partitionkey extension
event = CloudEvent(
id="123",
source="app",
type="event.type",
partitionkey="partition-1" # Built-in extension
)
# Custom extensions
event = CloudEvent(
id="123",
source="app",
type="event.type",
customextension="value" # Any custom extension
)
# Access extensions
print(event.extensions["customextension"]) # "value"
# Register custom extension
class MyExtension:
name = "myext"
attributes = {"myfield": str}
def validate(self, event):
value = event.extensions.get("myfield")
if value and not isinstance(value, str):
raise ValidationError("myfield must be a string")
def get_attributes(self, event):
return {"myfield": event.extensions.get("myfield")}
register_extension(MyExtension())
Factory Pattern
from pyeventcloud import JSONFormatter, from_dict
formatter = JSONFormatter()
# Custom factory for event creation
def custom_factory(data: dict) -> CloudEvent:
# Add metadata or transform data
data["id"] = f"prefix-{data['id']}"
return from_dict(data)
event = formatter.deserialize(json_str, event_factory=custom_factory)
API Reference
Core
CloudEvent- Main CloudEvent classcreate_event()- Factory function with auto-generated IDfrom_dict()- Create CloudEvent from dictionary
Formats
JSONFormatter- JSON serialization/deserializationto_json()- Serialize single event to JSONfrom_json()- Deserialize single event from JSONto_json_batch()- Serialize multiple eventsfrom_json_batch()- Deserialize multiple events
Bindings
HTTPBinding- HTTP protocol binding (structured & binary modes)KafkaBinding- Kafka protocol binding (structured & binary modes)EventSerializer- Protocol for custom serializers
Extensions
PartitioningExtension- Built-in partitionkey extensionregister_extension()- Register custom extensionget_extension()- Get registered extensionExtensionRegistry- Extension registry class
Exceptions
CloudEventError- Base exceptionValidationError- Validation failuresSerializationError- Serialization/deserialization errorsBindingError- Protocol binding errorsExtensionError- Extension-related errors
Design Philosophy
Fail-Fast Validation
PyEventCloud validates events immediately when created, raising clear errors:
# Invalid event raises ValidationError immediately
try:
event = CloudEvent(
id="", # Empty ID
source="https://example.com",
type="event.type"
)
except ValidationError as e:
print(e) # "id must be a non-empty string"
print(e.attribute) # "id"
Format Decoupling
Bindings are completely decoupled from formats via the EventSerializer protocol:
# Any serializer implementing the protocol works
binding = HTTPBinding()
body, headers = binding.to_structured(event, JSONFormatter())
body, headers = binding.to_structured(event, AvroFormatter()) # Future
body, headers = binding.to_structured(event, ProtobufFormatter()) # Future
Development
Setup
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone the repository
git clone https://github.com/plugarut/pyeventcloud.git
cd pyeventcloud
# Install dependencies
uv sync --dev
Running Tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=src/pyeventcloud --cov-report=term-missing
# Run type checking
uv run mypy src/
# Run specific test file
uv run pytest tests/unit/test_event.py -v
Building
# Build distribution packages
uv build
# Check build artifacts
ls -lh dist/
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass and mypy is happy
- Submit a pull request
License
Apache License 2.0 - See LICENSE for details.
Acknowledgments
- Inspired by the CloudEvents Python SDK
- Implements CloudEvents v1.0
- HTTP binding follows HTTP Protocol Binding
- Kafka binding follows Kafka Protocol Binding
Links
Metadata
Release files for pyeventcloud 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyeventcloud-0.1.0.tar.gz | 20.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyeventcloud-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.9 kB
Release files / pyeventcloud-0.1.0.tar.gz
| Download URL | pyeventcloud-0.1.0.tar.gz |
|---|---|
| Size | 20.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
97530fc8216a6a4779a62f270c37260896f1bc345d9966ff793ccfec2b4a48a2
|
|
BLAKE2b-256 checksum How to use checksums |
5c19f488b82fff88b10a89ff8dc0ec31822ce3dec08e8f80ec0c6cc417812451
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2025.
Transparency logRelease files / pyeventcloud-0.1.0-py3-none-any.whl
| Download URL | pyeventcloud-0.1.0-py3-none-any.whl |
|---|---|
| Size | 30.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6264d97f06e3764e16c76f7c4ed67d6f3c280a9d1eb301dade42fdfb1aeb6aa6
|
|
BLAKE2b-256 checksum How to use checksums |
e642696774490e15c965e971794edb515c366e8d6203bd94c6ce743c2eb0ffc3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2025.
Transparency log