virid-std 0.1.0__py3-none-any.whl

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.

Potentially problematic release.


This version of virid-std might be problematic. Click here for more details.

virid/std/__init__.py ADDED
@@ -0,0 +1,8 @@
1
+ """
2
+ Copyright (c) 2026-present Ailrid.
3
+ Licensed under the Apache License, Version 2.0.
4
+ Project: Virid
5
+ """
6
+
7
+ from .plugin import StdPlugin
8
+ from .utils import execute_group, next_tick, execute_block
virid/std/plugin.py ADDED
@@ -0,0 +1,23 @@
1
+ """
2
+ Copyright (c) 2026-present Ailrid.
3
+ Licensed under the Apache License, Version 2.0.
4
+ Project: Virid
5
+ """
6
+
7
+ from virid.core import ViridApp
8
+ from .utils import activate_utils
9
+
10
+
11
+ def activate_plugin(app: ViridApp):
12
+ activate_utils(app)
13
+
14
+
15
+ class Plugin:
16
+ name = "std"
17
+
18
+ # 将返回值改为 None,以契合 Protocol 的声明
19
+ def install(self, app: ViridApp, options: None) -> None:
20
+ activate_plugin(app)
21
+
22
+
23
+ StdPlugin = Plugin()
@@ -0,0 +1,14 @@
1
+ """
2
+ Copyright (c) 2026-present Ailrid.
3
+ Licensed under the Apache License, Version 2.0.
4
+ Project: Virid
5
+ """
6
+
7
+ from .execute_group import activate_group_messages, execute_group, execute_block
8
+ from .nexttick import activate_next_tick, next_tick
9
+ from virid.core import ViridApp
10
+
11
+
12
+ def activate_utils(app: ViridApp):
13
+ activate_group_messages(app)
14
+ activate_next_tick(app)
@@ -0,0 +1,136 @@
1
+ """
2
+ Copyright (c) 2026-present Ailrid.
3
+ Licensed under the Apache License, Version 2.0.
4
+ Project: Virid
5
+ """
6
+
7
+ from typing import Any, Callable
8
+ from virid.core import EventMessage, ViridApp, MessageWriter, ExecuteHookContext
9
+ from contextlib import contextmanager
10
+
11
+ # 每个 key 中缓存的执行组队列及状态映射
12
+ execute_group_map: dict[str, list[dict[str, Any]]] = {}
13
+ message_key_map: dict[int, str] = {} # 键类型改为 int,用于存放 id(message)
14
+ key_message_map: dict[str, list[EventMessage]] = {}
15
+ call_back_map: dict[str, Callable[[bool], None]] = {}
16
+
17
+
18
+ def clear_group(group_id: str) -> None:
19
+ for message in key_message_map[group_id]:
20
+ message_key_map.pop(id(message), None) # 使用 id(message) 释放
21
+ key_message_map.pop(group_id, None)
22
+ execute_group_map.pop(group_id, None)
23
+ call_back_map.pop(group_id, None)
24
+
25
+
26
+ def after_execute_hook(
27
+ message: EventMessage,
28
+ _hook_context: ExecuteHookContext,
29
+ success: bool,
30
+ ) -> None:
31
+ key = message_key_map.get(id(message)) # 使用 id(message) 获取
32
+ if key:
33
+ execute_group = execute_group_map.get(key)
34
+ if execute_group is None:
35
+ return
36
+
37
+ if success:
38
+ # 只有当前任务执行成功,才继续下一个
39
+ if len(execute_group) > 0:
40
+ context = execute_group.pop(0)
41
+ resolve = context["resolve"]
42
+ resolve()
43
+ # 全部执行完成
44
+ if len(execute_group) == 0:
45
+ callback = call_back_map.get(key)
46
+ if callback:
47
+ callback(True)
48
+ clear_group(key)
49
+ else:
50
+ callback = call_back_map.get(key)
51
+ if callback:
52
+ callback(False)
53
+ clear_group(key)
54
+ # 如果出错了,直接取消执行队列
55
+ MessageWriter.error(
56
+ Exception(
57
+ f"[ExecuteGroup] Queue Execution Failed: Due to an error in the System execution triggered by {message.__class__.__name__}, the message group '{key}' has been cancelled"
58
+ )
59
+ )
60
+
61
+
62
+ def execute_group(
63
+ messages: list[EventMessage],
64
+ group_id: str = "default",
65
+ callback: Callable[[bool], None] | None = None,
66
+ ) -> None:
67
+ # 修复:原代码为 id in execute_group_map,会导致判定错误
68
+ if group_id in execute_group_map:
69
+ MessageWriter.error(
70
+ Exception(
71
+ f"[ExecuteGroup] Unavailable ID: The id '{group_id}' not yet executed"
72
+ )
73
+ )
74
+ if callback:
75
+ callback(False)
76
+ return
77
+
78
+ # 注册这一个执行组
79
+ execute_chain: list[dict[str, Any]] = []
80
+ key_message_map[group_id] = messages
81
+
82
+ for index, message in enumerate(messages):
83
+ if index == len(messages) - 1:
84
+ resolve = lambda: None
85
+ else:
86
+ # 使用默认参数绑定 next_msg,防止 Python 闭包延迟绑定导致总是拿到最后一条消息
87
+ next_msg = messages[index + 1]
88
+ resolve = lambda m=next_msg: MessageWriter.write(m)
89
+
90
+ execute_chain.append({"message": message, "resolve": resolve})
91
+ message_key_map[id(message)] = group_id # 使用 id(message) 作为键
92
+
93
+ if callback:
94
+ call_back_map[group_id] = callback
95
+
96
+ execute_group_map[group_id] = execute_chain
97
+
98
+ # 立刻触发第一个
99
+ MessageWriter.write(messages[0])
100
+
101
+
102
+ @contextmanager
103
+ def execute_block(
104
+ group_id: str = "default", callback: Callable[[bool], None] | None = None
105
+ ):
106
+ # 创建一个临时篮子,用来装 with 期间产生的所有消息实例
107
+ captured_messages: list[EventMessage] = []
108
+
109
+ # 备份原本的全局 MessageWriter.write 方法
110
+ original_write = MessageWriter.write
111
+
112
+ # 定义一个拦截函数
113
+ def mock_write(message: Any) -> None:
114
+ if isinstance(message, EventMessage):
115
+ # 如果是事件消息,拦截下来,存进篮子,先不发送
116
+ captured_messages.append(message)
117
+ else:
118
+ # 如果是其他不归群组管的消息(比如 InfoMessage 等),让它走原渠道正常发
119
+ original_write(message)
120
+
121
+ # 把原本的 write 换成拦截器
122
+ MessageWriter.write = mock_write # type: ignore
123
+
124
+ try:
125
+ yield # 此时执行 with 块内部的代码
126
+ finally:
127
+ # 离开 with 无论里面是否报错,雷打不动地把原本的 write 恢复回去
128
+ # 这确保了黑魔法不会污染全局
129
+ MessageWriter.write = original_write
130
+
131
+ if captured_messages:
132
+ execute_group(captured_messages, group_id=group_id, callback=callback)
133
+
134
+
135
+ def activate_group_messages(app: ViridApp) -> None:
136
+ app.on_after_execute(EventMessage, after_execute_hook)
@@ -0,0 +1,30 @@
1
+ """
2
+ Copyright (c) 2026-present Ailrid.
3
+ Licensed under the Apache License, Version 2.0.
4
+ Project: Virid
5
+ """
6
+
7
+ from typing import Callable, Any
8
+ from virid.core import ViridApp
9
+
10
+ # 一个简单的 nextTick 任务队列
11
+ tick_task_queue: list[Callable[[], None]] = []
12
+
13
+
14
+ def after_tick_hook(context: Any) -> None:
15
+ global tick_task_queue
16
+ if len(tick_task_queue) == 0:
17
+ return
18
+
19
+ # 严格遵循你 TS 原版的双缓冲/清空逻辑
20
+ for task in tick_task_queue:
21
+ task()
22
+ tick_task_queue = []
23
+
24
+
25
+ def next_tick(task: Callable[[], None]) -> None:
26
+ tick_task_queue.append(task)
27
+
28
+
29
+ def activate_next_tick(app: ViridApp) -> None:
30
+ app.on_after_tick(after_tick_hook)
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.4
2
+ Name: virid-std
3
+ Version: 0.1.0
4
+ Requires-Python: >=3.10
5
+ Requires-Dist: core
@@ -0,0 +1,8 @@
1
+ virid/std/__init__.py,sha256=385Z9dJFvhVTS46e6w1fnOLwYol5rc52spph4TGBV54,196
2
+ virid/std/plugin.py,sha256=RZXCqPCQmgsjOp4GZngBdkzUGilm7pLCcaejXgXbirI,443
3
+ virid/std/utils/__init__.py,sha256=0zSwodCzQIvcqVEvZfSA3aUP3NDDbCKEqHxzRtlvz9U,370
4
+ virid/std/utils/execute_group.py,sha256=LKzlXfgVCdEKFI33JbFykPVtvSacV49WCV2fTiaY7fs,4741
5
+ virid/std/utils/nexttick.py,sha256=oC_t2hLDsvZ7DTNHfr4eEp7rhRZzlPrcZnOJ8pFeJ9o,684
6
+ virid_std-0.1.0.dist-info/METADATA,sha256=wJS7crXxRfoD_QH8yUNgiersuj1dGEtcxT4NbIWlqPc,97
7
+ virid_std-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
8
+ virid_std-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any