Metadata-Version: 2.4
Name: cevent
Version: 1.0.0
Summary: C#-style event system for Python
Author-email: PippinStall <viacheslav.tsyplenkov@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/PippinStall/cevent
Project-URL: BugTracker, https://github.com/PippinStall/cevent/issues
Keywords: event,delegate,callback,observer,C#,signal,slots
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# 🪶 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
```bash
pip install cevent
```

### Or install locally from source
```bash
git clone https://github.com/PippinStall/cevent
cd cevent
pip install .
```

---

## 🚀 Quick Start

```python
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.

```python
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.

```python
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

```python
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:

```bash
pip install pytest
pytest
```

---

## 🧰 Async Compatibility

CEvent works seamlessly in asynchronous environments,  
though it does not depend on `asyncio`.

```python
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.

---
