⬆️ 适配 Pydantic V2 (#484)

* ⬆️ 适配 Pydantic V2

* 🐛 修复测试报错

* 🐛 适配忘记的 from_orm

* 🐛 忘记的 class-based `config`

* 🐛 更新 red 适配器版本
This commit is contained in:
uy/sun 2024-02-29 19:21:25 +08:00 committed by GitHub
parent ca68964ee9
commit b6e68730b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 300 additions and 128 deletions

28
nonebot_bison/compat.py Normal file
View File

@ -0,0 +1,28 @@
from typing import Literal, overload
from pydantic import BaseModel
from nonebot.compat import PYDANTIC_V2
__all__ = ("model_validator", "model_rebuild")
if PYDANTIC_V2:
from pydantic import model_validator as model_validator
def model_rebuild(model: type[BaseModel]):
return model.model_rebuild()
else:
from pydantic import root_validator
@overload
def model_validator(*, mode: Literal["before"]): ...
@overload
def model_validator(*, mode: Literal["after"]): ...
def model_validator(*, mode: Literal["before", "after"]):
return root_validator(pre=mode == "before", allow_reuse=True)
def model_rebuild(model: type[BaseModel]):
return model.update_forward_refs()

View File

@ -3,6 +3,7 @@ from collections import defaultdict
from datetime import time, datetime from datetime import time, datetime
from collections.abc import Callable, Sequence, Awaitable from collections.abc import Callable, Sequence, Awaitable
from nonebot.compat import model_dump
from sqlalchemy.orm import selectinload from sqlalchemy.orm import selectinload
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy import func, delete, select from sqlalchemy import func, delete, select
@ -46,10 +47,10 @@ class DBConfig:
tags: list[Tag], tags: list[Tag],
): ):
async with create_session() as session: async with create_session() as session:
db_user_stmt = select(User).where(User.user_target == user.dict()) db_user_stmt = select(User).where(User.user_target == model_dump(user))
db_user: User | None = await session.scalar(db_user_stmt) db_user: User | None = await session.scalar(db_user_stmt)
if not db_user: if not db_user:
db_user = User(user_target=user.dict()) db_user = User(user_target=model_dump(user))
session.add(db_user) session.add(db_user)
db_target_stmt = select(Target).where(Target.platform_name == platform_name).where(Target.target == target) db_target_stmt = select(Target).where(Target.platform_name == platform_name).where(Target.target == target)
db_target: Target | None = await session.scalar(db_target_stmt) db_target: Target | None = await session.scalar(db_target_stmt)
@ -76,7 +77,7 @@ class DBConfig:
async with create_session() as session: async with create_session() as session:
query_stmt = ( query_stmt = (
select(Subscribe) select(Subscribe)
.where(User.user_target == user.dict()) .where(User.user_target == model_dump(user))
.join(User) .join(User)
.options(selectinload(Subscribe.target)) .options(selectinload(Subscribe.target))
) )
@ -95,7 +96,7 @@ class DBConfig:
async def del_subscribe(self, user: PlatformTarget, target: str, platform_name: str): async def del_subscribe(self, user: PlatformTarget, target: str, platform_name: str):
async with create_session() as session: async with create_session() as session:
user_obj = await session.scalar(select(User).where(User.user_target == user.dict())) user_obj = await session.scalar(select(User).where(User.user_target == model_dump(user)))
target_obj = await session.scalar( target_obj = await session.scalar(
select(Target).where(Target.platform_name == platform_name, Target.target == target) select(Target).where(Target.platform_name == platform_name, Target.target == target)
) )
@ -121,7 +122,7 @@ class DBConfig:
subscribe_obj: Subscribe = await sess.scalar( subscribe_obj: Subscribe = await sess.scalar(
select(Subscribe) select(Subscribe)
.where( .where(
User.user_target == user.dict(), User.user_target == model_dump(user),
Target.target == target, Target.target == target,
Target.platform_name == platform_name, Target.platform_name == platform_name,
) )

View File

@ -1,4 +1,5 @@
from nonebot.log import logger from nonebot.log import logger
from nonebot.compat import model_dump
from nonebot_plugin_datastore.db import get_engine from nonebot_plugin_datastore.db import get_engine
from sqlalchemy.ext.asyncio.session import AsyncSession from sqlalchemy.ext.asyncio.session import AsyncSession
from nonebot_plugin_saa import TargetQQGroup, TargetQQPrivate from nonebot_plugin_saa import TargetQQGroup, TargetQQPrivate
@ -21,7 +22,7 @@ async def data_migrate():
user_target = TargetQQGroup(group_id=user["user"]) user_target = TargetQQGroup(group_id=user["user"])
else: else:
user_target = TargetQQPrivate(user_id=user["user"]) user_target = TargetQQPrivate(user_id=user["user"])
db_user = User(user_target=user_target.dict()) db_user = User(user_target=model_dump(user_target))
user_to_create.append(db_user) user_to_create.append(db_user)
user_sub_set = set() user_sub_set = set()
for sub in user["subs"]: for sub in user["subs"]:

View File

@ -3,6 +3,7 @@ from pathlib import Path
from nonebot_plugin_saa import PlatformTarget from nonebot_plugin_saa import PlatformTarget
from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.dialects.postgresql import JSONB
from nonebot.compat import PYDANTIC_V2, ConfigDict
from nonebot_plugin_datastore import get_plugin_data from nonebot_plugin_datastore import get_plugin_data
from sqlalchemy.orm import Mapped, relationship, mapped_column from sqlalchemy.orm import Mapped, relationship, mapped_column
from sqlalchemy import JSON, String, ForeignKey, UniqueConstraint from sqlalchemy import JSON, String, ForeignKey, UniqueConstraint
@ -46,6 +47,10 @@ class ScheduleTimeWeight(Model):
target: Mapped[Target] = relationship(back_populates="time_weight") target: Mapped[Target] = relationship(back_populates="time_weight")
if PYDANTIC_V2:
model_config = ConfigDict(arbitrary_types_allowed=True)
else:
class Config: class Config:
arbitrary_types_allowed = True arbitrary_types_allowed = True

View File

@ -1,6 +1,7 @@
from abc import ABC from abc import ABC
from pydantic import BaseModel from pydantic import BaseModel
from nonebot.compat import PYDANTIC_V2, ConfigDict
from nonebot_plugin_saa.registries import AllSupportedPlatformTarget as UserInfo from nonebot_plugin_saa.registries import AllSupportedPlatformTarget as UserInfo
from ....types import Tag, Category from ....types import Tag, Category
@ -10,6 +11,10 @@ class NBESFBase(BaseModel, ABC):
version: int # 表示nbesf格式版本有效版本从1开始 version: int # 表示nbesf格式版本有效版本从1开始
groups: list = [] groups: list = []
if PYDANTIC_V2:
model_config = ConfigDict(from_attributes=True)
else:
class Config: class Config:
orm_mode = True orm_mode = True

View File

@ -6,6 +6,7 @@ from functools import partial
from nonebot.log import logger from nonebot.log import logger
from pydantic import BaseModel from pydantic import BaseModel
from nonebot_plugin_saa import TargetQQGroup, TargetQQPrivate from nonebot_plugin_saa import TargetQQGroup, TargetQQPrivate
from nonebot.compat import PYDANTIC_V2, ConfigDict, model_dump, type_validate_json, type_validate_python
from ..utils import NBESFParseErr from ..utils import NBESFParseErr
from ....types import Tag, Category from ....types import Tag, Category
@ -16,14 +17,21 @@ from ...db_config import SubscribeDupException, config
NBESF_VERSION = 1 NBESF_VERSION = 1
class UserHead(BaseModel, orm_mode=True): class UserHead(BaseModel):
"""Bison快递包收货信息""" """Bison快递包收货信息"""
type: str type: str
uid: int uid: int
if PYDANTIC_V2:
model_config = ConfigDict(from_attributes=True)
else:
class Target(BaseModel, orm_mode=True): class Config:
orm_mode = True
class Target(BaseModel):
"""Bsion快递包发货信息""" """Bsion快递包发货信息"""
target_name: str target_name: str
@ -31,14 +39,28 @@ class Target(BaseModel, orm_mode=True):
platform_name: str platform_name: str
default_schedule_weight: int default_schedule_weight: int
if PYDANTIC_V2:
model_config = ConfigDict(from_attributes=True)
else:
class SubPayload(BaseModel, orm_mode=True): class Config:
orm_mode = True
class SubPayload(BaseModel):
"""Bison快递包里的单件货物""" """Bison快递包里的单件货物"""
categories: list[Category] categories: list[Category]
tags: list[Tag] tags: list[Tag]
target: Target target: Target
if PYDANTIC_V2:
model_config = ConfigDict(from_attributes=True)
else:
class Config:
orm_mode = True
class SubPack(BaseModel): class SubPack(BaseModel):
"""Bison给指定用户派送的快递包""" """Bison给指定用户派送的快递包"""
@ -56,7 +78,7 @@ class SubGroup(
结构参见`nbesf_model`下的对应版本 结构参见`nbesf_model`下的对应版本
""" """
version = NBESF_VERSION version: int = NBESF_VERSION
groups: list[SubPack] groups: list[SubPack]
@ -84,7 +106,7 @@ async def subs_receipt_gen(nbesf_data: SubGroup):
tags=sub.tags, tags=sub.tags,
) )
try: try:
await config.add_subscribe(receipt.user, **receipt.dict(exclude={"user"})) await config.add_subscribe(receipt.user, **model_dump(receipt, exclude={"user"}))
except SubscribeDupException: except SubscribeDupException:
logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在") logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在")
except Exception as e: except Exception as e:
@ -96,9 +118,9 @@ async def subs_receipt_gen(nbesf_data: SubGroup):
def nbesf_parser(raw_data: Any) -> SubGroup: def nbesf_parser(raw_data: Any) -> SubGroup:
try: try:
if isinstance(raw_data, str): if isinstance(raw_data, str):
nbesf_data = SubGroup.parse_raw(raw_data) nbesf_data = type_validate_json(SubGroup, raw_data)
else: else:
nbesf_data = SubGroup.parse_obj(raw_data) nbesf_data = type_validate_python(SubGroup, raw_data)
except Exception as e: except Exception as e:
logger.error("数据解析失败该数据格式可能不满足NBESF格式标准") logger.error("数据解析失败该数据格式可能不满足NBESF格式标准")

View File

@ -6,6 +6,7 @@ from functools import partial
from nonebot.log import logger from nonebot.log import logger
from pydantic import BaseModel from pydantic import BaseModel
from nonebot_plugin_saa.registries import AllSupportedPlatformTarget from nonebot_plugin_saa.registries import AllSupportedPlatformTarget
from nonebot.compat import PYDANTIC_V2, ConfigDict, model_dump, type_validate_json, type_validate_python
from ..utils import NBESFParseErr from ..utils import NBESFParseErr
from ....types import Tag, Category from ....types import Tag, Category
@ -16,7 +17,7 @@ from ...db_config import SubscribeDupException, config
NBESF_VERSION = 2 NBESF_VERSION = 2
class Target(BaseModel, orm_mode=True): class Target(BaseModel):
"""Bsion快递包发货信息""" """Bsion快递包发货信息"""
target_name: str target_name: str
@ -24,14 +25,28 @@ class Target(BaseModel, orm_mode=True):
platform_name: str platform_name: str
default_schedule_weight: int default_schedule_weight: int
if PYDANTIC_V2:
model_config = ConfigDict(from_attributes=True)
else:
class SubPayload(BaseModel, orm_mode=True): class Config:
orm_mode = True
class SubPayload(BaseModel):
"""Bison快递包里的单件货物""" """Bison快递包里的单件货物"""
categories: list[Category] categories: list[Category]
tags: list[Tag] tags: list[Tag]
target: Target target: Target
if PYDANTIC_V2:
model_config = ConfigDict(from_attributes=True)
else:
class Config:
orm_mode = True
class SubPack(BaseModel): class SubPack(BaseModel):
"""Bison给指定用户派送的快递包""" """Bison给指定用户派送的快递包"""
@ -68,7 +83,7 @@ async def subs_receipt_gen(nbesf_data: SubGroup):
tags=sub.tags, tags=sub.tags,
) )
try: try:
await config.add_subscribe(receipt.user, **receipt.dict(exclude={"user"})) await config.add_subscribe(receipt.user, **model_dump(receipt, exclude={"user"}))
except SubscribeDupException: except SubscribeDupException:
logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在") logger.warning(f"!添加订阅条目 {repr(receipt)} 失败: 相同的订阅已存在")
except Exception as e: except Exception as e:
@ -80,9 +95,9 @@ async def subs_receipt_gen(nbesf_data: SubGroup):
def nbesf_parser(raw_data: Any) -> SubGroup: def nbesf_parser(raw_data: Any) -> SubGroup:
try: try:
if isinstance(raw_data, str): if isinstance(raw_data, str):
nbesf_data = SubGroup.parse_raw(raw_data) nbesf_data = type_validate_json(SubGroup, raw_data)
else: else:
nbesf_data = SubGroup.parse_obj(raw_data) nbesf_data = type_validate_python(SubGroup, raw_data)
except Exception as e: except Exception as e:
logger.error("数据解析失败该数据格式可能不满足NBESF格式标准") logger.error("数据解析失败该数据格式可能不满足NBESF格式标准")

View File

@ -6,6 +6,7 @@ from sqlalchemy import select
from nonebot.log import logger from nonebot.log import logger
from sqlalchemy.sql.selectable import Select from sqlalchemy.sql.selectable import Select
from nonebot_plugin_saa import PlatformTarget from nonebot_plugin_saa import PlatformTarget
from nonebot.compat import type_validate_python
from nonebot_plugin_datastore.db import create_session from nonebot_plugin_datastore.db import create_session
from sqlalchemy.orm.strategy_options import selectinload from sqlalchemy.orm.strategy_options import selectinload
@ -37,7 +38,7 @@ async def subscribes_export(selector: Callable[[Select], Select]) -> v2.SubGroup
user_id_sub_dict: dict[int, list[v2.SubPayload]] = defaultdict(list) user_id_sub_dict: dict[int, list[v2.SubPayload]] = defaultdict(list)
for sub in sub_data: for sub in sub_data:
sub_paylaod = v2.SubPayload.from_orm(sub) sub_paylaod = type_validate_python(v2.SubPayload, sub)
user_id_sub_dict[sub.user_id].append(sub_paylaod) user_id_sub_dict[sub.user_id].append(sub_paylaod)
for user in user_data: for user in user_data:

View File

@ -4,6 +4,7 @@ from functools import partial
from httpx import AsyncClient from httpx import AsyncClient
from bs4 import BeautifulSoup as bs from bs4 import BeautifulSoup as bs
from pydantic import Field, BaseModel from pydantic import Field, BaseModel
from nonebot.compat import type_validate_python
from ..post import Post from ..post import Post
from ..types import Target, RawPost, Category from ..types import Target, RawPost, Category
@ -28,9 +29,6 @@ class BulletinListItem(BaseModel):
class BulletinList(BaseModel): class BulletinList(BaseModel):
list: list[BulletinListItem] list: list[BulletinListItem]
class Config:
extra = "ignore"
class BulletinData(BaseModel): class BulletinData(BaseModel):
cid: str cid: str
@ -76,7 +74,7 @@ class Arknights(NewMessage):
async def get_sub_list(self, _) -> list[BulletinListItem]: async def get_sub_list(self, _) -> list[BulletinListItem]:
raw_data = await self.client.get("https://ak-webview.hypergryph.com/api/game/bulletinList?target=IOS") raw_data = await self.client.get("https://ak-webview.hypergryph.com/api/game/bulletinList?target=IOS")
return ArkBulletinListResponse.parse_obj(raw_data.json()).data.list return type_validate_python(ArkBulletinListResponse, raw_data.json()).data.list
def get_id(self, post: BulletinListItem) -> Any: def get_id(self, post: BulletinListItem) -> Any:
return post.cid return post.cid
@ -95,7 +93,7 @@ class Arknights(NewMessage):
raw_data = await self.client.get( raw_data = await self.client.get(
f"https://ak-webview.hypergryph.com/api/game/bulletin/{self.get_id(post=raw_post)}" f"https://ak-webview.hypergryph.com/api/game/bulletin/{self.get_id(post=raw_post)}"
) )
data = ArkBulletinResponse.parse_obj(raw_data.json()).data data = type_validate_python(ArkBulletinResponse, raw_data.json()).data
def title_escape(text: str) -> str: def title_escape(text: str) -> str:
return text.replace("\\n", " - ") return text.replace("\\n", " - ")

View File

@ -9,6 +9,9 @@ from datetime import datetime, timedelta
from httpx import AsyncClient from httpx import AsyncClient
from nonebot.log import logger from nonebot.log import logger
from pydantic import Field, BaseModel from pydantic import Field, BaseModel
from nonebot.compat import type_validate_python
from nonebot_bison.compat import model_rebuild
from ..post import Post from ..post import Post
from ..utils import SchedulerConfig, text_similarity from ..utils import SchedulerConfig, text_similarity
@ -303,7 +306,7 @@ class Bilibililive(StatusChange):
infos = [] infos = []
for target in targets: for target in targets:
if target in data.keys(): if target in data.keys():
infos.append(self.Info.parse_obj(data[target])) infos.append(type_validate_python(self.Info, data[target]))
else: else:
infos.append(self._gen_empty_info(int(target))) infos.append(self._gen_empty_info(int(target)))
return infos return infos
@ -428,4 +431,4 @@ class BilibiliBangumi(StatusChange):
) )
Bilibililive.Info.update_forward_refs() model_rebuild(Bilibililive.Info)

View File

@ -1,12 +1,13 @@
import nonebot import nonebot
from pydantic import Field, BaseSettings from nonebot import get_plugin_config
from pydantic import Field, BaseModel
global_config = nonebot.get_driver().config global_config = nonebot.get_driver().config
PlatformName = str PlatformName = str
ThemeName = str ThemeName = str
class PlugConfig(BaseSettings): class PlugConfig(BaseModel):
bison_config_path: str = "" bison_config_path: str = ""
bison_use_pic: bool = Field( bison_use_pic: bool = Field(
default=False, default=False,
@ -22,7 +23,7 @@ class PlugConfig(BaseSettings):
bison_use_pic_merge: int = 0 # 多图片时启用图片合并转发(仅限群) bison_use_pic_merge: int = 0 # 多图片时启用图片合并转发(仅限群)
# 0不启用1首条消息单独发送剩余照片合并转发2以及以上所有消息全部合并转发 # 0不启用1首条消息单独发送剩余照片合并转发2以及以上所有消息全部合并转发
bison_resend_times: int = 0 bison_resend_times: int = 0
bison_proxy: str | None bison_proxy: str | None = None
bison_ua: str = Field( bison_ua: str = Field(
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
description="默认UA", description="默认UA",
@ -34,8 +35,5 @@ class PlugConfig(BaseSettings):
def outer_url(self) -> str: def outer_url(self) -> str:
return self.bison_outer_url or f"http://localhost:{global_config.port}/bison/" return self.bison_outer_url or f"http://localhost:{global_config.port}/bison/"
class Config:
extra = "ignore"
plugin_config = get_plugin_config(PlugConfig)
plugin_config = PlugConfig(**global_config.dict())

View File

@ -8,6 +8,7 @@ from functools import wraps, partial
from collections.abc import Callable, Coroutine from collections.abc import Callable, Coroutine
from nonebot.log import logger from nonebot.log import logger
from nonebot.compat import model_dump
from ..scheduler.manager import init_scheduler from ..scheduler.manager import init_scheduler
from ..config.subs_io.nbesf_model import v1, v2 from ..config.subs_io.nbesf_model import v1, v2
@ -95,14 +96,14 @@ async def subs_export(path: Path, format: str):
# If stream is None, it returns the produced stream. # If stream is None, it returns the produced stream.
# safe_dump produces only standard YAML tags and cannot represent an arbitrary Python object. # safe_dump produces only standard YAML tags and cannot represent an arbitrary Python object.
# 进行以下曲线救国方案 # 进行以下曲线救国方案
json_data = json.dumps(export_data.dict(), ensure_ascii=False) json_data = json.dumps(model_dump(export_data), ensure_ascii=False)
yaml_data = pyyaml.safe_load(json_data) yaml_data = pyyaml.safe_load(json_data)
pyyaml.safe_dump(yaml_data, f, sort_keys=False) pyyaml.safe_dump(yaml_data, f, sort_keys=False)
case "json": case "json":
logger.info("正在导出为json...") logger.info("正在导出为json...")
json.dump(export_data.dict(), f, indent=4, ensure_ascii=False) json.dump(model_dump(export_data), f, indent=4, ensure_ascii=False)
case _: case _:
raise click.BadParameter(message=f"不支持的导出格式: {format}") raise click.BadParameter(message=f"不支持的导出格式: {format}")

View File

@ -3,9 +3,10 @@ from datetime import datetime
from typing import TYPE_CHECKING, Literal from typing import TYPE_CHECKING, Literal
import jinja2 import jinja2
from pydantic import BaseModel, root_validator from pydantic import BaseModel
from nonebot_plugin_saa import Text, Image, MessageSegmentFactory from nonebot_plugin_saa import Text, Image, MessageSegmentFactory
from nonebot_bison.compat import model_validator
from nonebot_bison.theme.utils import convert_to_qr from nonebot_bison.theme.utils import convert_to_qr
from nonebot_bison.theme import Theme, ThemeRenderError, ThemeRenderUnsupportError from nonebot_bison.theme import Theme, ThemeRenderError, ThemeRenderUnsupportError
@ -35,7 +36,7 @@ class CeoboContent(BaseModel):
image: str | None image: str | None
text: str | None text: str | None
@root_validator @model_validator(mode="before")
def check(cls, values): def check(cls, values):
if values["image"] is None and values["text"] is None: if values["image"] is None and values["text"] is None:
raise ValueError("image and text cannot be both None") raise ValueError("image and text cannot be both None")

224
poetry.lock generated
View File

@ -205,6 +205,22 @@ type = "legacy"
url = "https://pypi.org/simple" url = "https://pypi.org/simple"
reference = "offical-source" reference = "offical-source"
[[package]]
name = "annotated-types"
version = "0.6.0"
description = "Reusable constraint types to use with typing.Annotated"
optional = false
python-versions = ">=3.8"
files = [
{file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
{file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
]
[package.source]
type = "legacy"
url = "https://pypi.org/simple"
reference = "offical-source"
[[package]] [[package]]
name = "anyio" name = "anyio"
version = "3.7.1" version = "3.7.1"
@ -2130,13 +2146,13 @@ reference = "offical-source"
[[package]] [[package]]
name = "nb-cli" name = "nb-cli"
version = "1.3.1" version = "1.4.0"
description = "CLI for nonebot2" description = "CLI for nonebot2"
optional = false optional = false
python-versions = "<4.0,>=3.9" python-versions = "<4.0,>=3.9"
files = [ files = [
{file = "nb_cli-1.3.1-py3-none-any.whl", hash = "sha256:fa95e1549d87a1f7fbac5df52532f7ca02c2c871b645b9b69290e35c31d73136"}, {file = "nb_cli-1.4.0-py3-none-any.whl", hash = "sha256:9b75d8ba5861493d266b6a5bd7d609b715e4f95ee3c37e1c91e2ece4ae821c0a"},
{file = "nb_cli-1.3.1.tar.gz", hash = "sha256:9b4dbbd83b9a8b70ba889f143ad303735528727c253c969e0c9935bc879a9051"}, {file = "nb_cli-1.4.0.tar.gz", hash = "sha256:8077bd1f44a6f8ea48f434e19dd942a8843d5b8cf909ab2f1c2a75f8cb4ff938"},
] ]
[package.dependencies] [package.dependencies]
@ -2147,7 +2163,7 @@ cookiecutter = ">=2.2,<3.0"
httpx = ">=0.18,<1.0" httpx = ">=0.18,<1.0"
jinja2 = ">=3.0,<4.0" jinja2 = ">=3.0,<4.0"
noneprompt = ">=0.1.9,<1.0.0" noneprompt = ">=0.1.9,<1.0.0"
pydantic = ">=1.9,<2.0" pydantic = ">=1.10.0,<2.5.0 || >2.5.0,<2.5.1 || >2.5.1,<3.0.0"
pyfiglet = ">=1.0.1,<2.0.0" pyfiglet = ">=1.0.1,<2.0.0"
tomlkit = ">=0.10,<1.0" tomlkit = ">=0.10,<1.0"
typing-extensions = ">=4.4,<5.0" typing-extensions = ">=4.4,<5.0"
@ -2203,13 +2219,13 @@ reference = "offical-source"
[[package]] [[package]]
name = "nonebot-adapter-qq" name = "nonebot-adapter-qq"
version = "1.4.1" version = "1.4.2"
description = "QQ adapter for nonebot2" description = "QQ adapter for nonebot2"
optional = false optional = false
python-versions = ">=3.8,<4.0" python-versions = ">=3.8,<4.0"
files = [ files = [
{file = "nonebot_adapter_qq-1.4.1-py3-none-any.whl", hash = "sha256:dbe59b9559943cb7940f0ff9190ec7428db75be9bc4ba1dbe2cba7ff6e249c23"}, {file = "nonebot_adapter_qq-1.4.2-py3-none-any.whl", hash = "sha256:1bae0016420140841baad81365a8226f448d89ce8bd375f9ec5dd030e244e1da"},
{file = "nonebot_adapter_qq-1.4.1.tar.gz", hash = "sha256:45e99d8caaf7e52857cbd2661d07fd1451bf56d63ef49e80b833933a222dcb26"}, {file = "nonebot_adapter_qq-1.4.2.tar.gz", hash = "sha256:69331998182ecbeec2efa3dee89c63a0d359b93936afa39f158224d96e087c3a"},
] ]
[package.dependencies] [package.dependencies]
@ -2225,17 +2241,17 @@ reference = "offical-source"
[[package]] [[package]]
name = "nonebot-adapter-red" name = "nonebot-adapter-red"
version = "0.8.0" version = "0.9.0"
description = "Red Protocol Adapter for Nonebot2" description = "Red Protocol Adapter for Nonebot2"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "nonebot_adapter_red-0.8.0-py3-none-any.whl", hash = "sha256:9bce0810e67a2754ba68d8c942bec12deeacb55459329f8e7a4f0b6416641180"}, {file = "nonebot_adapter_red-0.9.0-py3-none-any.whl", hash = "sha256:8dd5cd0a5d964faa23823b7c37fa8c64fa3ed8f67fa66515fe44a2708ee438ec"},
{file = "nonebot_adapter_red-0.8.0.tar.gz", hash = "sha256:577c0a286ed1f924339eb398ce1c5efd2cf727029116aff176b8715ab463c234"}, {file = "nonebot_adapter_red-0.9.0.tar.gz", hash = "sha256:a657c5ffb071c91deb4109bb94ac8046dcbea5cbb584437995c30ffb2d184954"},
] ]
[package.dependencies] [package.dependencies]
nonebot2 = ">=2.0.1" nonebot2 = ">=2.2.0"
packaging = ">=23.1" packaging = ">=23.1"
[package.extras] [package.extras]
@ -2268,18 +2284,19 @@ reference = "offical-source"
[[package]] [[package]]
name = "nonebot-plugin-apscheduler" name = "nonebot-plugin-apscheduler"
version = "0.3.0" version = "0.4.0"
description = "APScheduler Support for NoneBot2" description = "APScheduler Support for NoneBot2"
optional = false optional = false
python-versions = ">=3.8,<4.0" python-versions = ">=3.8,<4.0"
files = [ files = [
{file = "nonebot_plugin_apscheduler-0.3.0-py3-none-any.whl", hash = "sha256:ec5e0267293fc9803e543c6086d3e109ac87bf6dccea5473d219cad826238aae"}, {file = "nonebot_plugin_apscheduler-0.4.0-py3-none-any.whl", hash = "sha256:f01bb418a5ecf9f04dcadbbc2ff5ba565a48177eb0a758c8c46b13048ac5680c"},
{file = "nonebot_plugin_apscheduler-0.3.0.tar.gz", hash = "sha256:7c41cc1d49ea6af7c4518c72cd15f8c2f549071b8bc8bfc4b21fbdd0a4875cfd"}, {file = "nonebot_plugin_apscheduler-0.4.0.tar.gz", hash = "sha256:ba91e68809a38e6dbe28906366d47f37f754ded360944b938cd5ac62029a0eb6"},
] ]
[package.dependencies] [package.dependencies]
apscheduler = ">=3.7.0,<4.0.0" apscheduler = ">=3.7.0,<4.0.0"
nonebot2 = ">=2.0.0,<3.0.0" nonebot2 = ">=2.2.0,<3.0.0"
pydantic = ">=1.10.0,<2.5.0 || >2.5.0,<2.5.1 || >2.5.1,<3.0.0"
[package.source] [package.source]
type = "legacy" type = "legacy"
@ -2288,19 +2305,19 @@ reference = "offical-source"
[[package]] [[package]]
name = "nonebot-plugin-datastore" name = "nonebot-plugin-datastore"
version = "1.1.2" version = "1.2.0"
description = "适用于 Nonebot2 的数据存储插件" description = "适用于 Nonebot2 的数据存储插件"
optional = false optional = false
python-versions = ">=3.8,<4.0" python-versions = ">=3.9,<4.0"
files = [ files = [
{file = "nonebot_plugin_datastore-1.1.2-py3-none-any.whl", hash = "sha256:e61044e018c6b60701b38a078b5d0c1ff87e924ee1722675a14006cc32039b05"}, {file = "nonebot_plugin_datastore-1.2.0-py3-none-any.whl", hash = "sha256:22d9bfc948506eda78b010254da6f437c595d0c1878f8852cd92f84a935d204c"},
{file = "nonebot_plugin_datastore-1.1.2.tar.gz", hash = "sha256:32d06d0b06b32d2c02fb3f206820e0da64e0dde542cff3b8aa44abd93b3aeada"}, {file = "nonebot_plugin_datastore-1.2.0.tar.gz", hash = "sha256:34c6c3c19fc0da6808c6f73e931bacb931d7274ab376f23bdf1b352a760799ed"},
] ]
[package.dependencies] [package.dependencies]
alembic = ">=1.9.1,<2.0.0" alembic = ">=1.9.1,<2.0.0"
nonebot-plugin-localstore = ">=0.2.0,<0.3.0 || >0.3.0,<0.4.0 || >0.4.0" nonebot-plugin-localstore = ">=0.6.0"
nonebot2 = {version = ">=2.0.0,<3.0.0", extras = ["httpx"]} nonebot2 = {version = ">=2.2.0,<3.0.0", extras = ["httpx"]}
sqlalchemy = {version = ">=2.0.0,<3.0.0", extras = ["aiosqlite"]} sqlalchemy = {version = ">=2.0.0,<3.0.0", extras = ["aiosqlite"]}
[package.extras] [package.extras]
@ -2363,19 +2380,19 @@ reference = "offical-source"
[[package]] [[package]]
name = "nonebot-plugin-send-anything-anywhere" name = "nonebot-plugin-send-anything-anywhere"
version = "0.5.0" version = "0.6.0"
description = "An adaptor for nonebot2 adaptors" description = "An adaptor for nonebot2 adaptors"
optional = false optional = false
python-versions = ">=3.8,<4.0" python-versions = ">=3.8,<4.0"
files = [ files = [
{file = "nonebot_plugin_send_anything_anywhere-0.5.0-py3-none-any.whl", hash = "sha256:bff64f5f337643ba34b9ea0bdd8d86d3ee6285a29b9083d416a67d4815e83ddf"}, {file = "nonebot_plugin_send_anything_anywhere-0.6.0-py3-none-any.whl", hash = "sha256:30d328c350bc44c39d0e45b622a843275336b4e25d1d670ae1c76ace400fd3d6"},
{file = "nonebot_plugin_send_anything_anywhere-0.5.0.tar.gz", hash = "sha256:0230db94ca5654e2b0462b144db7ea74b763ee04fa7bc53deecacf32362e5268"}, {file = "nonebot_plugin_send_anything_anywhere-0.6.0.tar.gz", hash = "sha256:48196b7fdcb1c6c82ec6d27e225a2f11811aee4393edf86a874985480c4d199d"},
] ]
[package.dependencies] [package.dependencies]
anyio = ">=3.6.2,<4.0.0" anyio = ">=3.3.0,<5.0.0"
nonebot2 = ">=2.0.0,<3.0.0" nonebot2 = ">=2.0.0,<3.0.0"
pydantic = ">=1.10.5,<2.0.0" pydantic = ">=1.10.0,<2.5.0 || >2.5.0,<2.5.1 || >2.5.1,<3.0.0"
strenum = ">=0.4.8,<0.5.0" strenum = ">=0.4.8,<0.5.0"
[package.source] [package.source]
@ -2943,55 +2960,118 @@ reference = "offical-source"
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "1.10.14" version = "2.6.3"
description = "Data validation and settings management using python type hints" description = "Data validation using Python type hints"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.8"
files = [ files = [
{file = "pydantic-1.10.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4fcec873f90537c382840f330b90f4715eebc2bc9925f04cb92de593eae054"}, {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"},
{file = "pydantic-1.10.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e3a76f571970fcd3c43ad982daf936ae39b3e90b8a2e96c04113a369869dc87"}, {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"},
{file = "pydantic-1.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d886bd3c3fbeaa963692ef6b643159ccb4b4cefaf7ff1617720cbead04fd1d"},
{file = "pydantic-1.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:798a3d05ee3b71967844a1164fd5bdb8c22c6d674f26274e78b9f29d81770c4e"},
{file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:23d47a4b57a38e8652bcab15a658fdb13c785b9ce217cc3a729504ab4e1d6bc9"},
{file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9f674b5c3bebc2eba401de64f29948ae1e646ba2735f884d1594c5f675d6f2a"},
{file = "pydantic-1.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:24a7679fab2e0eeedb5a8924fc4a694b3bcaac7d305aeeac72dd7d4e05ecbebf"},
{file = "pydantic-1.10.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d578ac4bf7fdf10ce14caba6f734c178379bd35c486c6deb6f49006e1ba78a7"},
{file = "pydantic-1.10.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa7790e94c60f809c95602a26d906eba01a0abee9cc24150e4ce2189352deb1b"},
{file = "pydantic-1.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad4e10efa5474ed1a611b6d7f0d130f4aafadceb73c11d9e72823e8f508e663"},
{file = "pydantic-1.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245f4f61f467cb3dfeced2b119afef3db386aec3d24a22a1de08c65038b255f"},
{file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:21efacc678a11114c765eb52ec0db62edffa89e9a562a94cbf8fa10b5db5c046"},
{file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:412ab4a3f6dbd2bf18aefa9f79c7cca23744846b31f1d6555c2ee2b05a2e14ca"},
{file = "pydantic-1.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:e897c9f35281f7889873a3e6d6b69aa1447ceb024e8495a5f0d02ecd17742a7f"},
{file = "pydantic-1.10.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d604be0f0b44d473e54fdcb12302495fe0467c56509a2f80483476f3ba92b33c"},
{file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42c7d17706911199798d4c464b352e640cab4351efe69c2267823d619a937e5"},
{file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:596f12a1085e38dbda5cbb874d0973303e34227b400b6414782bf205cc14940c"},
{file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfb113860e9288d0886e3b9e49d9cf4a9d48b441f52ded7d96db7819028514cc"},
{file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bc3ed06ab13660b565eed80887fcfbc0070f0aa0691fbb351657041d3e874efe"},
{file = "pydantic-1.10.14-cp37-cp37m-win_amd64.whl", hash = "sha256:ad8c2bc677ae5f6dbd3cf92f2c7dc613507eafe8f71719727cbc0a7dec9a8c01"},
{file = "pydantic-1.10.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c37c28449752bb1f47975d22ef2882d70513c546f8f37201e0fec3a97b816eee"},
{file = "pydantic-1.10.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49a46a0994dd551ec051986806122767cf144b9702e31d47f6d493c336462597"},
{file = "pydantic-1.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e3819bd20a42470d6dd0fe7fc1c121c92247bca104ce608e609b59bc7a77ee"},
{file = "pydantic-1.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbb503bbbbab0c588ed3cd21975a1d0d4163b87e360fec17a792f7d8c4ff29f"},
{file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:336709883c15c050b9c55a63d6c7ff09be883dbc17805d2b063395dd9d9d0022"},
{file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ae57b4d8e3312d486e2498d42aed3ece7b51848336964e43abbf9671584e67f"},
{file = "pydantic-1.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:dba49d52500c35cfec0b28aa8b3ea5c37c9df183ffc7210b10ff2a415c125c4a"},
{file = "pydantic-1.10.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c66609e138c31cba607d8e2a7b6a5dc38979a06c900815495b2d90ce6ded35b4"},
{file = "pydantic-1.10.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d986e115e0b39604b9eee3507987368ff8148222da213cd38c359f6f57b3b347"},
{file = "pydantic-1.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:646b2b12df4295b4c3148850c85bff29ef6d0d9621a8d091e98094871a62e5c7"},
{file = "pydantic-1.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282613a5969c47c83a8710cc8bfd1e70c9223feb76566f74683af889faadc0ea"},
{file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:466669501d08ad8eb3c4fecd991c5e793c4e0bbd62299d05111d4f827cded64f"},
{file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:13e86a19dca96373dcf3190fcb8797d40a6f12f154a244a8d1e8e03b8f280593"},
{file = "pydantic-1.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:08b6ec0917c30861e3fe71a93be1648a2aa4f62f866142ba21670b24444d7fd8"},
{file = "pydantic-1.10.14-py3-none-any.whl", hash = "sha256:8ee853cd12ac2ddbf0ecbac1c289f95882b2d4482258048079d13be700aa114c"},
{file = "pydantic-1.10.14.tar.gz", hash = "sha256:46f17b832fe27de7850896f3afee50ea682220dd218f7e9c88d436788419dca6"},
] ]
[package.dependencies] [package.dependencies]
typing-extensions = ">=4.2.0" annotated-types = ">=0.4.0"
pydantic-core = "2.16.3"
typing-extensions = ">=4.6.1"
[package.extras] [package.extras]
dotenv = ["python-dotenv (>=0.10.4)"] email = ["email-validator (>=2.0.0)"]
email = ["email-validator (>=1.0.3)"]
[package.source]
type = "legacy"
url = "https://pypi.org/simple"
reference = "offical-source"
[[package]]
name = "pydantic-core"
version = "2.16.3"
description = ""
optional = false
python-versions = ">=3.8"
files = [
{file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
{file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
{file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
{file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
{file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
{file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
{file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
{file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
{file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
{file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
{file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
{file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
{file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
{file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
{file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
{file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
{file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
{file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
{file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
{file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
{file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
{file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
{file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
{file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
{file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
{file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
{file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
{file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
{file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
{file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
{file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
{file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
{file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
]
[package.dependencies]
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
[package.source] [package.source]
type = "legacy" type = "legacy"
@ -3906,13 +3986,13 @@ reference = "offical-source"
[[package]] [[package]]
name = "tomlkit" name = "tomlkit"
version = "0.12.3" version = "0.12.4"
description = "Style preserving TOML library" description = "Style preserving TOML library"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, {file = "tomlkit-0.12.4-py3-none-any.whl", hash = "sha256:5cd82d48a3dd89dee1f9d64420aa20ae65cfbd00668d6f094d7578a78efbb77b"},
{file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, {file = "tomlkit-0.12.4.tar.gz", hash = "sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3"},
] ]
[package.source] [package.source]
@ -4485,4 +4565,4 @@ yaml = []
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = ">=3.10,<4.0.0" python-versions = ">=3.10,<4.0.0"
content-hash = "5853345e1678e8b581c98e75c55d626888054aee3c65264547c19bbd876840d1" content-hash = "13ed3c2ef12bf2fec8ea959ad55d9cc6efb6287b0e584f4db0df98efb4418549"

View File

@ -26,17 +26,18 @@ beautifulsoup4 = ">=4.12.3"
expiringdict = "^1.2.1" expiringdict = "^1.2.1"
feedparser = "^6.0.2" feedparser = "^6.0.2"
httpx = ">=0.16.1" httpx = ">=0.16.1"
nonebot2 = {extras = ["fastapi"], version = "^2.1.3"} nonebot2 = { extras = ["fastapi"], version = "^2.2.1" }
nonebot-adapter-onebot = "^2.0.0" nonebot-adapter-onebot = "^2.0.0"
nonebot-plugin-htmlrender = ">=0.2.0" nonebot-plugin-htmlrender = ">=0.2.0"
nonebot-plugin-datastore = ">=0.6.2,<2.0.0" nonebot-plugin-datastore = ">=1.2.0,<2.0.0"
nonebot-plugin-apscheduler = ">=0.2,<0.4" nonebot-plugin-apscheduler = ">=0.4.0"
nonebot-plugin-send-anything-anywhere = "^0.5.0" nonebot-plugin-send-anything-anywhere = ">=0.5.0,<0.7.0"
pillow = ">=8.1,<11.0" pillow = ">=8.1,<11.0"
pyjwt = "^2.1.0" pyjwt = "^2.1.0"
python-socketio = "^5.4.0" python-socketio = "^5.4.0"
tinydb = "^4.3.0" tinydb = "^4.3.0"
qrcode = "^7.4.2" qrcode = "^7.4.2"
pydantic = ">=1.10.0,<3.0.0,!=2.5.0,!=2.5.1"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
black = ">=23.7,<25.0" black = ">=23.7,<25.0"
@ -62,10 +63,10 @@ respx = "^0.20.0"
optional = true optional = true
[tool.poetry.group.docker.dependencies] [tool.poetry.group.docker.dependencies]
nb-cli = "^1.2.8" nb-cli = "^1.4.0"
nonebot2 = {extras = ["fastapi", "aiohttp"], version = "^2.1.3"} nonebot2 = { extras = ["fastapi", "aiohttp"], version = "^2.2.1" }
nonebot-adapter-red = ">=0.7.4,<0.9.0" nonebot-adapter-red = "^0.9.0"
nonebot-adapter-qq = "^1.3.4" nonebot-adapter-qq = "^1.4.2"
nonebot-adapter-telegram = "^0.1.0b14" nonebot-adapter-telegram = "^0.1.0b14"
poetry-core = "^1.8.1" poetry-core = "^1.8.1"
@ -131,6 +132,7 @@ executionEnvironments = [
] }, ] },
{ root = "./" }, { root = "./" },
] ]
defineConstant = { PYDANTIC_V2 = true }
[[tool.poetry.source]] [[tool.poetry.source]]
name = "offical-source" name = "offical-source"

View File

@ -1,5 +1,6 @@
import pytest import pytest
from nonebug.app import App from nonebug.app import App
from nonebot.compat import model_dump
from .utils import get_json from .utils import get_json
@ -41,14 +42,14 @@ async def test_subs_export(app: App, init_scheduler):
assert len(data) == 3 assert len(data) == 3
nbesf_data = await subscribes_export(lambda x: x) nbesf_data = await subscribes_export(lambda x: x)
assert nbesf_data.dict() == get_json("v2/subs_export.json") assert model_dump(nbesf_data) == get_json("v2/subs_export.json")
nbesf_data_user_234 = await subscribes_export( nbesf_data_user_234 = await subscribes_export(
lambda stmt: stmt.where(User.user_target == {"platform_type": "QQ Group", "group_id": 2342}) lambda stmt: stmt.where(User.user_target == {"platform_type": "QQ Group", "group_id": 2342})
) )
assert len(nbesf_data_user_234.groups) == 1 assert len(nbesf_data_user_234.groups) == 1
assert len(nbesf_data_user_234.groups[0].subs) == 2 assert len(nbesf_data_user_234.groups[0].subs) == 2
assert nbesf_data_user_234.groups[0].user_target == { assert model_dump(nbesf_data_user_234.groups[0].user_target) == {
"group_id": 2342, "group_id": 2342,
"platform_type": "QQ Group", "platform_type": "QQ Group",
} }

View File

@ -1,5 +1,7 @@
from typing import TYPE_CHECKING, Literal, TypedDict from typing import TYPE_CHECKING, Literal, TypedDict
from nonebot.compat import PYDANTIC_V2, ConfigDict
if TYPE_CHECKING: if TYPE_CHECKING:
from nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent from nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent
@ -35,6 +37,10 @@ def fake_group_message_event(**field) -> "GroupMessageEvent":
) )
to_me: bool = False to_me: bool = False
if PYDANTIC_V2:
model_config = ConfigDict(extra="forbid")
else:
class Config: class Config:
extra = "forbid" extra = "forbid"
@ -62,6 +68,10 @@ def fake_private_message_event(**field) -> "PrivateMessageEvent":
sender: Sender = Sender(nickname="test") sender: Sender = Sender(nickname="test")
to_me: bool = False to_me: bool = False
if PYDANTIC_V2:
model_config = ConfigDict(extra="forbid")
else:
class Config: class Config:
extra = "forbid" extra = "forbid"