Feature: 为事件响应器添加更多源码信息 (#2351)

This commit is contained in:
Ju4tCode
2023-09-09 13:46:09 +08:00
committed by GitHub
parent 3601a33f20
commit c4716e3e17
9 changed files with 199 additions and 35 deletions

View File

@ -6,6 +6,7 @@ matchers = MatcherManager()
from .matcher import Matcher as Matcher
from .matcher import current_bot as current_bot
from .matcher import MatcherSource as MatcherSource
from .matcher import current_event as current_event
from .matcher import current_handler as current_handler
from .matcher import current_matcher as current_matcher

View File

@ -1,4 +1,9 @@
import sys
import inspect
import warnings
from pathlib import Path
from types import ModuleType
from dataclasses import dataclass
from contextvars import ContextVar
from typing_extensions import Self
from datetime import datetime, timedelta
@ -20,6 +25,7 @@ from typing import (
from nonebot.log import logger
from nonebot.internal.rule import Rule
from nonebot.utils import classproperty
from nonebot.dependencies import Dependent
from nonebot.internal.permission import User, Permission
from nonebot.internal.adapter import (
@ -74,15 +80,51 @@ current_matcher: ContextVar["Matcher"] = ContextVar("current_matcher")
current_handler: ContextVar[Dependent] = ContextVar("current_handler")
@dataclass
class MatcherSource:
"""Matcher 源代码上下文信息"""
plugin_name: Optional[str] = None
"""事件响应器所在插件名称"""
module_name: Optional[str] = None
"""事件响应器所在插件模块的路径名"""
lineno: Optional[int] = None
"""事件响应器所在行号"""
@property
def plugin(self) -> Optional["Plugin"]:
"""事件响应器所在插件"""
from nonebot.plugin import get_plugin
if self.plugin_name is not None:
return get_plugin(self.plugin_name)
@property
def module(self) -> Optional[ModuleType]:
if self.module_name is not None:
return sys.modules.get(self.module_name)
@property
def file(self) -> Optional[Path]:
if self.module is not None and (file := inspect.getsourcefile(self.module)):
return Path(file).absolute()
class MatcherMeta(type):
if TYPE_CHECKING:
module_name: Optional[str]
type: str
_source: Optional[MatcherSource]
module_name: Optional[str]
def __repr__(self) -> str:
return (
f"{self.__name__}(type={self.type!r}"
+ (f", module={self.module_name}" if self.module_name else "")
+ (
f", lineno={self._source.lineno}"
if self._source and self._source.lineno is not None
else ""
)
+ ")"
)
@ -90,14 +132,7 @@ class MatcherMeta(type):
class Matcher(metaclass=MatcherMeta):
"""事件响应器类"""
plugin: ClassVar[Optional["Plugin"]] = None
"""事件响应器所在插件"""
module: ClassVar[Optional[ModuleType]] = None
"""事件响应器所在插件模块"""
plugin_name: ClassVar[Optional[str]] = None
"""事件响应器所在插件名"""
module_name: ClassVar[Optional[str]] = None
"""事件响应器所在点分割插件模块路径"""
_source: ClassVar[Optional[MatcherSource]] = None
type: ClassVar[str] = ""
"""事件响应器类型"""
@ -142,6 +177,11 @@ class Matcher(metaclass=MatcherMeta):
return (
f"{self.__class__.__name__}(type={self.type!r}"
+ (f", module={self.module_name}" if self.module_name else "")
+ (
f", lineno={self._source.lineno}"
if self._source and self._source.lineno is not None
else ""
)
+ ")"
)
@ -158,6 +198,7 @@ class Matcher(metaclass=MatcherMeta):
*,
plugin: Optional["Plugin"] = None,
module: Optional[ModuleType] = None,
source: Optional[MatcherSource] = None,
expire_time: Optional[Union[datetime, timedelta]] = None,
default_state: Optional[T_State] = None,
default_type_updater: Optional[Union[T_TypeUpdater, Dependent[str]]] = None,
@ -176,22 +217,47 @@ class Matcher(metaclass=MatcherMeta):
temp: 是否为临时事件响应器,即触发一次后删除
priority: 响应优先级
block: 是否阻止事件向更低优先级的响应器传播
plugin: 事件响应器所在插件
module: 事件响应器所在模块
default_state: 默认状态 `state`
plugin: **Deprecated.** 事件响应器所在插件
module: **Deprecated.** 事件响应器所在模块
source: 事件响应器源代码上下文信息
expire_time: 事件响应器最终有效时间点,过时即被删除
default_state: 默认状态 `state`
default_type_updater: 默认事件类型更新函数
default_permission_updater: 默认会话权限更新函数
返回:
Type[Matcher]: 新的事件响应器类
"""
if plugin is not None:
warnings.warn(
(
"Pass `plugin` context info to create Matcher is deprecated. "
"Use `source` instead."
),
DeprecationWarning,
)
if module is not None:
warnings.warn(
(
"Pass `module` context info to create Matcher is deprecated. "
"Use `source` instead."
),
DeprecationWarning,
)
source = source or (
MatcherSource(
plugin_name=plugin and plugin.name,
module_name=module and module.__name__,
)
if plugin is not None or module is not None
else None
)
NewMatcher = type(
cls.__name__,
(cls,),
{
"plugin": plugin,
"module": module,
"plugin_name": plugin and plugin.name,
"module_name": module and module.__name__,
"_source": source,
"type": type_,
"rule": rule or Rule(),
"permission": permission or Permission(),
@ -253,6 +319,26 @@ class Matcher(metaclass=MatcherMeta):
"""销毁当前的事件响应器"""
matchers[cls.priority].remove(cls)
@classproperty
def plugin(cls) -> Optional["Plugin"]:
"""事件响应器所在插件"""
return cls._source and cls._source.plugin
@classproperty
def module(cls) -> Optional[ModuleType]:
"""事件响应器所在插件模块"""
return cls._source and cls._source.module
@classproperty
def plugin_name(cls) -> Optional[str]:
"""事件响应器所在插件名"""
return cls._source and cls._source.plugin_name
@classproperty
def module_name(cls) -> Optional[str]:
"""事件响应器所在插件模块路径"""
return cls._source and cls._source.module_name
@classmethod
async def check_perm(
cls,
@ -773,8 +859,7 @@ class Matcher(metaclass=MatcherMeta):
temp=True,
priority=0,
block=True,
plugin=self.plugin,
module=self.module,
source=self.__class__._source,
expire_time=bot.config.session_expire_timeout,
default_state=self.state,
default_type_updater=self.__class__._default_type_updater,
@ -794,8 +879,7 @@ class Matcher(metaclass=MatcherMeta):
temp=True,
priority=0,
block=True,
plugin=self.plugin,
module=self.module,
source=self.__class__._source,
expire_time=bot.config.session_expire_timeout,
default_state=self.state,
default_type_updater=self.__class__._default_type_updater,