Metadata-Version: 2.5
Name: relaykit-tools
Version: 0.1.1
Summary: A tiny, dependency-free event bus for Python applications.
License-Expression: MIT
License-File: LICENSE
Keywords: event-bus,event-driven,events,publish-subscribe,pubsub
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown


# RelayKit Tools

**A tiny, dependency-free event bus for Python.**

RelayKit Tools lets different parts of your application communicate through
events without needing to know about each other.

## Features

- Simple publish/subscribe API
- Decorator-based event handlers
- One-time event listeners
- Wildcard listeners for observing events
- Remove listeners individually or clear them all
- Zero runtime dependencies
- Type-annotated Python API

## Installation

```bash
pip install relaykit-tools
```

## Quick start

```python
from relaykit_tools import EventBus

bus = EventBus()

def greet(name):
    print(f"Hello, {name}!")

bus.on("user.joined", greet)
bus.emit("user.joined", "Alex")

# Output: Hello, Alex!
```

## Use decorators

```python
from relaykit_tools import EventBus

bus = EventBus()

@bus.on("order.created")
def process_order(order_id):
    print(f"Processing order {order_id}")

bus.emit("order.created", 123)
```

## One-time listeners

A one-time listener removes itself before its first invocation.

```python
@bus.once("app.started")
def initialize():
    print("Application initialized")

bus.emit("app.started")
bus.emit("app.started")  # Does not invoke initialize again
```

## Wildcard listeners

Listen to events regardless of their names. Wildcard handlers receive
the event name as their first argument.

```python
@bus.on("*")
def log_event(event_name, *args, **kwargs):
    print(f"Event: {event_name}")

bus.emit("user.created", 42)
bus.emit("user.deleted", 42)
```

## Remove listeners

```python
def handle_message(message):
    print(message)

bus.on("message", handle_message)
bus.off("message", handle_message)

# Remove every listener for one event
bus.off("message")

# Remove every listener for every event
bus.clear()
```

## Inspect listeners

```python
bus.listener_count("message")  # Listeners for one event
bus.listener_count()           # All registered listeners
```

## Error handling

Handlers run in registration order. By default, if a handler raises
an exception, the exception propagates to the caller and subsequent
handlers are not invoked.

```python
try:
    bus.emit("task.started")
except Exception as exc:
    print(f"Event handler failed: {exc}")
```

## Limitations

- Event dispatch is synchronous.
- The event bus is not thread-safe.
- Handler exceptions stop the current dispatch.
- Event names are case-sensitive.
- Wildcard listeners use `"*"` as their event name.

## Requirements

Python 3.10 or newer.

## License

MIT
