mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-09-07 04:26:45 +00:00
💡 add docstrings
This commit is contained in:
@ -1,7 +1,10 @@
|
||||
"""
|
||||
## 后端驱动适配基类
|
||||
"""本模块定义了驱动适配器基类。
|
||||
|
||||
各驱动请继承以下基类
|
||||
各驱动请继承以下基类。
|
||||
|
||||
FrontMatter:
|
||||
sidebar_position: 0
|
||||
description: nonebot.drivers 模块
|
||||
"""
|
||||
|
||||
import abc
|
||||
@ -35,57 +38,38 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class Driver(abc.ABC):
|
||||
"""
|
||||
Driver 基类。
|
||||
"""Driver 基类。
|
||||
|
||||
参数:
|
||||
env: 包含环境信息的 Env 对象
|
||||
config: 包含配置信息的 Config 对象
|
||||
"""
|
||||
|
||||
_adapters: Dict[str, "Adapter"] = {}
|
||||
"""
|
||||
已注册的适配器列表
|
||||
"""
|
||||
"""已注册的适配器列表"""
|
||||
_bot_connection_hook: Set[T_BotConnectionHook] = set()
|
||||
"""
|
||||
Bot 连接建立时执行的函数
|
||||
"""
|
||||
"""Bot 连接建立时执行的函数"""
|
||||
_bot_disconnection_hook: Set[T_BotDisconnectionHook] = set()
|
||||
"""
|
||||
Bot 连接断开时执行的函数
|
||||
"""
|
||||
"""Bot 连接断开时执行的函数"""
|
||||
|
||||
def __init__(self, env: Env, config: Config):
|
||||
"""
|
||||
参数:
|
||||
env: 包含环境信息的 Env 对象
|
||||
config: 包含配置信息的 Config 对象
|
||||
"""
|
||||
self.env: str = env.environment
|
||||
"""
|
||||
环境名称
|
||||
"""
|
||||
"""环境名称"""
|
||||
self.config: Config = config
|
||||
"""
|
||||
配置对象
|
||||
"""
|
||||
"""全局配置对象"""
|
||||
self._clients: Dict[str, "Bot"] = {}
|
||||
"""
|
||||
已连接的 Bot
|
||||
"""
|
||||
|
||||
@property
|
||||
def bots(self) -> Dict[str, "Bot"]:
|
||||
"""
|
||||
获取当前所有已连接的 Bot
|
||||
"""
|
||||
"""获取当前所有已连接的 Bot"""
|
||||
return self._clients
|
||||
|
||||
def register_adapter(self, adapter: Type["Adapter"], **kwargs) -> None:
|
||||
"""
|
||||
注册一个协议适配器
|
||||
"""注册一个协议适配器
|
||||
|
||||
参数:
|
||||
name: 适配器名称,用于在连接时进行识别
|
||||
adapter: 适配器 Class
|
||||
**kwargs: 其他传递给适配器的参数
|
||||
adapter: 适配器类
|
||||
kwargs: 其他传递给适配器的参数
|
||||
"""
|
||||
name = adapter.get_name()
|
||||
if name in self._adapters:
|
||||
@ -121,36 +105,36 @@ class Driver(abc.ABC):
|
||||
|
||||
@abc.abstractmethod
|
||||
def on_startup(self, func: Callable) -> Callable:
|
||||
"""注册一个在驱动启动时运行的函数"""
|
||||
"""注册一个在驱动器启动时执行的函数"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def on_shutdown(self, func: Callable) -> Callable:
|
||||
"""注册一个在驱动停止时运行的函数"""
|
||||
"""注册一个在驱动器停止时执行的函数"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_bot_connect(self, func: T_BotConnectionHook) -> T_BotConnectionHook:
|
||||
"""
|
||||
装饰一个函数使他在 bot 通过 WebSocket 连接成功时执行。
|
||||
"""装饰一个函数使他在 bot 连接成功时执行。
|
||||
|
||||
参数:
|
||||
bot: 当前连接上的 Bot 对象
|
||||
插槽函数参数:
|
||||
|
||||
- bot: 当前连接上的 Bot 对象
|
||||
"""
|
||||
self._bot_connection_hook.add(func)
|
||||
return func
|
||||
|
||||
def on_bot_disconnect(self, func: T_BotDisconnectionHook) -> T_BotDisconnectionHook:
|
||||
"""
|
||||
装饰一个函数使他在 bot 通过 WebSocket 连接断开时执行。
|
||||
"""装饰一个函数使他在 bot 连接断开时执行。
|
||||
|
||||
参数:
|
||||
bot: 当前连接上的 Bot 对象
|
||||
插槽函数参数:
|
||||
|
||||
- bot: 当前连接上的 Bot 对象
|
||||
"""
|
||||
self._bot_disconnection_hook.add(func)
|
||||
return func
|
||||
|
||||
def _bot_connect(self, bot: "Bot") -> None:
|
||||
"""在 WebSocket 连接成功后,调用该函数来注册 bot 对象"""
|
||||
"""在连接成功后,调用该函数来注册 bot 对象"""
|
||||
if bot.self_id in self._clients:
|
||||
raise RuntimeError(f"Duplicate bot connection with id {bot.self_id}")
|
||||
self._clients[bot.self_id] = bot
|
||||
@ -169,7 +153,7 @@ class Driver(abc.ABC):
|
||||
asyncio.create_task(_run_hook(bot))
|
||||
|
||||
def _bot_disconnect(self, bot: "Bot") -> None:
|
||||
"""在 WebSocket 连接断开后,调用该函数来注销 bot 对象"""
|
||||
"""在连接断开后,调用该函数来注销 bot 对象"""
|
||||
if bot.self_id in self._clients:
|
||||
del self._clients[bot.self_id]
|
||||
|
||||
@ -188,32 +172,33 @@ class Driver(abc.ABC):
|
||||
|
||||
|
||||
class ForwardMixin(abc.ABC):
|
||||
"""客户端混入基类。"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def type(self) -> str:
|
||||
"""客户端驱动类型名称"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def request(self, setup: Request) -> Response:
|
||||
"""发送一个 HTTP 请求"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
@asynccontextmanager
|
||||
async def websocket(self, setup: Request) -> AsyncGenerator[WebSocket, None]:
|
||||
"""发起一个 WebSocket 连接"""
|
||||
raise NotImplementedError
|
||||
yield # used for static type checking's generator detection
|
||||
|
||||
|
||||
class ForwardDriver(Driver, ForwardMixin):
|
||||
"""
|
||||
Forward Driver 基类。将客户端框架封装,以满足适配器使用。
|
||||
"""
|
||||
"""客户端基类。将客户端框架封装,以满足适配器使用。"""
|
||||
|
||||
|
||||
class ReverseDriver(Driver):
|
||||
"""
|
||||
Reverse Driver 基类。将后端框架封装,以满足适配器使用。
|
||||
"""
|
||||
"""服务端基类。将后端框架封装,以满足适配器使用。"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
@ -229,20 +214,26 @@ class ReverseDriver(Driver):
|
||||
|
||||
@abc.abstractmethod
|
||||
def setup_http_server(self, setup: "HTTPServerSetup") -> None:
|
||||
"""设置一个 HTTP 服务器路由配置"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def setup_websocket_server(self, setup: "WebSocketServerSetup") -> None:
|
||||
"""设置一个 WebSocket 服务器路由配置"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def combine_driver(driver: Type[Driver], *mixins: Type[ForwardMixin]) -> Type[Driver]:
|
||||
"""将一个驱动器和多个混入类合并。"""
|
||||
# check first
|
||||
assert issubclass(driver, Driver), "`driver` must be subclass of Driver"
|
||||
assert all(
|
||||
map(lambda m: issubclass(m, ForwardMixin), mixins)
|
||||
), "`mixins` must be subclass of ForwardMixin"
|
||||
|
||||
if not mixins:
|
||||
return driver
|
||||
|
||||
class CombinedDriver(*mixins, driver, ForwardDriver): # type: ignore
|
||||
@property
|
||||
def type(self) -> str:
|
||||
@ -257,6 +248,8 @@ def combine_driver(driver: Type[Driver], *mixins: Type[ForwardMixin]) -> Type[Dr
|
||||
|
||||
@dataclass
|
||||
class HTTPServerSetup:
|
||||
"""HTTP 服务器路由配置。"""
|
||||
|
||||
path: URL # path should not be absolute, check it by URL.is_absolute() == False
|
||||
method: str
|
||||
name: str
|
||||
@ -265,6 +258,8 @@ class HTTPServerSetup:
|
||||
|
||||
@dataclass
|
||||
class WebSocketServerSetup:
|
||||
"""WebSocket 服务器路由配置。"""
|
||||
|
||||
path: URL # path should not be absolute, check it by URL.is_absolute() == False
|
||||
name: str
|
||||
handle_func: Callable[[WebSocket], Awaitable[Any]]
|
||||
|
@ -1,10 +1,21 @@
|
||||
"""
|
||||
## AIOHTTP 驱动适配
|
||||
"""[AIOHTTP](https://aiohttp.readthedocs.io/en/stable/) 驱动适配器。
|
||||
|
||||
```bash
|
||||
nb driver install aiohttp
|
||||
# 或者
|
||||
pip install nonebot2[aiohttp]
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
本驱动仅支持客户端连接
|
||||
:::
|
||||
|
||||
FrontMatter:
|
||||
sidebar_position: 2
|
||||
description: nonebot.drivers.aiohttp 模块
|
||||
"""
|
||||
|
||||
from typing import AsyncGenerator
|
||||
from typing import Type, AsyncGenerator
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from nonebot.typing import overrides
|
||||
@ -12,7 +23,12 @@ from nonebot.drivers import Request, Response
|
||||
from nonebot.exception import WebSocketClosed
|
||||
from nonebot.drivers._block_driver import BlockDriver
|
||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||
from nonebot.drivers import HTTPVersion, ForwardMixin, combine_driver
|
||||
from nonebot.drivers import (
|
||||
HTTPVersion,
|
||||
ForwardMixin,
|
||||
ForwardDriver,
|
||||
combine_driver,
|
||||
)
|
||||
|
||||
try:
|
||||
import aiohttp
|
||||
@ -23,6 +39,8 @@ except ImportError:
|
||||
|
||||
|
||||
class Mixin(ForwardMixin):
|
||||
"""AIOHTTP Mixin"""
|
||||
|
||||
@property
|
||||
@overrides(ForwardMixin)
|
||||
def type(self) -> str:
|
||||
@ -84,6 +102,8 @@ class Mixin(ForwardMixin):
|
||||
|
||||
|
||||
class WebSocket(BaseWebSocket):
|
||||
"""AIOHTTP Websocket Wrapper"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@ -138,4 +158,5 @@ class WebSocket(BaseWebSocket):
|
||||
await self.websocket.send_bytes(data)
|
||||
|
||||
|
||||
Driver = combine_driver(BlockDriver, Mixin)
|
||||
Driver: Type[ForwardDriver] = combine_driver(BlockDriver, Mixin) # type: ignore
|
||||
"""AIOHTTP Driver"""
|
||||
|
@ -1,9 +1,12 @@
|
||||
"""
|
||||
## FastAPI 驱动适配
|
||||
"""[FastAPI](https://fastapi.tiangolo.com/) 驱动适配
|
||||
|
||||
本驱动同时支持服务端以及客户端连接
|
||||
:::tip 提示
|
||||
本驱动仅支持服务端连接
|
||||
:::
|
||||
|
||||
后端使用方法请参考: [`FastAPI 文档`](https://fastapi.tiangolo.com/)
|
||||
FrontMatter:
|
||||
sidebar_position: 1
|
||||
description: nonebot.drivers.fastapi 模块
|
||||
"""
|
||||
|
||||
import logging
|
||||
@ -39,53 +42,33 @@ def catch_closed(func):
|
||||
|
||||
|
||||
class Config(BaseSettings):
|
||||
"""
|
||||
FastAPI 驱动框架设置,详情参考 FastAPI 文档
|
||||
"""
|
||||
"""FastAPI 驱动框架设置,详情参考 FastAPI 文档"""
|
||||
|
||||
fastapi_openapi_url: Optional[str] = None
|
||||
"""
|
||||
`openapi.json` 地址,默认为 `None` 即关闭
|
||||
"""
|
||||
"""`openapi.json` 地址,默认为 `None` 即关闭"""
|
||||
fastapi_docs_url: Optional[str] = None
|
||||
"""
|
||||
`swagger` 地址,默认为 `None` 即关闭
|
||||
"""
|
||||
"""`swagger` 地址,默认为 `None` 即关闭"""
|
||||
fastapi_redoc_url: Optional[str] = None
|
||||
"""
|
||||
`redoc` 地址,默认为 `None` 即关闭
|
||||
"""
|
||||
"""`redoc` 地址,默认为 `None` 即关闭"""
|
||||
fastapi_include_adapter_schema: bool = True
|
||||
"""
|
||||
是否包含适配器路由的 schema,默认为 `True`
|
||||
"""
|
||||
"""是否包含适配器路由的 schema,默认为 `True`"""
|
||||
fastapi_reload: bool = False
|
||||
"""
|
||||
开启/关闭冷重载
|
||||
"""
|
||||
"""开启/关闭冷重载"""
|
||||
fastapi_reload_dirs: Optional[List[str]] = None
|
||||
"""
|
||||
重载监控文件夹列表,默认为 uvicorn 默认值
|
||||
"""
|
||||
"""重载监控文件夹列表,默认为 uvicorn 默认值"""
|
||||
fastapi_reload_delay: Optional[float] = None
|
||||
"""
|
||||
重载延迟,默认为 uvicorn 默认值
|
||||
"""
|
||||
"""重载延迟,默认为 uvicorn 默认值"""
|
||||
fastapi_reload_includes: Optional[List[str]] = None
|
||||
"""
|
||||
要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值
|
||||
"""
|
||||
"""要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值"""
|
||||
fastapi_reload_excludes: Optional[List[str]] = None
|
||||
"""
|
||||
不要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值
|
||||
"""
|
||||
"""不要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值"""
|
||||
|
||||
class Config:
|
||||
extra = "ignore"
|
||||
|
||||
|
||||
class Driver(ReverseDriver):
|
||||
"""FastAPI 驱动框架。包含反向 Server 功能。"""
|
||||
"""FastAPI 驱动框架。"""
|
||||
|
||||
def __init__(self, env: Env, config: NoneBotConfig):
|
||||
super(Driver, self).__init__(env, config)
|
||||
@ -254,6 +237,8 @@ class Driver(ReverseDriver):
|
||||
|
||||
|
||||
class FastAPIWebSocket(BaseWebSocket):
|
||||
"""FastAPI WebSocket Wrapper"""
|
||||
|
||||
@overrides(BaseWebSocket)
|
||||
def __init__(self, *, request: BaseRequest, websocket: WebSocket):
|
||||
super().__init__(request=request)
|
||||
@ -294,3 +279,6 @@ class FastAPIWebSocket(BaseWebSocket):
|
||||
@overrides(BaseWebSocket)
|
||||
async def send_bytes(self, data: bytes) -> None:
|
||||
await self.websocket.send({"type": "websocket.send", "bytes": data})
|
||||
|
||||
|
||||
__autodoc__ = {"catch_closed": False}
|
||||
|
@ -1,4 +1,20 @@
|
||||
from typing import AsyncGenerator
|
||||
"""[HTTPX](https://www.python-httpx.org/) 驱动适配
|
||||
|
||||
```bash
|
||||
nb driver install httpx
|
||||
# 或者
|
||||
pip install nonebot2[httpx]
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
本驱动仅支持客户端 HTTP 连接
|
||||
:::
|
||||
|
||||
FrontMatter:
|
||||
sidebar_position: 3
|
||||
description: nonebot.drivers.httpx 模块
|
||||
"""
|
||||
from typing import Type, AsyncGenerator
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from nonebot.typing import overrides
|
||||
@ -9,6 +25,7 @@ from nonebot.drivers import (
|
||||
WebSocket,
|
||||
HTTPVersion,
|
||||
ForwardMixin,
|
||||
ForwardDriver,
|
||||
combine_driver,
|
||||
)
|
||||
|
||||
@ -21,6 +38,8 @@ except ImportError:
|
||||
|
||||
|
||||
class Mixin(ForwardMixin):
|
||||
"""HTTPX Mixin"""
|
||||
|
||||
@property
|
||||
@overrides(ForwardMixin)
|
||||
def type(self) -> str:
|
||||
@ -57,4 +76,5 @@ class Mixin(ForwardMixin):
|
||||
yield ws
|
||||
|
||||
|
||||
Driver = combine_driver(BlockDriver, Mixin)
|
||||
Driver: Type[ForwardDriver] = combine_driver(BlockDriver, Mixin) # type: ignore
|
||||
"""HTTPX Driver"""
|
||||
|
@ -1,7 +1,18 @@
|
||||
"""
|
||||
## Quart 驱动适配
|
||||
"""[Quart](https://pgjones.gitlab.io/quart/index.html) 驱动适配
|
||||
|
||||
后端使用方法请参考: [`Quart 文档`](https://pgjones.gitlab.io/quart/index.html)
|
||||
```bash
|
||||
nb driver install quart
|
||||
# 或者
|
||||
pip install nonebot2[quart]
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
本驱动仅支持服务端连接
|
||||
:::
|
||||
|
||||
FrontMatter:
|
||||
sidebar_position: 5
|
||||
description: nonebot.drivers.quart 模块
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
@ -47,39 +58,25 @@ def catch_closed(func):
|
||||
|
||||
|
||||
class Config(BaseSettings):
|
||||
"""
|
||||
Quart 驱动框架设置
|
||||
"""
|
||||
"""Quart 驱动框架设置"""
|
||||
|
||||
quart_reload: bool = False
|
||||
"""
|
||||
开启/关闭冷重载
|
||||
"""
|
||||
"""开启/关闭冷重载"""
|
||||
quart_reload_dirs: Optional[List[str]] = None
|
||||
"""
|
||||
重载监控文件夹列表,默认为 uvicorn 默认值
|
||||
"""
|
||||
"""重载监控文件夹列表,默认为 uvicorn 默认值"""
|
||||
quart_reload_delay: Optional[float] = None
|
||||
"""
|
||||
重载延迟,默认为 uvicorn 默认值
|
||||
"""
|
||||
"""重载延迟,默认为 uvicorn 默认值"""
|
||||
quart_reload_includes: Optional[List[str]] = None
|
||||
"""
|
||||
要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值
|
||||
"""
|
||||
"""要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值"""
|
||||
quart_reload_excludes: Optional[List[str]] = None
|
||||
"""
|
||||
不要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值
|
||||
"""
|
||||
"""不要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值"""
|
||||
|
||||
class Config:
|
||||
extra = "ignore"
|
||||
|
||||
|
||||
class Driver(ReverseDriver):
|
||||
"""
|
||||
Quart 驱动框架
|
||||
"""
|
||||
"""Quart 驱动框架"""
|
||||
|
||||
def __init__(self, env: Env, config: NoneBotConfig):
|
||||
super().__init__(env, config)
|
||||
@ -239,6 +236,8 @@ class Driver(ReverseDriver):
|
||||
|
||||
|
||||
class WebSocket(BaseWebSocket):
|
||||
"""Quart WebSocket Wrapper"""
|
||||
|
||||
def __init__(self, *, request: BaseRequest, websocket: QuartWebSocket):
|
||||
super().__init__(request=request)
|
||||
self.websocket = websocket
|
||||
@ -280,3 +279,6 @@ class WebSocket(BaseWebSocket):
|
||||
@overrides(BaseWebSocket)
|
||||
async def send_bytes(self, data: bytes):
|
||||
await self.websocket.send(data)
|
||||
|
||||
|
||||
__autodoc__ = {"catch_closed": False}
|
||||
|
@ -1,6 +1,22 @@
|
||||
"""[websockets](https://websockets.readthedocs.io/) 驱动适配
|
||||
|
||||
```bash
|
||||
nb driver install websockets
|
||||
# 或者
|
||||
pip install nonebot2[websockets]
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
本驱动仅支持客户端 WebSocket 连接
|
||||
:::
|
||||
|
||||
FrontMatter:
|
||||
sidebar_position: 4
|
||||
description: nonebot.drivers.websockets 模块
|
||||
"""
|
||||
import logging
|
||||
from functools import wraps
|
||||
from typing import AsyncGenerator
|
||||
from typing import Type, AsyncGenerator
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from nonebot.typing import overrides
|
||||
@ -9,7 +25,7 @@ from nonebot.drivers import Request, Response
|
||||
from nonebot.exception import WebSocketClosed
|
||||
from nonebot.drivers._block_driver import BlockDriver
|
||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||
from nonebot.drivers import ForwardMixin, combine_driver
|
||||
from nonebot.drivers import ForwardMixin, ForwardDriver, combine_driver
|
||||
|
||||
try:
|
||||
from websockets.exceptions import ConnectionClosed
|
||||
@ -38,6 +54,8 @@ def catch_closed(func):
|
||||
|
||||
|
||||
class Mixin(ForwardMixin):
|
||||
"""Websockets Mixin"""
|
||||
|
||||
@property
|
||||
@overrides(ForwardMixin)
|
||||
def type(self) -> str:
|
||||
@ -60,6 +78,8 @@ class Mixin(ForwardMixin):
|
||||
|
||||
|
||||
class WebSocket(BaseWebSocket):
|
||||
"""Websockets WebSocket Wrapper"""
|
||||
|
||||
@overrides(BaseWebSocket)
|
||||
def __init__(self, *, request: Request, websocket: WebSocketClientProtocol):
|
||||
super().__init__(request=request)
|
||||
@ -103,4 +123,5 @@ class WebSocket(BaseWebSocket):
|
||||
await self.websocket.send(data)
|
||||
|
||||
|
||||
Driver = combine_driver(BlockDriver, Mixin)
|
||||
Driver: Type[ForwardDriver] = combine_driver(BlockDriver, Mixin) # type: ignore
|
||||
"""Websockets Driver"""
|
||||
|
Reference in New Issue
Block a user