diff --git a/nonebot/__init__.py b/nonebot/__init__.py index 23ecf93d..ead5b6d6 100644 --- a/nonebot/__init__.py +++ b/nonebot/__init__.py @@ -49,6 +49,7 @@ from typing import Any, Dict, Type, Union, TypeVar, Optional, overload import loguru +from nonebot.compat import model_dump from nonebot.log import logger as logger from nonebot.adapters import Bot, Adapter from nonebot.config import DOTENV_TYPE, Env, Config @@ -310,7 +311,7 @@ def init(*, _env_file: Optional[DOTENV_TYPE] = None, **kwargs: Any) -> None: f"Current Env: {escape_tag(env.environment)}" ) logger.opt(colors=True).debug( - f"Loaded Config: {escape_tag(str(config.dict()))}" + f"Loaded Config: {escape_tag(str(model_dump(config)))}" ) DriverClass = _resolve_combine_expr(config.driver) diff --git a/nonebot/compat.py b/nonebot/compat.py index 348179db..df5dbb0d 100644 --- a/nonebot/compat.py +++ b/nonebot/compat.py @@ -194,8 +194,9 @@ if PYDANTIC_V2: # pragma: pydantic-v2 model: BaseModel, include: Optional[Set[str]] = None, exclude: Optional[Set[str]] = None, + by_alias: bool = False, ) -> Dict[str, Any]: - return model.model_dump(include=include, exclude=exclude) + return model.model_dump(include=include, exclude=exclude, by_alias=by_alias) def type_validate_python(type_: Type[T], data: Any) -> T: """Validate data with given type.""" @@ -339,8 +340,9 @@ else: # pragma: pydantic-v1 model: BaseModel, include: Optional[Set[str]] = None, exclude: Optional[Set[str]] = None, + by_alias: bool = False, ) -> Dict[str, Any]: - return model.dict(include=include, exclude=exclude) + return model.dict(include=include, exclude=exclude, by_alias=by_alias) def type_validate_python(type_: Type[T], data: Any) -> T: """Validate data with given type.""" diff --git a/nonebot/drivers/fastapi.py b/nonebot/drivers/fastapi.py index 86094c66..b1515136 100644 --- a/nonebot/drivers/fastapi.py +++ b/nonebot/drivers/fastapi.py @@ -31,6 +31,7 @@ from nonebot.drivers import Driver as BaseDriver from nonebot.config import Config as NoneBotConfig from nonebot.drivers import Request as BaseRequest from nonebot.drivers import WebSocket as BaseWebSocket +from nonebot.compat import model_dump, type_validate_python from nonebot.drivers import HTTPServerSetup, WebSocketServerSetup try: @@ -89,7 +90,7 @@ class Driver(BaseDriver, ASGIMixin): def __init__(self, env: Env, config: NoneBotConfig): super().__init__(env, config) - self.fastapi_config: Config = Config(**config.dict()) + self.fastapi_config: Config = type_validate_python(Config, model_dump(config)) self._server_app = FastAPI( lifespan=self._lifespan_manager, diff --git a/nonebot/drivers/quart.py b/nonebot/drivers/quart.py index dd9b91c7..9ab73a31 100644 --- a/nonebot/drivers/quart.py +++ b/nonebot/drivers/quart.py @@ -30,6 +30,7 @@ from nonebot.drivers import Driver as BaseDriver from nonebot.config import Config as NoneBotConfig from nonebot.drivers import Request as BaseRequest from nonebot.drivers import WebSocket as BaseWebSocket +from nonebot.compat import model_dump, type_validate_python from nonebot.drivers import HTTPServerSetup, WebSocketServerSetup try: @@ -81,7 +82,7 @@ class Driver(BaseDriver, ASGIMixin): def __init__(self, env: Env, config: NoneBotConfig): super().__init__(env, config) - self.quart_config = Config(**config.dict()) + self.quart_config = type_validate_python(Config, model_dump(config)) self._server_app = Quart( self.__class__.__qualname__, **self.quart_config.quart_extra diff --git a/website/docs/appendices/rule.md b/website/docs/appendices/rule.md index bccb413f..a4e55a87 100644 --- a/website/docs/appendices/rule.md +++ b/website/docs/appendices/rule.md @@ -21,7 +21,7 @@ options: `RuleChecker` 是一个返回值为 `bool` 类型的依赖函数,即 `RuleChecker` 支持依赖注入。我们可以根据上一节中添加的[配置项](./config.mdx#插件配置),在 `weather` 插件目录中编写一个响应规则: ```python {3,4} title=weather/__init__.py -plugin_config = Config.parse_obj(get_driver().config) +plugin_config = get_plugin_config(Config) async def is_enable() -> bool: return plugin_config.weather_plugin_enabled @@ -57,7 +57,7 @@ weather = on_command("天气", rule=rule) ```python {10} title=weather/__init__.py from nonebot.rule import to_me -plugin_config = Config.parse_obj(get_driver().config) +plugin_config = get_plugin_config(Config) async def is_enable() -> bool: return plugin_config.weather_plugin_enabled diff --git a/website/docs/developer/adapter-writing.md b/website/docs/developer/adapter-writing.md index 0e835da9..33cd2b7a 100644 --- a/website/docs/developer/adapter-writing.md +++ b/website/docs/developer/adapter-writing.md @@ -97,6 +97,7 @@ from typing import Any from typing_extensions import override from nonebot.drivers import Driver +from nonebot import get_plugin_config from nonebot.adapters import Adapter as BaseAdapter from .config import Config @@ -106,7 +107,7 @@ class Adapter(BaseAdapter): def __init__(self, driver: Driver, **kwargs: Any): super().__init__(driver, **kwargs) # 读取适配器所需的配置项 - self.adapter_config: Config = Config(**self.config.dict()) + self.adapter_config: Config = get_plugin_config(Config) @classmethod @override @@ -125,6 +126,7 @@ NoneBot 提供了多种 [Driver](../advanced/driver) 来帮助适配器进行网 import asyncio from typing_extensions import override +from nonebot import get_plugin_config from nonebot.exception import WebSocketClosed from nonebot.drivers import Request, WebSocketClientMixin @@ -132,7 +134,7 @@ class Adapter(BaseAdapter): @override def __init__(self, driver: Driver, **kwargs: Any): super().__init__(driver, **kwargs) - self.adapter_config: Config = Config(**self.config.dict()) + self.adapter_config: Config = get_plugin_config(Config) self.task: Optional[asyncio.Task] = None # 存储 ws 任务 self.setup() @@ -200,6 +202,7 @@ class Adapter(BaseAdapter): ##### 服务端通信方式 ```python {30,38} title=adapter.py +from nonebot import get_plugin_config from nonebot.drivers import ( Request, ASGIMixin, @@ -212,7 +215,7 @@ class Adapter(BaseAdapter): @override def __init__(self, driver: Driver, **kwargs: Any): super().__init__(driver, **kwargs) - self.adapter_config: Config = Config(**self.config.dict()) + self.adapter_config: Config = get_plugin_config(Config) self.setup() def setup(self) -> None: @@ -286,6 +289,8 @@ class Adapter(BaseAdapter): import asyncio from typing import Any, Dict +from nonebot.compat import type_validate_python + from .bot import Bot from .event import Event from .log import log @@ -301,7 +306,7 @@ class Adapter(BaseAdapter): # 做一层异常处理,以应对平台事件数据的变更 try: - return your_event_class.parse_obj(payload) + return type_validate_python(your_event_class, payload) except Exception as e: # 无法正常解析为具体 Event 时,给出日志提示 log( @@ -309,7 +314,7 @@ class Adapter(BaseAdapter): f"Parse event error: {str(payload)}", ) # 也可以尝试转为基础 Event 进行处理 - return Event.parse_obj(payload) + return type_validate_python(Event, payload) async def _forward(self, bot: Bot): @@ -440,6 +445,7 @@ Event 是 NoneBot 中的事件主体对象,所有平台消息在进入处理 ```python {5,8,13,18,23,28,33} title=event.py from typing_extensions import override +from nonebot.compat import model_dump from nonebot.adapters import Event as BaseEvent class Event(BaseEvent): @@ -452,7 +458,7 @@ class Event(BaseEvent): @override def get_event_description(self) -> str: # 返回事件的描述,用于日志打印,请注意转义 loguru tag - return escape_tag(repr(self.dict())) + return escape_tag(repr(model_dump(self))) @override def get_message(self):