Metadata-Version: 2.4
Name: eventbus-lite
Version: 1.0.0
Summary: Lightweight thread-safe synchronous event bus for Python
Author: kupriyanovde
License: MIT
Project-URL: Homepage, https://github.com/kupriyanovde/eventbus
Project-URL: Repository, https://github.com/kupriyanovde/eventbus
Project-URL: Issues, https://github.com/kupriyanovde/eventbus/issues
Keywords: eventbus,events,pubsub,observer,messaging,architecture,synchronous
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
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
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: flake8>=6.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: pre-commit>=3.0; extra == "dev"
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Requires-Dist: pytest-cov>=4.0; extra == "test"
Provides-Extra: docs
Requires-Dist: sphinx>=6.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=1.3; extra == "docs"

# EventBus

Лёгкая потокобезопасная шина событий (publish/subscribe) для Python.

## Возможности

* синхронная обработка событий;
* потокобезопасность;
* приоритеты обработчиков;
* стабильный порядок вызова;
* одноразовые подписки (`once`);
* декораторы регистрации;
* временные подписки через контекстный менеджер;
* поддержка шаблонов `*` и `**`;
* отмена события;
* остановка распространения события;
* слабые ссылки на методы и вызываемые объекты;
* автоматическое удаление уничтоженных подписчиков;
* кэширование маршрутизации событий;
* генерация событий об ошибках;
* строгий режим обработки исключений;
* отсутствие внешних зависимостей.

Поддерживаемые версии Python:

* Python 3.10+
* Python 3.11
* Python 3.12
* Python 3.13

---

# Установка

```bash
pip install eventbus
```

---

# Быстрый старт

```python
from eventbus import EventBus

bus = EventBus()


def handler(event):
    print(event.type)
    print(event.data)


bus.subscribe(
    "system/start",
    handler
)

bus.publish(
    "system/start",
    version="1.0"
)
```

Результат:

```text
system/start
{'version': '1.0'}
```

---

# Объект Event

Каждое событие представлено экземпляром класса `Event`.

```python
event.type
event.data
event.source
event.timestamp
event.result
event.cancelled
event.propagation_stopped
event.exception
```

---

# Подписка

```python
bus.subscribe(
    "system/start",
    handler
)
```

---

# Публикация

```python
event = bus.publish(
    "system/start",
    value=123
)
```

Метод `publish()` возвращает объект `Event`.

---

# Приоритеты

Обработчики вызываются в порядке возрастания приоритета.

```python
bus.subscribe(
    "test",
    first_handler,
    priority=100
)

bus.subscribe(
    "test",
    second_handler,
    priority=200
)
```

Сначала будет вызван `first_handler`.

---

# Стабильный порядок

Если приоритеты одинаковы, обработчики вызываются в порядке регистрации.

```python
bus.subscribe("test", h1)
bus.subscribe("test", h2)
bus.subscribe("test", h3)
```

Порядок вызова:

```text
h1
h2
h3
```

---

# Одноразовые обработчики

```python
bus.subscribe(
    "system/start",
    handler,
    once=True
)
```

После первого вызова обработчик будет автоматически удалён.

---

# Декораторы

## on()

```python
@bus.on("system/start")
def on_start(event):
    print("started")
```

## once()

```python
@bus.once("system/start")
def initialize(event):
    print("called once")
```

---

# Удаление подписки

```python
bus.unsubscribe(
    "system/start",
    handler
)
```

---

# Контекстный менеджер

```python
with bus.subscription(
    "system/start",
    handler
):
    bus.publish("system/start")

# подписка автоматически удалена
```

---

# Шаблоны

## Точное совпадение

```python
system/start
```

---

## *

Один сегмент.

```python
system/*
```

Подходит для:

```text
system/start
system/stop
```

---

## **

Любое количество сегментов.

```python
system/**
```

Подходит для:

```text
system
system/start
system/core/start
system/core/network/start
```

---

# Отмена события

```python
def handler(event):
    event.cancel("denied")
```

После вызова:

```python
event.cancelled == True
```

Оставшиеся обработчики вызваны не будут.

Результат доступен через:

```python
event.result
```

---

# Остановка распространения

```python
def handler(event):
    event.stop_propagation()
```

Оставшиеся обработчики не вызываются, однако событие не считается отменённым.

```python
event.cancelled == False
```

---

# Исключения

По умолчанию исключения внутри обработчиков не прерывают работу EventBus.

```python
def handler(event):
    raise RuntimeError()
```

Исключение сохраняется:

```python
event.exception
```

Также автоматически публикуется событие:

```text
system/error/event
```

---

# Строгий режим

```python
bus = EventBus(strict=True)
```

В этом режиме исключение приводит к возбуждению:

```python
EventDispatchError
```

---

# Слабые ссылки

Методы объектов и вызываемые экземпляры хранятся через слабые ссылки.

Если объект уничтожен сборщиком мусора, подписка удаляется автоматически.

```python
class Receiver:

    def on_event(self, event):
        pass


receiver = Receiver()

bus.subscribe(
    "test",
    receiver.on_event
)
```

---

# Потокобезопасность

Все операции регистрации, удаления подписчиков и публикации событий являются потокобезопасными.

```python
from threading import Thread
```

Один экземпляр `EventBus` может безопасно использоваться несколькими потоками одновременно.

---

# Исключения библиотеки

## EventBusError

Базовый класс всех исключений.

## InvalidPatternError

Некорректный шаблон события.

## InvalidHandlerError

Переданный объект не является вызываемым.

## DuplicateSubscriptionError

Ошибка повторной регистрации.

## EventDispatchError

Ошибка обработки события.

---

# Тестирование

Проект покрыт тестами.

```bash
pytest
```

---

# Лицензия

MIT License
