diff --git a/nonebot/adapters/__init__.py b/nonebot/adapters/__init__.py index cdb8e8ee..1bb0bf87 100644 --- a/nonebot/adapters/__init__.py +++ b/nonebot/adapters/__init__.py @@ -1,6 +1,10 @@ """本模块定义了协议适配基类,各协议请继承以下基类。 -使用 {ref}`nonebot.drivers.Driver.register_adapter` 注册适配器 +使用 {ref}`nonebot.drivers.Driver.register_adapter` 注册适配器。 + +FrontMatter: + sidebar_position: 0 + description: nonebot.adapters 模块 """ from typing import Iterable diff --git a/nonebot/adapters/_adapter.py b/nonebot/adapters/_adapter.py index f278906f..423a4bb3 100644 --- a/nonebot/adapters/_adapter.py +++ b/nonebot/adapters/_adapter.py @@ -1,3 +1,8 @@ +""" +FrontMatter: + sidebar_position: 1 + description: nonebot.adapters._adapter 模块 +""" import abc from contextlib import asynccontextmanager from typing import Any, Dict, AsyncGenerator diff --git a/nonebot/adapters/_bot.py b/nonebot/adapters/_bot.py index 43c406bf..4ac6b969 100644 --- a/nonebot/adapters/_bot.py +++ b/nonebot/adapters/_bot.py @@ -1,3 +1,8 @@ +""" +FrontMatter: + sidebar_position: 2 + description: nonebot.adapters._bot 模块 +""" import abc import asyncio from functools import partial diff --git a/nonebot/adapters/_event.py b/nonebot/adapters/_event.py index 4172cb4d..6dd4d141 100644 --- a/nonebot/adapters/_event.py +++ b/nonebot/adapters/_event.py @@ -1,3 +1,8 @@ +""" +FrontMatter: + sidebar_position: 3 + description: nonebot.adapters._event 模块 +""" import abc from pydantic import BaseModel diff --git a/nonebot/adapters/_message.py b/nonebot/adapters/_message.py index f1d8f295..b40a4d0b 100644 --- a/nonebot/adapters/_message.py +++ b/nonebot/adapters/_message.py @@ -1,3 +1,8 @@ +""" +FrontMatter: + sidebar_position: 4 + description: nonebot.adapters._message 模块 +""" import abc from copy import deepcopy from dataclasses import field, asdict, dataclass diff --git a/nonebot/adapters/_template.py b/nonebot/adapters/_template.py index 1d60bc7e..b691cbcb 100644 --- a/nonebot/adapters/_template.py +++ b/nonebot/adapters/_template.py @@ -1,3 +1,8 @@ +""" +FrontMatter: + sidebar_position: 5 + description: nonebot.adapters._template 模块 +""" import inspect import functools from string import Formatter diff --git a/nonebot/dependencies/__init__.py b/nonebot/dependencies/__init__.py index 7971f777..7255a0a3 100644 --- a/nonebot/dependencies/__init__.py +++ b/nonebot/dependencies/__init__.py @@ -1,4 +1,9 @@ -"""本模块模块实现了依赖注入的定义与处理。""" +"""本模块模块实现了依赖注入的定义与处理。 + +FrontMatter: + sidebar_position: 0 + description: nonebot.dependencies 模块 +""" import abc import inspect diff --git a/nonebot/dependencies/utils.py b/nonebot/dependencies/utils.py index 1f5c25b4..b8353662 100644 --- a/nonebot/dependencies/utils.py +++ b/nonebot/dependencies/utils.py @@ -1,3 +1,8 @@ +""" +FrontMatter: + sidebar_position: 1 + description: nonebot.dependencies.utils 模块 +""" import inspect from typing import Any, Dict, Callable diff --git a/nonebot/drivers/__init__.py b/nonebot/drivers/__init__.py index 8054955b..40a29cac 100644 --- a/nonebot/drivers/__init__.py +++ b/nonebot/drivers/__init__.py @@ -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]] diff --git a/nonebot/drivers/aiohttp.py b/nonebot/drivers/aiohttp.py index 934cd1fb..bdfafaa4 100644 --- a/nonebot/drivers/aiohttp.py +++ b/nonebot/drivers/aiohttp.py @@ -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""" diff --git a/nonebot/drivers/fastapi.py b/nonebot/drivers/fastapi.py index 95ab0b76..978dd2f1 100644 --- a/nonebot/drivers/fastapi.py +++ b/nonebot/drivers/fastapi.py @@ -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} diff --git a/nonebot/drivers/httpx.py b/nonebot/drivers/httpx.py index fe82e50d..79100dcf 100644 --- a/nonebot/drivers/httpx.py +++ b/nonebot/drivers/httpx.py @@ -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""" diff --git a/nonebot/drivers/quart.py b/nonebot/drivers/quart.py index 32e00a1d..2f610064 100644 --- a/nonebot/drivers/quart.py +++ b/nonebot/drivers/quart.py @@ -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} diff --git a/nonebot/drivers/websockets.py b/nonebot/drivers/websockets.py index b3f2d99c..57b87169 100644 --- a/nonebot/drivers/websockets.py +++ b/nonebot/drivers/websockets.py @@ -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""" diff --git a/nonebot/plugin/__init__.py b/nonebot/plugin/__init__.py index beb65fad..7898518f 100644 --- a/nonebot/plugin/__init__.py +++ b/nonebot/plugin/__init__.py @@ -1,7 +1,37 @@ -""" -## 插件 +"""本模块为 NoneBot 插件开发提供便携的定义函数。 -为 NoneBot 插件开发提供便携的定义函数。 +## 快捷导入 + +为方便使用,本模块从子模块导入了部分内容,以下内容可以直接通过本模块导入: + +- `on` => {ref}``on` ` +- `on_metaevent` => {ref}``on_metaevent` ` +- `on_message` => {ref}``on_message` ` +- `on_notice` => {ref}``on_notice` ` +- `on_request` => {ref}``on_request` ` +- `on_startswith` => {ref}``on_startswith` ` +- `on_endswith` => {ref}``on_endswith` ` +- `on_keyword` => {ref}``on_keyword` ` +- `on_command` => {ref}``on_command` ` +- `on_shell_command` => {ref}``on_shell_command` ` +- `on_regex` => {ref}``on_regex` ` +- `CommandGroup` => {ref}``CommandGroup` ` +- `Matchergroup` => {ref}``MatcherGroup` ` +- `load_plugin` => {ref}``load_plugin` ` +- `load_plugins` => {ref}``load_plugins` ` +- `load_all_plugins` => {ref}``load_all_plugins` ` +- `load_from_json` => {ref}``load_from_json` ` +- `load_from_toml` => {ref}``load_from_toml` ` +- `load_builtin_plugin` => {ref}``load_builtin_plugin` ` +- `load_builtin_plugins` => {ref}``load_builtin_plugins` ` +- `get_plugin` => {ref}``get_plugin` ` +- `get_loaded_plugins` => {ref}``get_loaded_plugins` ` +- `export` => {ref}``export` ` +- `require` => {ref}``require` ` + +FrontMatter: + sidebar_position: 0 + description: nonebot.plugin 模块 """ from typing import List, Optional diff --git a/nonebot/plugin/export.py b/nonebot/plugin/export.py index 20b86957..d49cc362 100644 --- a/nonebot/plugin/export.py +++ b/nonebot/plugin/export.py @@ -1,9 +1,17 @@ +"""本模块定义了插件导出的内容对象。 + +在新版插件系统中,推荐优先使用直接 import 所需要的插件内容。 + +FrontMatter: + sidebar_position: 4 + description: nonebot.plugin.export 模块 +""" + from . import _current_plugin class Export(dict): - """ - 插件导出内容以使得其他插件可以获得。 + """插件导出内容以使得其他插件可以获得。 用法: ```python @@ -42,9 +50,7 @@ class Export(dict): def export() -> Export: - """ - 获取插件的导出内容对象 - """ + """获取当前插件的导出内容对象""" plugin = _current_plugin.get() if not plugin: raise RuntimeError("Export outside of the plugin!") diff --git a/nonebot/plugin/load.py b/nonebot/plugin/load.py index 6ebb93bf..2d2c55bb 100644 --- a/nonebot/plugin/load.py +++ b/nonebot/plugin/load.py @@ -1,3 +1,9 @@ +"""本模块定义插件加载接口。 + +FrontMatter: + sidebar_position: 1 + description: nonebot.plugin.load 模块 +""" import json import warnings from typing import Set, Iterable, Optional @@ -11,8 +17,7 @@ from .plugin import Plugin, get_plugin def load_plugin(module_path: str) -> Optional[Plugin]: - """ - 使用 `PluginManager` 加载单个插件,可以是本地插件或是通过 `pip` 安装的插件。 + """加载单个插件,可以是本地插件或是通过 `pip` 安装的插件。 参数: module_path: 插件名称 `path.to.your.plugin` @@ -24,11 +29,10 @@ def load_plugin(module_path: str) -> Optional[Plugin]: def load_plugins(*plugin_dir: str) -> Set[Plugin]: - """ - 导入目录下多个插件,以 `_` 开头的插件不会被导入! + """导入文件夹下多个插件,以 `_` 开头的插件不会被导入! 参数: - plugin_dir: 插件路径 + plugin_dir: 文件夹路径 """ manager = PluginManager(search_path=plugin_dir) _managers.append(manager) @@ -38,12 +42,11 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]: def load_all_plugins( module_path: Iterable[str], plugin_dir: Iterable[str] ) -> Set[Plugin]: - """ - 导入指定列表中的插件以及指定目录下多个插件,以 `_` 开头的插件不会被导入! + """导入指定列表中的插件以及指定目录下多个插件,以 `_` 开头的插件不会被导入! 参数: module_path: 指定插件集合 - plugin_dir: 指定插件路径集合 + plugin_dir: 指定文件夹路径集合 """ manager = PluginManager(module_path, plugin_dir) _managers.append(manager) @@ -51,12 +54,23 @@ def load_all_plugins( def load_from_json(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: - """ - 导入指定 json 文件中的 `plugins` 以及 `plugin_dirs` 下多个插件,以 `_` 开头的插件不会被导入! + """导入指定 json 文件中的 `plugins` 以及 `plugin_dirs` 下多个插件,以 `_` 开头的插件不会被导入! 参数: file_path: 指定 json 文件路径 encoding: 指定 json 文件编码 + + 用法: + ```json title=plugins.json + { + "plugins": ["some_plugin"], + "plugin_dirs": ["some_dir"] + } + ``` + + ```python + nonebot.load_from_json("plugins.json") + ``` """ with open(file_path, "r", encoding=encoding) as f: data = json.load(f) @@ -68,13 +82,22 @@ def load_from_json(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: def load_from_toml(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: - """ - 导入指定 toml 文件 `[tool.nonebot]` 中的 `plugins` 以及 `plugin_dirs` 下多个插件, - 以 `_` 开头的插件不会被导入! + """导入指定 toml 文件 `[tool.nonebot]` 中的 `plugins` 以及 `plugin_dirs` 下多个插件,以 `_` 开头的插件不会被导入! 参数: file_path: 指定 toml 文件路径 encoding: 指定 toml 文件编码 + + 用法: + ```toml title=pyproject.toml + [tool.nonebot] + plugins = ["some_plugin"] + plugin_dirs = ["some_dir"] + ``` + + ```python + nonebot.load_from_toml("pyproject.toml") + ``` """ with open(file_path, "r", encoding=encoding) as f: data = tomlkit.parse(f.read()) # type: ignore @@ -97,25 +120,30 @@ def load_from_toml(file_path: str, encoding: str = "utf-8") -> Set[Plugin]: def load_builtin_plugin(name: str) -> Optional[Plugin]: - """ - 导入 NoneBot 内置插件 + """导入 NoneBot 内置插件。 + + 参数: + name: 插件名称 """ return load_plugin(f"nonebot.plugins.{name}") def load_builtin_plugins(*plugins) -> Set[Plugin]: - """ - 导入多个 NoneBot 内置插件 + """导入多个 NoneBot 内置插件。 + + 参数: + plugins: 插件名称列表 """ return load_all_plugins([f"nonebot.plugins.{p}" for p in plugins], []) def require(name: str) -> Export: - """ - 获取一个插件的导出内容 + """获取一个插件的导出内容。 + + 如果为 `load_plugins` 文件夹导入的插件,则为文件(夹)名。 参数: - name: 插件名,与 `load_plugin` 参数一致。如果为 `load_plugins` 导入的插件,则为文件(夹)名。 + name: 插件名,即 {ref}`nonebot.plugin.plugin.Plugin.name`。 异常: RuntimeError: 插件无法加载 diff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py index b1c8bb89..c46c77c4 100644 --- a/nonebot/plugin/manager.py +++ b/nonebot/plugin/manager.py @@ -1,3 +1,11 @@ +"""本模块实现插件加载流程。 + +参考: [import hooks](https://docs.python.org/3/reference/import.html#import-hooks), [PEP302](https://www.python.org/dev/peps/pep-0302/) + +FrontMatter: + sidebar_position: 5 + description: nonebot.plugin.manager 模块 +""" import sys import pkgutil import importlib diff --git a/nonebot/plugin/on.py b/nonebot/plugin/on.py index eeaa340d..440b2351 100644 --- a/nonebot/plugin/on.py +++ b/nonebot/plugin/on.py @@ -1,3 +1,9 @@ +"""本模块定义事件响应器便携定义函数。 + +FrontMatter: + sidebar_position: 2 + description: nonebot.plugin.on 模块 +""" import re import sys import inspect diff --git a/nonebot/plugin/plugin.py b/nonebot/plugin/plugin.py index 4b8e6254..10e43723 100644 --- a/nonebot/plugin/plugin.py +++ b/nonebot/plugin/plugin.py @@ -1,3 +1,9 @@ +"""本模块定义插件对象。 + +FrontMatter: + sidebar_position: 3 + description: nonebot.plugin.plugin 模块 +""" from types import ModuleType from dataclasses import field, dataclass from typing import TYPE_CHECKING, Set, Dict, Type, Optional @@ -10,9 +16,7 @@ if TYPE_CHECKING: from .manager import PluginManager plugins: Dict[str, "Plugin"] = {} -""" -已加载的插件 -""" +"""已加载的插件""" @dataclass(eq=False) @@ -20,53 +24,36 @@ class Plugin(object): """存储插件信息""" name: str - """ - 插件名称,使用 文件/文件夹 名称作为插件名 - """ + """插件名称,使用 文件/文件夹 名称作为插件名""" module: ModuleType - """ - 插件模块对象 - """ + """插件模块对象""" module_name: str - """ - 点分割模块路径 - """ + """点分割模块路径""" manager: "PluginManager" - """ - 导入该插件的插件管理器 - """ + """导入该插件的插件管理器""" export: Export = field(default_factory=Export) - """ - 插件内定义的导出内容 - """ + """插件内定义的导出内容""" matcher: Set[Type[Matcher]] = field(default_factory=set) - """ - 插件内定义的 `Matcher` - """ + """插件内定义的 `Matcher`""" parent_plugin: Optional["Plugin"] = None - """ - 父插件 - """ + """父插件""" sub_plugins: Set["Plugin"] = field(default_factory=set) - """ - 子插件集合 - """ + """子插件集合""" def get_plugin(name: str) -> Optional[Plugin]: - """ - 获取当前导入的某个插件。 + """获取已经导入的某个插件。 + + 如果为 `load_plugins` 文件夹导入的插件,则为文件(夹)名。 参数: - name: 插件名,与 `load_plugin` 参数一致。如果为 `load_plugins` 导入的插件,则为文件(夹)名。 + name: 插件名,即 {ref}`nonebot.plugin.plugin.Plugin.name`。 """ return plugins.get(name) def get_loaded_plugins() -> Set[Plugin]: - """ - 获取当前已导入的所有插件。 - """ + """获取当前已导入的所有插件。""" return set(plugins.values()) diff --git a/poetry.lock b/poetry.lock index ab2fe1d9..0e93aee4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -721,7 +721,7 @@ python-versions = "*" [[package]] name = "pyparsing" -version = "3.0.6" +version = "3.0.7" description = "Python parsing module" category = "dev" optional = false @@ -1109,7 +1109,7 @@ websockets = ["websockets"] [metadata] lock-version = "1.1" python-versions = "^3.7.3" -content-hash = "0e101f22381597b968f6c51419c1aa284243183f7298ac7837f125510e5a7a53" +content-hash = "b18b98c20de891dfd80f15ac896f13ed529264dd4913ed1ca9cccff3fee379ba" [metadata.files] aiodns = [ @@ -1848,8 +1848,8 @@ pygtrie = [ {file = "pygtrie-2.4.2.tar.gz", hash = "sha256:43205559d28863358dbbf25045029f58e2ab357317a59b11f11ade278ac64692"}, ] pyparsing = [ - {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, - {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"}, + {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, + {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, ] pytest = [ {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, diff --git a/pyproject.toml b/pyproject.toml index ca3998cf..6353eff6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ tomlkit = "^0.7.0" fastapi = "^0.70.0" typing-extensions = ">=3.10.0,<5.0.0" Quart = { version = "^0.16.0", optional = true } -websockets = { version=">=9.1", optional = true } +websockets = { version="^10.0", optional = true } pydantic = { version = "~1.9.0", extras = ["dotenv"] } uvicorn = { version = "^0.15.0", extras = ["standard"] } aiohttp = { version = "^3.7.4", extras = ["speedups"], optional = true }