C#-style event system for Python
Project description
🪶 CEvent
CEvent is a lightweight Python library that brings C#-style event mechanics to Python.
It provides a clean and intuitive way to manage event subscriptions and callbacks using += and -= operators.
✨ Features
- ✅ Subscribe and unsubscribe with
+=/-= - ✅ Invoke events explicitly via
.invoke() - ✅ Pass positional and keyword arguments (
*args,**kwargs) - ✅ Prevent duplicate subscriptions
- ✅ Safely call handlers — skips incompatible ones
- ✅ Clear all subscribers with
.clear() - ✅ No external dependencies — pure Python
💾 Installation
From PyPI
pip install cevent
Or install locally from source
git clone https://github.com/PippinStall/cevent
cd cevent
pip install .
🚀 Quick Start
from cevent import CEvent
# Create an event
on_click = CEvent()
# Subscribe handlers
def greet(name):
print(f"Hello, {name}!")
def goodbye(name):
print(f"Goodbye, {name}!")
on_click += greet
on_click += goodbye
# Invoke the event
on_click.invoke("World")
# → Hello, World!
# → Goodbye, World!
# Unsubscribe a handler
on_click -= goodbye
⚙️ Publisher–Subscriber Example
CEvent can be used as a lightweight publisher/subscriber (observer) system.
from cevent import CEvent
class Button:
def __init__(self):
self.on_click = CEvent()
def click(self):
print("[Button] Click detected.")
self.on_click.invoke(self)
class Logger:
def log_click(self, sender):
print(f"[Logger] {sender} clicked.")
button = Button()
logger = Logger()
button.on_click += logger.log_click
button.click()
📤 Output:
[Button] Click detected.
[Logger] <__main__.Button object at 0x...> clicked.
🧩 Example with Argument Safety
If different handlers have incompatible function signatures,
CEvent will skip them safely and display a warning.
from cevent import CEvent
event = CEvent()
event += lambda: print("Handler without arguments")
event += lambda x: print(f"Handler with arg: {x}")
event.invoke(42)
📤 Output:
Handler with arg: 42
[CEvent] Warning: some handlers failed to invoke:
- <function <lambda> at 0x...>: <lambda>() takes 0 positional arguments but 1 was given
This makes event handling safe even when subscribers have different parameter requirements.
🧹 Managing Subscribers
from cevent import CEvent
event = CEvent()
event += lambda: print("One")
event += lambda: print("Two")
# List current subscribers
print(list(event))
# → [<function <lambda> at ...>, <function <lambda> at ...>]
# Clear all
event.clear()
print(list(event)) # → []
🧠 Why Use CEvent?
| Problem | CEvent Solution |
|---|---|
| Manual callback management | Simple += / -= operators |
| Duplicate subscriptions | Automatically prevented |
| Different argument signatures | Safe invocation with warning |
| Hard-to-read callback lists | repr() and iteration supported |
| Too much boilerplate | Minimal, expressive, and readable |
🧪 Testing
CEvent includes a minimal test suite.
You can run it locally with:
pip install pytest
pytest
🧰 Async Compatibility
CEvent works seamlessly in asynchronous environments,
though it does not depend on asyncio.
import asyncio
from cevent import CEvent
on_ready = CEvent()
async def prepare():
await asyncio.sleep(1)
print("System ready.")
on_ready.invoke()
def notify():
print("✅ Received ready event!")
on_ready += notify
asyncio.run(prepare())
📤 Output:
System ready.
✅ Received ready event!
📦 Package Structure
cevent/
├── cevent/
│ ├── __init__.py
│ └── core.py
├── tests/
│ └── test_cevent.py
├── LICENSE
├── README.md
└── pyproject.toml
🔖 Version
CEvent v1.0.0
📜 License
MIT License — free for personal and commercial use.
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 cevent-1.0.0.tar.gz.
File metadata
- Download URL: cevent-1.0.0.tar.gz
- Upload date:
- Size: 4.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
312500c7be3bf6de49989204a6e64d41864f88d7893be1a3b558274bd836559a
|
|
| MD5 |
234bfc326d1919bbe989e35b7e205d75
|
|
| BLAKE2b-256 |
e90d9ea0f48dafbcc18df3180e3d971d0c5ffb95f3f47004e2e721ca51857648
|
File details
Details for the file cevent-1.0.0-py3-none-any.whl.
File metadata
- Download URL: cevent-1.0.0-py3-none-any.whl
- Upload date:
- Size: 4.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6328915c95de78a370ace1e62799189624416db159a688ffd5ab63373b56d349
|
|
| MD5 |
9271c70f6c00ac805076fcb22da30f64
|
|
| BLAKE2b-256 |
adccb248e340aa5bbc6c17be65f21f4248c8a80ff06351157fb633c34ea715a4
|