💡 add adapter docstring

This commit is contained in:
yanyongyu 2022-01-20 14:49:46 +08:00
parent 98ef09585a
commit aef585c60c
7 changed files with 115 additions and 98 deletions

View File

@ -1,7 +1,6 @@
"""
## 协议适配基类
"""本模块定义了协议适配基类,各协议请继承以下基类。
各协议请继承以下基类并使用 `driver.register_adapter` 注册适配器
使用 {ref}`nonebot.drivers.Driver.register_adapter` 注册适配器
"""
from typing import Iterable

View File

@ -18,56 +18,89 @@ from ._bot import Bot
class Adapter(abc.ABC):
"""协议适配器基类。
通常 Adapter 中编写协议通信相关代码: 建立通信连接处理接收与发送 data
参数:
driver: {ref}`nonebot.drivers.Driver` 实例
kwargs: 其他由 {ref}`nonebot.drivers.Driver.register_adapter` 传入的额外参数
"""
def __init__(self, driver: Driver, **kwargs: Any):
self.driver: Driver = driver
"""{ref}`nonebot.drivers.Driver` 实例"""
self.bots: Dict[str, Bot] = {}
"""本协议适配器已建立连接的 {ref}`nonebot.adapters._bot.Bot` 实例"""
@classmethod
@abc.abstractmethod
def get_name(cls) -> str:
"""当前协议适配器的名称"""
raise NotImplementedError
@property
def config(self) -> Config:
"""全局 NoneBot 配置"""
return self.driver.config
def bot_connect(self, bot: Bot) -> None:
"""告知 NoneBot 建立了一个新的 {ref}`nonebot.adapters._bot.Bot` 连接。
当有新的 {ref}`nonebot.adapters._bot.Bot` 实例连接建立成功时调用
参数:
bot: {ref}`nonebot.adapters._bot.Bot` 实例
"""
self.driver._bot_connect(bot)
self.bots[bot.self_id] = bot
def bot_disconnect(self, bot: Bot) -> None:
"""告知 NoneBot {ref}`nonebot.adapters._bot.Bot` 连接已断开。
当有 {ref}`nonebot.adapters._bot.Bot` 实例连接断开时调用
参数:
bot: {ref}`nonebot.adapters._bot.Bot` 实例
"""
self.driver._bot_disconnect(bot)
self.bots.pop(bot.self_id, None)
def setup_http_server(self, setup: HTTPServerSetup):
"""设置一个 HTTP 服务器路由配置"""
if not isinstance(self.driver, ReverseDriver):
raise TypeError("Current driver does not support http server")
self.driver.setup_http_server(setup)
def setup_websocket_server(self, setup: WebSocketServerSetup):
"""设置一个 WebSocket 服务器路由配置"""
if not isinstance(self.driver, ReverseDriver):
raise TypeError("Current driver does not support websocket server")
self.driver.setup_websocket_server(setup)
async def request(self, setup: Request) -> Response:
"""进行一个 HTTP 客户端请求"""
if not isinstance(self.driver, ForwardDriver):
raise TypeError("Current driver does not support http client")
return await self.driver.request(setup)
@asynccontextmanager
async def websocket(self, setup: Request) -> AsyncGenerator[WebSocket, None]:
"""建立一个 WebSocket 客户端连接请求"""
if not isinstance(self.driver, ForwardDriver):
raise TypeError("Current driver does not support websocket client")
async with self.driver.websocket(setup) as ws:
yield ws
@abc.abstractmethod
async def _call_api(self, bot: Bot, api: str, **data) -> Any:
"""
`adapter` 实际调用 api 的逻辑实现函数实现该方法以调用 api
async def _call_api(self, bot: Bot, api: str, **data: Any) -> Any:
"""`Adapter` 实际调用 api 的逻辑实现函数,实现该方法以调用 api。
参数:
api: API 名称
**data: API 数据
data: API 数据
"""
raise NotImplementedError
__autodoc__ = {"Adapter._call_api": True}

View File

@ -21,26 +21,23 @@ class _ApiCall(Protocol):
class Bot(abc.ABC):
"""
Bot 基类用于处理上报消息并提供 API 调用接口
"""Bot 基类。
用于处理上报消息并提供 API 调用接口
参数:
adapter: 协议适配器实例
self_id: 机器人 ID
"""
_calling_api_hook: Set[T_CallingAPIHook] = set()
"""
call_api 时执行的函数
"""
"""call_api 时执行的函数"""
_called_api_hook: Set[T_CalledAPIHook] = set()
"""
call_api 后执行的函数
"""
"""call_api 后执行的函数"""
def __init__(self, adapter: "Adapter", self_id: str):
"""
参数:
self_id: 机器人 ID
request: request 连接对象
"""
self.adapter: "Adapter" = adapter
"""协议适配器实例"""
self.self_id: str = self_id
"""机器人 ID"""
@ -49,19 +46,20 @@ class Bot(abc.ABC):
@property
def type(self) -> str:
"""协议适配器名称"""
return self.adapter.get_name()
@property
def config(self) -> Config:
"""全局 NoneBot 配置"""
return self.adapter.config
async def call_api(self, api: str, **data: Any) -> Any:
"""
调用机器人 API 接口可以通过该函数或直接通过 bot 属性进行调用
"""调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用
参数:
api: API 名称
**data: API 数据
data: API 数据
用法:
```python
@ -121,41 +119,44 @@ class Bot(abc.ABC):
@abc.abstractmethod
async def send(
self, event: "Event", message: Union[str, "Message", "MessageSegment"], **kwargs
self,
event: "Event",
message: Union[str, "Message", "MessageSegment"],
**kwargs: Any,
) -> Any:
"""
调用机器人基础发送消息接口
"""调用机器人基础发送消息接口
参数:
event: 上报事件
message: 要发送的消息
kwargs: 任意额外参数
"""
raise NotImplementedError
@classmethod
def on_calling_api(cls, func: T_CallingAPIHook) -> T_CallingAPIHook:
"""
调用 api 预处理
"""调用 api 预处理。
参数:
bot: 当前 bot 对象
api: 调用的 api 名称
data: api 调用的参数字典
插槽函数参数:
- bot: 当前 bot 对象
- api: 调用的 api 名称
- data: api 调用的参数字典
"""
cls._calling_api_hook.add(func)
return func
@classmethod
def on_called_api(cls, func: T_CalledAPIHook) -> T_CalledAPIHook:
"""
调用 api 后处理
"""调用 api 后处理。
参数:
bot: 当前 bot 对象
exception: 调用 api 时发生的错误
api: 调用的 api 名称
data: api 调用的参数字典
result: api 调用的返回
插槽函数参数:
- bot: 当前 bot 对象
- exception: 调用 api 时发生的错误
- api: 调用的 api 名称
- data: api 调用的参数字典
- result: api 调用的返回
"""
cls._called_api_hook.add(func)
return func

View File

@ -16,31 +16,26 @@ class Event(abc.ABC, BaseModel):
@abc.abstractmethod
def get_type(self) -> str:
"""
获取事件类型的方法类型通常为 NoneBot 内置的四种类型
"""
"""获取事件类型的方法,类型通常为 NoneBot 内置的四种类型。"""
raise NotImplementedError
@abc.abstractmethod
def get_event_name(self) -> str:
"""
获取事件名称的方法
"""
"""获取事件名称的方法。"""
raise NotImplementedError
@abc.abstractmethod
def get_event_description(self) -> str:
"""
获取事件描述的方法通常为事件具体内容
"""
"""获取事件描述的方法,通常为事件具体内容。"""
raise NotImplementedError
def __str__(self) -> str:
return f"[{self.get_event_name()}]: {self.get_event_description()}"
def get_log_string(self) -> str:
"""
获取事件日志信息的方法通常你不需要修改这个方法只有当希望 NoneBot 隐藏该事件日志时可以抛出 `NoLogException` 异常
"""获取事件日志信息的方法。
通常你不需要修改这个方法只有当希望 NoneBot 隐藏该事件日志时可以抛出 `NoLogException` 异常
异常:
NoLogException
@ -49,34 +44,27 @@ class Event(abc.ABC, BaseModel):
@abc.abstractmethod
def get_user_id(self) -> str:
"""
获取事件主体 id 的方法通常是用户 id
"""
"""获取事件主体 id 的方法,通常是用户 id 。"""
raise NotImplementedError
@abc.abstractmethod
def get_session_id(self) -> str:
"""
获取会话 id 的方法用于判断当前事件属于哪一个会话通常是用户 id群组 id 组合
"""
"""获取会话 id 的方法,用于判断当前事件属于哪一个会话,通常是用户 id、群组 id 组合。"""
raise NotImplementedError
@abc.abstractmethod
def get_message(self) -> "Message":
"""
获取事件消息内容的方法
"""
"""获取事件消息内容的方法。"""
raise NotImplementedError
def get_plaintext(self) -> str:
"""
获取消息纯文本的方法通常不需要修改默认通过 `get_message().extract_plain_text` 获取
"""获取消息纯文本的方法。
通常不需要修改默认通过 `get_message().extract_plain_text` 获取
"""
return self.get_message().extract_plain_text()
@abc.abstractmethod
def is_tome(self) -> bool:
"""
获取事件是否与机器人有关的方法
"""
"""获取事件是否与机器人有关的方法。"""
raise NotImplementedError

View File

@ -25,17 +25,14 @@ class MessageSegment(Mapping, abc.ABC, Generic[TM]):
"""消息段基类"""
type: str
"""
消息段类型
"""
"""消息段类型"""
data: Dict[str, Any] = field(default_factory=lambda: {})
"""
消息段数据
"""
"""消息段数据"""
@classmethod
@abc.abstractmethod
def get_message_class(cls) -> Type[TM]:
"""获取消息数组类型"""
raise NotImplementedError
@abc.abstractmethod
@ -84,11 +81,16 @@ class MessageSegment(Mapping, abc.ABC, Generic[TM]):
@abc.abstractmethod
def is_text(self) -> bool:
"""当前消息段是否为纯文本"""
raise NotImplementedError
class Message(List[TMS], abc.ABC):
"""消息数组"""
"""消息数组
参数:
message: 消息内容
"""
def __init__(
self: TM,
@ -96,10 +98,6 @@ class Message(List[TMS], abc.ABC):
*args,
**kwargs,
):
"""
参数:
message: 消息内容
"""
super().__init__(*args, **kwargs)
if message is None:
return
@ -112,8 +110,9 @@ class Message(List[TMS], abc.ABC):
@classmethod
def template(cls: Type[TM], format_string: Union[str, TM]) -> MessageTemplate[TM]:
"""
根据创建消息模板, 用法和 `str.format` 大致相同, 但是可以输出消息对象, 并且支持以 `Message` 对象作为消息模板
"""创建消息模板。
用法和 `str.format` 大致相同, 但是可以输出消息对象, 并且支持以 `Message` 对象作为消息模板
并且提供了拓展的格式化控制符, 可以用适用于该消息类型的 `MessageSegment` 的工厂方法创建消息
@ -137,13 +136,14 @@ class Message(List[TMS], abc.ABC):
format_string: 格式化字符串
返回:
MessageFormatter[TM]: 消息格式化器
消息格式化器
"""
return MessageTemplate(format_string, cls)
@classmethod
@abc.abstractmethod
def get_segment_class(cls) -> Type[TMS]:
"""获取消息段类型"""
raise NotImplementedError
def __str__(self):
@ -160,6 +160,7 @@ class Message(List[TMS], abc.ABC):
@staticmethod
@abc.abstractmethod
def _construct(msg: Union[str, Mapping, Iterable[Mapping], Any]) -> Iterable[TMS]:
"""构造消息数组"""
raise NotImplementedError
def __add__(self: TM, other: Union[str, Mapping, Iterable[Mapping]]) -> TM:
@ -181,8 +182,7 @@ class Message(List[TMS], abc.ABC):
return self
def append(self: TM, obj: Union[str, TMS]) -> TM:
"""
添加一个消息段到消息数组末尾
"""添加一个消息段到消息数组末尾。
参数:
obj: 要添加的消息段
@ -196,8 +196,7 @@ class Message(List[TMS], abc.ABC):
return self
def extend(self: TM, obj: Union[TM, Iterable[TMS]]) -> TM:
"""
拼接一个消息数组或多个消息段到消息数组末尾
"""拼接一个消息数组或多个消息段到消息数组末尾。
参数:
obj: 要添加的消息数组
@ -210,8 +209,9 @@ class Message(List[TMS], abc.ABC):
return deepcopy(self)
def extract_plain_text(self: "Message[MessageSegment]") -> str:
"""
提取消息内纯文本消息
"""
"""提取消息内纯文本消息"""
return "".join(str(seg) for seg in self if seg.is_text())
__autodoc__ = {"MessageSegment.__str__": True}

View File

@ -31,7 +31,12 @@ FormatSpecFunc_T = TypeVar("FormatSpecFunc_T", bound=FormatSpecFunc)
class MessageTemplate(Formatter, Generic[TF]):
"""消息模板格式化实现类"""
"""消息模板格式化实现类。
参数:
template: 模板
factory: 消息构造类型默认为 `str`
"""
@overload
def __init__(
@ -46,13 +51,6 @@ class MessageTemplate(Formatter, Generic[TF]):
...
def __init__(self, template, factory=str) -> None:
"""
创建一个模板
参数:
template: 模板
factory: 消息构造类型默认为 `str`
"""
self.template: TF = template
self.factory: Type[TF] = factory
self.format_specs: Dict[str, FormatSpecFunc] = {}
@ -67,9 +65,7 @@ class MessageTemplate(Formatter, Generic[TF]):
return spec
def format(self, *args: Any, **kwargs: Any) -> TF:
"""
根据模板和参数生成消息对象
"""
"""根据模板和参数生成消息对象"""
msg = self.factory()
if isinstance(self.template, str):
msg += self.vformat(self.template, args, kwargs)

2
poetry.lock generated
View File

@ -562,7 +562,7 @@ six = ">=1.6.1"
type = "git"
url = "https://github.com/nonebot/nb-autodoc.git"
reference = "master"
resolved_reference = "35bcf0e5c41aa59aa923e201b3935ea96afc6273"
resolved_reference = "9371179f1ae4a1659ae789187b1dd323b7751a02"
[[package]]
name = "nodeenv"