Skip to content

Commit 6a7a4e8

Browse files
committed
🐛 fix version 0.59.2
add `matcher.clean()`
1 parent 310c0e8 commit 6a7a4e8

5 files changed

Lines changed: 52 additions & 5 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ reportShadowedImports = false
231231
disableBytesTypePromotions = true
232232

233233
[tool.pdm.scripts]
234-
test = "pytest -v -n 2 -W ignore ./tests/"
234+
test = "pytest -v -W ignore ./tests/"
235235
format = { composite = ["isort ./src/ ./example/ ./tests/","black ./src/ ./example/ ./tests/","ruff check ./src/ ./example/ ./tests/"] }
236236

237237
[tool.pytest.ini_options]

src/nonebot_plugin_alconna/extension.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,14 @@ def __init__(
261261

262262
_callbacks.add(self._callback)
263263

264-
finalize(self, _callbacks.remove, self._callback)
264+
finalize(self, _callbacks.discard, self._callback)
265+
266+
def destroy(self) -> None:
267+
"""销毁当前的扩展执行器,清理相关资源。"""
268+
_callbacks.discard(self._callback)
269+
self.extensions.clear()
270+
self.context.clear()
271+
del self._rule
265272

266273
def _callback(self, *append_global_ext: type[Extension] | Extension):
267274
for _ext in append_global_ext:

src/nonebot_plugin_alconna/matcher.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from nonebot.consts import ARG_KEY, RECEIVE_KEY
2222
from nonebot.internal.params import DefaultParam
2323
from nepattern import ANY, STRING, TPattern, AnyString
24+
from nonebot.internal.matcher.matcher import MatcherMeta
2425
from _weakref import _remove_dead_weakref # type: ignore
2526
from nonebot import require, get_driver, get_plugin_config
2627
from nonebot.plugin.on import store_matcher, get_matcher_source
@@ -106,18 +107,47 @@ def __get__(self, instance, owner):
106107
T1 = TypeVar("T1")
107108

108109

109-
class AlconnaMatcher(Matcher):
110+
class AlconnaMatcherMeta(MatcherMeta):
111+
if TYPE_CHECKING:
112+
_command_path: str
113+
114+
def __repr__(self) -> str:
115+
return (
116+
f"{self.__class__.__name__}(type={self.type!r}"
117+
+ (f", module={self.module_name}" if self.module_name else "")
118+
+ (f", lineno={self._source.lineno}" if self._source and self._source.lineno is not None else "")
119+
+ f", command={self._command_path}"
120+
+ ")"
121+
)
122+
123+
124+
class AlconnaMatcher(Matcher, metaclass=AlconnaMatcherMeta):
110125
# command: ClassVar[weakref.ReferenceType[Alconna]]
111126
basepath: ClassVar[str]
112127
executor: ClassVar[ExtensionExecutor]
113-
_command_path: ClassVar[str]
128+
_command_path: ClassVar[str] = ""
114129
_tests: ClassVar[list[tuple[UniMessage, dict[str, Any] | None, bool]]]
115130
_rule: ClassVar[AlconnaRule]
116131

117132
@classmethod
118133
def command(cls) -> Alconna:
119134
return cls._rule.command() # type: ignore
120135

136+
@classmethod
137+
def clean(cls) -> None:
138+
matchers[cls.priority].remove(cls)
139+
cls._rule.destroy()
140+
cls.executor.destroy()
141+
142+
def __repr__(self) -> str:
143+
return (
144+
f"{self.__class__.__name__}(type={self.type!r}"
145+
+ (f", module={self.module_name}" if self.module_name else "")
146+
+ (f", lineno={self._source.lineno}" if self._source and self._source.lineno is not None else "")
147+
+ f", command={self._command_path}"
148+
+ ")"
149+
)
150+
121151
@classmethod
122152
@overload
123153
def shortcut(cls, key: str | TPattern, args: ShortcutArgs | None = None) -> type[Self]:
@@ -1033,7 +1063,6 @@ def on_alconna(
10331063
)
10341064
matcher: type[AlconnaMatcher] = cast("type[AlconnaMatcher]", NewMatcher)
10351065
matcher.HANDLER_PARAM_TYPES = params
1036-
log("TRACE", f"Define new matcher {NewMatcher}")
10371066

10381067
matchers[priority].append(NewMatcher)
10391068
store_matcher(matcher)
@@ -1044,6 +1073,8 @@ def on_alconna(
10441073
command.meta.extra["matcher.source"] = matcher._source
10451074
command.meta.extra["matcher.position"] = (priority, len(matchers[priority]) - 1)
10461075

1076+
log("TRACE", f"Define new matcher {NewMatcher}")
1077+
10471078
def remove(wr, selfref=weakref.ref(command.meta), _atomic_removal=_remove_dead_weakref):
10481079
self = selfref()
10491080
if self is not None:

src/nonebot_plugin_alconna/rule.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ async def _waiter_handle(_event: Event, _matcher: Matcher, content: UniMsg):
198198

199199
self._waiter = _waiter_handle
200200

201+
def destroy(self) -> None:
202+
"""销毁 Alconna 规则,释放资源。"""
203+
self._tasks.clear()
204+
if cmd := self.command():
205+
command_manager.delete(cmd)
206+
self._waiter = None
207+
201208
@property
202209
def rule(self) -> Rule:
203210
return Rule(self)

tests/test_aliases.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ async def _(city: str):
2929
event2 = fake_group_message_event_v11(message=Message("天气abcd"), user_id=123)
3030
ctx.receive_event(bot, event2)
3131
ctx.should_not_pass_rule()
32+
33+
matcher.clean()

0 commit comments

Comments
 (0)