A high-performance, simple-structured event system, relies on asyncio
Project description
一个高性能,结构简洁,依赖于 Python内置库asyncio 的事件系统, 设计灵感来自Graia BroadcastControl。
项目仍处于开发阶段,部分内容可能会有较大改变
安装
从 PyPI 安装
pip install arclet-letoderea
样例
基本使用
import asyncio
import arclet.letoderea as le
@le.make_event
class TestEvent:
name: str
@le.on_global
async def test_subscriber(name: str):
print(name)
async def main():
await le.publish(TestEvent("Letoderea"))
asyncio.run(main())
依赖注入
import asyncio
import arclet.letoderea as le
@le.make_event
class TestEvent:
name: str
@le.depends()
async def get_msg(event):
return f"Hello, {event.name}"
@le.on(TestEvent)
async def test_subscriber(msg: str = get_msg):
print(msg)
async def main():
await le.publish(TestEvent("Letoderea"))
asyncio.run(main())
通信
import asyncio
import random
import arclet.letoderea as le
@le.make_event
class Event:
name: str
@le.make_event(name="rand")
class RandomData:
seed: int
def check_result(self, value) -> le.Result[float] | None: ...
@le.on(RandomData)
def random_subscriber(seed: int):
return random.Random(seed).random()
@le.on(Event)
async def event_subscriber(event: Event):
print(f"Event: {event.name}")
result = await le.post(RandomData(42))
print(f"Random: {result.value}")
async def main():
await le.publish(Event("Letoderea"))
asyncio.run(main())
过滤
import asyncio
import arclet.letoderea as le
@le.make_event
class Event:
name: str
flag: bool = False
@le.on_global
@le.enter_if(le.deref(Event).name == "Letoderea")
async def sub_if_letoderea():
...
@le.on_global
@le.enter_if & le.deref(Event).flag & (le.deref(Event).name != "Letoderea")
async def sub_if_not_letoderea():
...
async def main():
await le.publish(Event("Letoderea"))
await le.publish(Event("OtherEvent", True))
asyncio.run(main())
说明
事件
- 事件可以是任何对象,只要实现了
gather异步方法, 或使用define并传入supplier参数,或使用@gather装饰器注册了 supplier 方法 gather方法的参数为Contexts类型,用于传递上下文信息- 事件可以通过
gather方法将自身想要传递的信息整合进Contexts中 - 事件可以携带
Provider,它们会在事件被订阅时注入到订阅者中 - 订阅子类事件时,父类事件的
Provider会被继承 - 订阅父类事件时,其子类事件也会被分发给订阅者
订阅
- 通过
Scope.register,on,use或on_global装饰器可以将一个函数注册为事件的订阅者 - 上述方法会返回
Subscriber类型对象,可以通过其.dispose方法取消订阅 - 订阅者的参数可以是任何类型,事件系统会尝试从
Contexts中查找对应的值并注入 - 默认情况下
event为名字的参数会被注入为事件的实例 - 订阅者可以设置优先级,值越小优先级越高
上下文
Contexts类型是一个dict的子类,用于传递上下文信息,除此之外与dict没有区别Contexts默认包含$event键,其值为事件的实例Contexts默认包含$subscriber键,其值为订阅者的实例- 在订阅者的函数执行后,其结果会被存储在
Contexts中,键为$result - 若在解析参数时抛出异常,异常值会被存储在
Contexts中,键为$error
依赖注入
Provider[T]负责管理参数的注入, 其会尝试从Contexts中选择需求的参数返回- 对于订阅者的每个参数,在订阅者注册后,事件系统会遍历该订阅者拥有的所有
Provider, 并依次调用Provider.validate方法,如果返回True,则将该Provider绑定到该参数上。 当进行依赖解析时,事件系统会遍历该参数绑定的所有Provider,并依次调用Provider.__call__方法, 如果返回值不为None,则将该返回值注入到该参数中。 Provider.validate方法用于验证订阅函数的参数是否为该Provider可绑定的参数。默认实现为检查目标参数的类型声明是否为T。 也可以通过重写该方法来实现自定义的验证逻辑。Provider.__call__方法用于从Contexts中获取参数- 原则上
Provider只负责注入单一类型的参数。若想处理多个类型的参数,可以声明自己为Provider[Union[A, B, ...]]类型, 并在Provider.validate方法中进行自定义的逻辑判断。但更推荐的做法是构造多个Provider,并将其绑定到同一个参数上。 - 对于特殊的辅助器
Depend,事件系统会将其作为特殊的Provider处理,绑定了Depend的参数在解析时将直接调用设置在Depend上的方法。 Provider可以设置优先级,值越小优先级越高- 另有
ProviderFactory,用于集成多个Provider的分配,以方便event.providers的设置
事件发布
- 一般情况下通过
publish或post方法可以发布一个事件让事件系统进行处理 publish会处理所有合适的订阅者,而post会在某一个订阅者返回了有效值后停止处理,并返回该值Publisher.validate方法用于验证该事件是否为该发布者的订阅者所关注的事件Publisher.supply方法用于让事件系统主动获取事件并分发给所有订阅者use,Scope.register可以指定Publisher- 通过
define可以便捷的定义发布者,并在.use等处通过定义的名字引用
层次
Scope类负责管理订阅者与事件的交互- 所有的订阅者都会存储在
Scope中 publish与post可以指定Scope
传播
Subscriber类型对象被创建后,其能通过propagate方法来设置订阅的同级传播。- 传播中的订阅者会在当前订阅者执行后或执行前执行,取决于
propagate的参数prepend。 向后传播的订阅者能拿到上一个订阅者的返回值。 - 传播中的订阅者会继承当前订阅者的
Provider。 - 传播中的订阅者可以通过返回特殊值
STOP来中止同级传播。 - 对于传播中的订阅者,若其依赖注入的参数未满足,则会尝试延迟执行。若所有的传播订阅者都无法满足其依赖注入的参数,则会抛出异常。
propagate方法可以为传播订阅者设置优先级,值越小优先级越高。propagate方法可以接受特殊类型Propagator, 其有一个compose方法,用来提供一系列的传播订阅者。
开源协议
本实现以 MIT 为开源协议。
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
arclet_letoderea-0.19.5.tar.gz
(34.9 kB
view details)
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 arclet_letoderea-0.19.5.tar.gz.
File metadata
- Download URL: arclet_letoderea-0.19.5.tar.gz
- Upload date:
- Size: 34.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: pdm/2.25.6 CPython/3.11.7 Windows/10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23c87cd03f8f16bff6d3f1b83174b43f53cc6b4cf4dbf13a126d20d6f8706e9d
|
|
| MD5 |
2dea1952dcc81dcf4f1116c2c62212a5
|
|
| BLAKE2b-256 |
0e687c47b92f0f25faf7112c1d45eeea027fb46388e39d09b8c0b83d644c13c7
|
File details
Details for the file arclet_letoderea-0.19.5-py3-none-any.whl.
File metadata
- Download URL: arclet_letoderea-0.19.5-py3-none-any.whl
- Upload date:
- Size: 30.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: pdm/2.25.6 CPython/3.11.7 Windows/10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f1a4a8cf538f97e96949ce1cec62278e4068d89fc22689acaf51ca5a6a7cbd9
|
|
| MD5 |
8ed4e57260ac66a1ddf78526378a32ae
|
|
| BLAKE2b-256 |
420108fc3d0be84237d285371863fdcf414cd2068f425a7cee4a3c9a2f2044ea
|