eventbus-lite 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. eventbus_lite-1.0.0/PKG-INFO +443 -0
  2. eventbus_lite-1.0.0/README.MD +408 -0
  3. eventbus_lite-1.0.0/eventbus/__init__.py +67 -0
  4. eventbus_lite-1.0.0/eventbus/bus.py +565 -0
  5. eventbus_lite-1.0.0/eventbus/event.py +117 -0
  6. eventbus_lite-1.0.0/eventbus/exceptions.py +72 -0
  7. eventbus_lite-1.0.0/eventbus/matcher.py +141 -0
  8. eventbus_lite-1.0.0/eventbus/subscriber.py +46 -0
  9. eventbus_lite-1.0.0/eventbus_lite.egg-info/PKG-INFO +443 -0
  10. eventbus_lite-1.0.0/eventbus_lite.egg-info/SOURCES.txt +41 -0
  11. eventbus_lite-1.0.0/eventbus_lite.egg-info/dependency_links.txt +1 -0
  12. eventbus_lite-1.0.0/eventbus_lite.egg-info/requires.txt +16 -0
  13. eventbus_lite-1.0.0/eventbus_lite.egg-info/top_level.txt +1 -0
  14. eventbus_lite-1.0.0/pyproject.toml +63 -0
  15. eventbus_lite-1.0.0/setup.cfg +4 -0
  16. eventbus_lite-1.0.0/tests/test_callable_objects.py +59 -0
  17. eventbus_lite-1.0.0/tests/test_cancel.py +37 -0
  18. eventbus_lite-1.0.0/tests/test_context_manager.py +19 -0
  19. eventbus_lite-1.0.0/tests/test_dead_references.py +75 -0
  20. eventbus_lite-1.0.0/tests/test_decorator.py +34 -0
  21. eventbus_lite-1.0.0/tests/test_dispatch_cache.py +53 -0
  22. eventbus_lite-1.0.0/tests/test_duplicates.py +20 -0
  23. eventbus_lite-1.0.0/tests/test_error_event.py +72 -0
  24. eventbus_lite-1.0.0/tests/test_exceptions.py +58 -0
  25. eventbus_lite-1.0.0/tests/test_gc.py +27 -0
  26. eventbus_lite-1.0.0/tests/test_invalid_input.py +21 -0
  27. eventbus_lite-1.0.0/tests/test_locking.py +24 -0
  28. eventbus_lite-1.0.0/tests/test_matcher.py +25 -0
  29. eventbus_lite-1.0.0/tests/test_memory_leaks.py +29 -0
  30. eventbus_lite-1.0.0/tests/test_multiple_patterns.py +66 -0
  31. eventbus_lite-1.0.0/tests/test_once.py +36 -0
  32. eventbus_lite-1.0.0/tests/test_pattern_cache.py +70 -0
  33. eventbus_lite-1.0.0/tests/test_priority.py +33 -0
  34. eventbus_lite-1.0.0/tests/test_recursive_publish.py +89 -0
  35. eventbus_lite-1.0.0/tests/test_reentrancy.py +40 -0
  36. eventbus_lite-1.0.0/tests/test_stable_order.py +51 -0
  37. eventbus_lite-1.0.0/tests/test_stop_propagation.py +37 -0
  38. eventbus_lite-1.0.0/tests/test_stress.py +84 -0
  39. eventbus_lite-1.0.0/tests/test_strict_mode.py +16 -0
  40. eventbus_lite-1.0.0/tests/test_subscribe.py +42 -0
  41. eventbus_lite-1.0.0/tests/test_thread_safety.py +30 -0
  42. eventbus_lite-1.0.0/tests/test_unsubscribe.py +29 -0
  43. eventbus_lite-1.0.0/tests/test_weakref.py +53 -0
@@ -0,0 +1,443 @@
1
+ Metadata-Version: 2.4
2
+ Name: eventbus-lite
3
+ Version: 1.0.0
4
+ Summary: Lightweight thread-safe synchronous event bus for Python
5
+ Author: kupriyanovde
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/kupriyanovde/eventbus
8
+ Project-URL: Repository, https://github.com/kupriyanovde/eventbus
9
+ Project-URL: Issues, https://github.com/kupriyanovde/eventbus/issues
10
+ Keywords: eventbus,events,pubsub,observer,messaging,architecture,synchronous
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0; extra == "dev"
24
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
25
+ Requires-Dist: black>=23.0; extra == "dev"
26
+ Requires-Dist: flake8>=6.0; extra == "dev"
27
+ Requires-Dist: mypy>=1.0; extra == "dev"
28
+ Requires-Dist: pre-commit>=3.0; extra == "dev"
29
+ Provides-Extra: test
30
+ Requires-Dist: pytest>=7.0; extra == "test"
31
+ Requires-Dist: pytest-cov>=4.0; extra == "test"
32
+ Provides-Extra: docs
33
+ Requires-Dist: sphinx>=6.0; extra == "docs"
34
+ Requires-Dist: sphinx-rtd-theme>=1.3; extra == "docs"
35
+
36
+ # EventBus
37
+
38
+ Лёгкая потокобезопасная шина событий (publish/subscribe) для Python.
39
+
40
+ ## Возможности
41
+
42
+ * синхронная обработка событий;
43
+ * потокобезопасность;
44
+ * приоритеты обработчиков;
45
+ * стабильный порядок вызова;
46
+ * одноразовые подписки (`once`);
47
+ * декораторы регистрации;
48
+ * временные подписки через контекстный менеджер;
49
+ * поддержка шаблонов `*` и `**`;
50
+ * отмена события;
51
+ * остановка распространения события;
52
+ * слабые ссылки на методы и вызываемые объекты;
53
+ * автоматическое удаление уничтоженных подписчиков;
54
+ * кэширование маршрутизации событий;
55
+ * генерация событий об ошибках;
56
+ * строгий режим обработки исключений;
57
+ * отсутствие внешних зависимостей.
58
+
59
+ Поддерживаемые версии Python:
60
+
61
+ * Python 3.10+
62
+ * Python 3.11
63
+ * Python 3.12
64
+ * Python 3.13
65
+
66
+ ---
67
+
68
+ # Установка
69
+
70
+ ```bash
71
+ pip install eventbus
72
+ ```
73
+
74
+ ---
75
+
76
+ # Быстрый старт
77
+
78
+ ```python
79
+ from eventbus import EventBus
80
+
81
+ bus = EventBus()
82
+
83
+
84
+ def handler(event):
85
+ print(event.type)
86
+ print(event.data)
87
+
88
+
89
+ bus.subscribe(
90
+ "system/start",
91
+ handler
92
+ )
93
+
94
+ bus.publish(
95
+ "system/start",
96
+ version="1.0"
97
+ )
98
+ ```
99
+
100
+ Результат:
101
+
102
+ ```text
103
+ system/start
104
+ {'version': '1.0'}
105
+ ```
106
+
107
+ ---
108
+
109
+ # Объект Event
110
+
111
+ Каждое событие представлено экземпляром класса `Event`.
112
+
113
+ ```python
114
+ event.type
115
+ event.data
116
+ event.source
117
+ event.timestamp
118
+ event.result
119
+ event.cancelled
120
+ event.propagation_stopped
121
+ event.exception
122
+ ```
123
+
124
+ ---
125
+
126
+ # Подписка
127
+
128
+ ```python
129
+ bus.subscribe(
130
+ "system/start",
131
+ handler
132
+ )
133
+ ```
134
+
135
+ ---
136
+
137
+ # Публикация
138
+
139
+ ```python
140
+ event = bus.publish(
141
+ "system/start",
142
+ value=123
143
+ )
144
+ ```
145
+
146
+ Метод `publish()` возвращает объект `Event`.
147
+
148
+ ---
149
+
150
+ # Приоритеты
151
+
152
+ Обработчики вызываются в порядке возрастания приоритета.
153
+
154
+ ```python
155
+ bus.subscribe(
156
+ "test",
157
+ first_handler,
158
+ priority=100
159
+ )
160
+
161
+ bus.subscribe(
162
+ "test",
163
+ second_handler,
164
+ priority=200
165
+ )
166
+ ```
167
+
168
+ Сначала будет вызван `first_handler`.
169
+
170
+ ---
171
+
172
+ # Стабильный порядок
173
+
174
+ Если приоритеты одинаковы, обработчики вызываются в порядке регистрации.
175
+
176
+ ```python
177
+ bus.subscribe("test", h1)
178
+ bus.subscribe("test", h2)
179
+ bus.subscribe("test", h3)
180
+ ```
181
+
182
+ Порядок вызова:
183
+
184
+ ```text
185
+ h1
186
+ h2
187
+ h3
188
+ ```
189
+
190
+ ---
191
+
192
+ # Одноразовые обработчики
193
+
194
+ ```python
195
+ bus.subscribe(
196
+ "system/start",
197
+ handler,
198
+ once=True
199
+ )
200
+ ```
201
+
202
+ После первого вызова обработчик будет автоматически удалён.
203
+
204
+ ---
205
+
206
+ # Декораторы
207
+
208
+ ## on()
209
+
210
+ ```python
211
+ @bus.on("system/start")
212
+ def on_start(event):
213
+ print("started")
214
+ ```
215
+
216
+ ## once()
217
+
218
+ ```python
219
+ @bus.once("system/start")
220
+ def initialize(event):
221
+ print("called once")
222
+ ```
223
+
224
+ ---
225
+
226
+ # Удаление подписки
227
+
228
+ ```python
229
+ bus.unsubscribe(
230
+ "system/start",
231
+ handler
232
+ )
233
+ ```
234
+
235
+ ---
236
+
237
+ # Контекстный менеджер
238
+
239
+ ```python
240
+ with bus.subscription(
241
+ "system/start",
242
+ handler
243
+ ):
244
+ bus.publish("system/start")
245
+
246
+ # подписка автоматически удалена
247
+ ```
248
+
249
+ ---
250
+
251
+ # Шаблоны
252
+
253
+ ## Точное совпадение
254
+
255
+ ```python
256
+ system/start
257
+ ```
258
+
259
+ ---
260
+
261
+ ## *
262
+
263
+ Один сегмент.
264
+
265
+ ```python
266
+ system/*
267
+ ```
268
+
269
+ Подходит для:
270
+
271
+ ```text
272
+ system/start
273
+ system/stop
274
+ ```
275
+
276
+ ---
277
+
278
+ ## **
279
+
280
+ Любое количество сегментов.
281
+
282
+ ```python
283
+ system/**
284
+ ```
285
+
286
+ Подходит для:
287
+
288
+ ```text
289
+ system
290
+ system/start
291
+ system/core/start
292
+ system/core/network/start
293
+ ```
294
+
295
+ ---
296
+
297
+ # Отмена события
298
+
299
+ ```python
300
+ def handler(event):
301
+ event.cancel("denied")
302
+ ```
303
+
304
+ После вызова:
305
+
306
+ ```python
307
+ event.cancelled == True
308
+ ```
309
+
310
+ Оставшиеся обработчики вызваны не будут.
311
+
312
+ Результат доступен через:
313
+
314
+ ```python
315
+ event.result
316
+ ```
317
+
318
+ ---
319
+
320
+ # Остановка распространения
321
+
322
+ ```python
323
+ def handler(event):
324
+ event.stop_propagation()
325
+ ```
326
+
327
+ Оставшиеся обработчики не вызываются, однако событие не считается отменённым.
328
+
329
+ ```python
330
+ event.cancelled == False
331
+ ```
332
+
333
+ ---
334
+
335
+ # Исключения
336
+
337
+ По умолчанию исключения внутри обработчиков не прерывают работу EventBus.
338
+
339
+ ```python
340
+ def handler(event):
341
+ raise RuntimeError()
342
+ ```
343
+
344
+ Исключение сохраняется:
345
+
346
+ ```python
347
+ event.exception
348
+ ```
349
+
350
+ Также автоматически публикуется событие:
351
+
352
+ ```text
353
+ system/error/event
354
+ ```
355
+
356
+ ---
357
+
358
+ # Строгий режим
359
+
360
+ ```python
361
+ bus = EventBus(strict=True)
362
+ ```
363
+
364
+ В этом режиме исключение приводит к возбуждению:
365
+
366
+ ```python
367
+ EventDispatchError
368
+ ```
369
+
370
+ ---
371
+
372
+ # Слабые ссылки
373
+
374
+ Методы объектов и вызываемые экземпляры хранятся через слабые ссылки.
375
+
376
+ Если объект уничтожен сборщиком мусора, подписка удаляется автоматически.
377
+
378
+ ```python
379
+ class Receiver:
380
+
381
+ def on_event(self, event):
382
+ pass
383
+
384
+
385
+ receiver = Receiver()
386
+
387
+ bus.subscribe(
388
+ "test",
389
+ receiver.on_event
390
+ )
391
+ ```
392
+
393
+ ---
394
+
395
+ # Потокобезопасность
396
+
397
+ Все операции регистрации, удаления подписчиков и публикации событий являются потокобезопасными.
398
+
399
+ ```python
400
+ from threading import Thread
401
+ ```
402
+
403
+ Один экземпляр `EventBus` может безопасно использоваться несколькими потоками одновременно.
404
+
405
+ ---
406
+
407
+ # Исключения библиотеки
408
+
409
+ ## EventBusError
410
+
411
+ Базовый класс всех исключений.
412
+
413
+ ## InvalidPatternError
414
+
415
+ Некорректный шаблон события.
416
+
417
+ ## InvalidHandlerError
418
+
419
+ Переданный объект не является вызываемым.
420
+
421
+ ## DuplicateSubscriptionError
422
+
423
+ Ошибка повторной регистрации.
424
+
425
+ ## EventDispatchError
426
+
427
+ Ошибка обработки события.
428
+
429
+ ---
430
+
431
+ # Тестирование
432
+
433
+ Проект покрыт тестами.
434
+
435
+ ```bash
436
+ pytest
437
+ ```
438
+
439
+ ---
440
+
441
+ # Лицензия
442
+
443
+ MIT License