From cc9e1d09a09d6e3edd756bd5ab4fe1456326c33a Mon Sep 17 00:00:00 2001 From: mizhexiaoxiao <1157861072@qq.com> Date: Tue, 19 Sep 2023 11:22:50 +0800 Subject: [PATCH] Upgrade to pydantic2.0 --- app/api/v1/apis/apis.py | 17 +- app/api/v1/base/base.py | 24 +-- app/api/v1/menus/menus.py | 14 +- app/api/v1/roles/roles.py | 27 +-- app/api/v1/users/users.py | 21 +- app/core/crud.py | 4 +- app/models/admin.py | 4 +- app/models/base.py | 45 ++++- app/schemas/apis.py | 2 +- app/schemas/base.py | 64 ++++-- app/schemas/login.py | 3 +- app/schemas/menus.py | 19 +- app/schemas/roles.py | 21 +- app/schemas/users.py | 17 +- app/settings/config.py | 6 +- poetry.lock | 311 +++++++++++++++++++++-------- pyproject.toml | 3 +- web/src/utils/http/interceptors.js | 27 +-- 18 files changed, 384 insertions(+), 245 deletions(-) diff --git a/app/api/v1/apis/apis.py b/app/api/v1/apis/apis.py index fc5a936..f1e6c71 100644 --- a/app/api/v1/apis/apis.py +++ b/app/api/v1/apis/apis.py @@ -26,12 +26,9 @@ async def list_api( q &= Q(summary__contains=summary) if tags: q &= Q(tags__contains=tags) - total, api_objs = await api_controller.list(page=page, page_size=page_size, search=q, order=["id"]) - result = [] - for api in api_objs: - api_dict = await api.to_dict(m2m=False) - result.append(api_dict) - return SuccessExtra(data=result, total=total, page=page, page_size=page_size) + total, api_objs = await api_controller.list(page=page, page_size=page_size, search=q, order=["tags", "id"]) + data = [await obj.to_dict() for obj in api_objs] + return SuccessExtra(data=data, total=total, page=page, page_size=page_size) @router.get("/get", summary="查看Api") @@ -39,16 +36,16 @@ async def get_api( id: int = Query(..., description="Api"), ): api_obj = await api_controller.get(id=id) - api_dict = await api_obj.to_dict() - return Success(code=200, data=api_dict) + data = await api_obj.to_dict() + return Success(data=data) @router.post("/create", summary="创建Api") async def create_api( api_in: ApiCreate, ): - new_api = await api_controller.create(obj_in=api_in) - return Success(msg="Created Successfully", data=new_api) + await api_controller.create(obj_in=api_in) + return Success(msg="Created Successfully") @router.post("/update", summary="更新Api") diff --git a/app/api/v1/base/base.py b/app/api/v1/base/base.py index eeefe52..4850ede 100644 --- a/app/api/v1/base/base.py +++ b/app/api/v1/base/base.py @@ -6,7 +6,7 @@ from app.controllers.user import UserController, user_controller from app.core.ctx import CTX_USER_ID from app.core.dependency import DependAuth from app.models.admin import Api, Menu, Role, User -from app.schemas.base import BaseResponse, Fail, Success +from app.schemas.base import Fail, Success from app.schemas.login import * from app.schemas.users import UpdatePassword from app.settings import settings @@ -17,13 +17,13 @@ router = APIRouter() @router.post("/access_token", summary="获取token") -async def login_access_token(credentials: CredentialsSchema) -> BaseResponse: +async def login_access_token(credentials: CredentialsSchema): user: User = await user_controller.authenticate(credentials) await user_controller.update_last_login(user.id) access_token_expires = timedelta(minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES) expire = datetime.utcnow() + access_token_expires - result = JWTOut( + data = JWTOut( access_token=create_access_token( data=JWTPayload( user_id=user.id, @@ -34,23 +34,21 @@ async def login_access_token(credentials: CredentialsSchema) -> BaseResponse: ), username=user.username, ) - - return BaseResponse(code=200, data=result) + return Success(data=data.model_dump()) @router.get("/userinfo", summary="查看用户信息", dependencies=[DependAuth]) async def get_userinfo(): user_id = CTX_USER_ID.get() user_obj = await user_controller.get(id=user_id) - to_dict = await user_obj.to_dict() - to_dict.pop("password") - to_dict["avatar"] = "https://avatars.githubusercontent.com/u/54677442?v=4" - - return BaseResponse(code=200, data=to_dict) + data = await user_obj.to_dict() + data.pop("password") + data["avatar"] = "https://avatars.githubusercontent.com/u/54677442?v=4" + return Success(data=data) @router.get("/usermenu", summary="查看用户菜单", dependencies=[DependAuth]) -async def get_user_menu() -> BaseResponse: +async def get_user_menu(): user_id = CTX_USER_ID.get() user_obj = await User.filter(id=user_id).first() menus: list[Menu] = [] @@ -78,7 +76,7 @@ async def get_user_menu() -> BaseResponse: @router.get("/userapi", summary="查看用户API", dependencies=[DependAuth]) -async def get_user_api() -> BaseResponse: +async def get_user_api(): user_id = CTX_USER_ID.get() user_obj = await User.filter(id=user_id).first() if user_obj.is_superuser: @@ -95,7 +93,7 @@ async def get_user_api() -> BaseResponse: @router.post("/update_password", summary="更新用户密码", dependencies=[DependAuth]) -async def update_user_password(req_in: UpdatePassword) -> BaseResponse: +async def update_user_password(req_in: UpdatePassword): user_controller = UserController() user = await user_controller.get(req_in.id) verified = verify_password(req_in.old_password, user.password) diff --git a/app/api/v1/menus/menus.py b/app/api/v1/menus/menus.py index 9eeef21..a6a5718 100644 --- a/app/api/v1/menus/menus.py +++ b/app/api/v1/menus/menus.py @@ -3,7 +3,7 @@ import logging from fastapi import APIRouter, Query from app.controllers.menu import menu_controller -from app.schemas.base import BaseResponse, Fail, Success +from app.schemas.base import Fail, Success, SuccessExtra from app.schemas.menus import * logger = logging.getLogger(__name__) @@ -15,13 +15,13 @@ router = APIRouter() async def list_menu( page: int = Query(1, description="页码"), page_size: int = Query(10, description="每页数量"), -) -> MenuOutList: +): parent_menus = await menu_controller.model.filter(parent_id=0).order_by("order") res_menu = [] for menu in parent_menus: child_menu = await menu_controller.model.filter(parent_id=menu.id).order_by("order") menu_dict = await menu.to_dict() - menu_dict["children"] = child_menu + menu_dict["children"] = [await obj.to_dict() for obj in child_menu] res_menu.append(menu_dict) return SuccessExtra(data=res_menu, total=len(res_menu), page=page, page_size=page_size) @@ -29,7 +29,7 @@ async def list_menu( @router.get("/get", summary="查看菜单") async def get_menu( menu_id: int = Query(..., description="菜单id"), -) -> BaseResponse: +): result = await menu_controller.get(id=menu_id) return Success(data=result) @@ -37,7 +37,7 @@ async def get_menu( @router.post("/create", summary="创建菜单") async def create_menu( menu_in: MenuCreate, -) -> BaseResponse: +): await menu_controller.create(obj_in=menu_in) return Success(msg="Created Success") @@ -45,7 +45,7 @@ async def create_menu( @router.post("/update", summary="更新菜单") async def update_menu( menu_in: MenuUpdate, -) -> BaseResponse: +): await menu_controller.update(id=menu_in.id, obj_in=menu_in.update_dict()) return Success(msg="Updated Success") @@ -53,7 +53,7 @@ async def update_menu( @router.delete("/delete", summary="删除菜单") async def delete_menu( id: int = Query(..., description="菜单id"), -) -> BaseResponse: +): child_menu_count = await menu_controller.model.filter(parent_id=id).count() if child_menu_count > 0: return Fail(msg="Cannot delete a menu with child menus") diff --git a/app/api/v1/roles/roles.py b/app/api/v1/roles/roles.py index 7357a96..0255e4b 100644 --- a/app/api/v1/roles/roles.py +++ b/app/api/v1/roles/roles.py @@ -5,7 +5,7 @@ from fastapi.exceptions import HTTPException from tortoise.expressions import Q from app.controllers import role_controller -from app.schemas.base import BaseResponse, Success, SuccessExtra +from app.schemas.base import Success, SuccessExtra from app.schemas.roles import * logger = logging.getLogger(__name__) @@ -17,26 +17,27 @@ async def list_role( page: int = Query(1, description="页码"), page_size: int = Query(10, description="每页数量"), role_name: str = Query("", description="角色名称,用于查询"), -) -> RoleOutList: +): q = Q() if role_name: q = Q(name__contains=role_name) - total, result = await role_controller.list(page=page, page_size=page_size, search=q) - return SuccessExtra(data=result, total=total, page=page, page_size=page_size) + total, role_objs = await role_controller.list(page=page, page_size=page_size, search=q) + data = [await obj.to_dict() for obj in role_objs] + return SuccessExtra(data=data, total=total, page=page, page_size=page_size) @router.get("/get", summary="查看角色") async def get_role( role_id: int = Query(..., description="角色ID"), -) -> RoleOut: +): role_obj = await role_controller.get(id=role_id) - return Success(data=role_obj) + return Success(data=await role_obj.to_dict()) @router.post("/create", summary="创建角色") async def create_role( role_in: RoleCreate, -) -> BaseResponse: +): if await role_controller.is_exist(name=role_in.name): raise HTTPException( status_code=400, @@ -47,7 +48,7 @@ async def create_role( @router.post("/update", summary="更新角色") -async def update_role(role_in: RoleUpdate) -> BaseResponse: +async def update_role(role_in: RoleUpdate): await role_controller.update(id=role_in.id, obj_in=role_in.update_dict()) return Success(msg="Updated Successfully") @@ -55,20 +56,20 @@ async def update_role(role_in: RoleUpdate) -> BaseResponse: @router.delete("/delete", summary="删除角色") async def delete_role( role_id: int = Query(..., description="角色ID"), -) -> BaseResponse: +): await role_controller.remove(id=role_id) return Success(msg="Deleted Success") @router.get("/authorized", summary="查看角色权限") -async def get_role_authorized(id: int = Query(..., description="角色ID")) -> BaseResponse: +async def get_role_authorized(id: int = Query(..., description="角色ID")): role_obj = await role_controller.get(id=id) - role_dict = await role_obj.to_dict() - return Success(data=role_dict) + data = await role_obj.to_dict(m2m=True) + return Success(data=data) @router.post("/authorized", summary="更新角色权限") -async def update_role_authorized(role_in: RoleUpdateMenusApis) -> BaseResponse: +async def update_role_authorized(role_in: RoleUpdateMenusApis): role_obj = await role_controller.get(id=role_in.id) await role_controller.update_roles(role=role_obj, menu_ids=role_in.menu_ids, api_infos=role_in.api_infos) return Success(msg="Updated Successfully") diff --git a/app/api/v1/users/users.py b/app/api/v1/users/users.py index bcc22e2..94c00a3 100644 --- a/app/api/v1/users/users.py +++ b/app/api/v1/users/users.py @@ -6,7 +6,7 @@ from tortoise.expressions import Q from app.controllers.user import UserController from app.core.dependency import DependPermisson -from app.schemas.base import BaseResponse, Success, SuccessExtra +from app.schemas.base import Success, SuccessExtra from app.schemas.users import * logger = logging.getLogger(__name__) @@ -20,7 +20,7 @@ async def list_user( page_size: int = Query(10, description="每页数量"), username: str = Query("", description="用户名称,用于搜索"), email: str = Query("", description="邮箱地址"), -) -> UserOutList: +): user_controller = UserController() q = Q() if username: @@ -28,27 +28,24 @@ async def list_user( if email: q &= Q(email__contains=email) total, user_objs = await user_controller.list(page=page, page_size=page_size, search=q) - result = [] - for user in user_objs: - user_dict = await user.to_dict() - result.append(user_dict) - return SuccessExtra(data=result, total=total, page=page, page_size=page_size) + data = [await obj.to_dict(m2m=True) for obj in user_objs] + return SuccessExtra(data=data, total=total, page=page, page_size=page_size) @router.get("/get", summary="查看用户", dependencies=[DependPermisson]) async def get_user( user_id: int = Query(..., description="用户ID"), -) -> UserOut: +): user_controller = UserController() user_obj = await user_controller.get(id=user_id) user_dict = await user_obj.to_dict() - return Success(code=200, data=user_dict) + return Success(data=user_dict) @router.post("/create", summary="创建用户", dependencies=[DependPermisson]) async def create_user( user_in: UserCreate, -) -> BaseResponse: +): user_controller = UserController() user = await user_controller.get_by_email(user_in.email) if user: @@ -64,7 +61,7 @@ async def create_user( @router.post("/update", summary="更新用户", dependencies=[DependPermisson]) async def update_user( user_in: UserUpdate, -) -> BaseResponse: +): user_controller = UserController() user = await user_controller.update(obj_in=user_in) await user_controller.update_roles(user, user_in.roles) @@ -74,7 +71,7 @@ async def update_user( @router.delete("/delete", summary="删除用户", dependencies=[DependPermisson]) async def delete_user( user_id: int = Query(..., description="用户ID"), -) -> BaseResponse: +): user_controller = UserController() await user_controller.remove(id=user_id) return Success(msg="Deleted Successfully") diff --git a/app/core/crud.py b/app/core/crud.py index 6743427..7f85c26 100644 --- a/app/core/crud.py +++ b/app/core/crud.py @@ -25,7 +25,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]): if isinstance(obj_in, Dict): obj_dict = obj_in else: - obj_dict = obj_in.dict() + obj_dict = obj_in.model_dump() obj = self.model(**obj_dict) await obj.save() return obj @@ -34,7 +34,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]): if isinstance(obj_in, Dict): obj_dict = obj_in else: - obj_dict = obj_in.dict(exclude_unset=True) + obj_dict = obj_in.model_dump(exclude_unset=True) obj = await self.get(id=id) obj = obj.update_from_dict(obj_dict) await obj.save() diff --git a/app/models/admin.py b/app/models/admin.py index d62dd26..93b2df6 100644 --- a/app/models/admin.py +++ b/app/models/admin.py @@ -2,7 +2,7 @@ from tortoise import fields from app.schemas.menus import MenuType -from .base import BaseModel, TimestampMixin +from .base import BaseModel, CustomDatetimeField, TimestampMixin from .enums import MethodType @@ -14,7 +14,7 @@ class User(BaseModel, TimestampMixin): password = fields.CharField(max_length=128, null=True, description="密码") is_active = fields.BooleanField(default=True, description="是否激活") is_superuser = fields.BooleanField(default=False, description="是否为超级管理员") - last_login = fields.DatetimeField(null=True, description="最后登录时间") + last_login = CustomDatetimeField(null=True, description="最后登录时间") roles = fields.ManyToManyField("models.Role", related_name="user_roles") class Meta: diff --git a/app/models/base.py b/app/models/base.py index 8ed2045..0254877 100644 --- a/app/models/base.py +++ b/app/models/base.py @@ -1,16 +1,29 @@ -from tortoise import fields, models +import datetime +import functools +from typing import Any, Optional + +from tortoise import fields, models, timezone + +try: + from ciso8601 import parse_datetime +except ImportError: # pragma: nocoverage + from iso8601 import parse_date + + parse_datetime = functools.partial(parse_date, default_timezone=None) +from tortoise.timezone import get_timezone, localtime class BaseModel(models.Model): id = fields.BigIntField(pk=True, index=True) - async def to_dict(self, m2m=True): + async def to_dict(self, m2m=False): d = {} for field in self._meta.db_fields: d[field] = getattr(self, field) if m2m: for field in self._meta.m2m_fields: - d[field] = await getattr(self, field).all().values() + values = await getattr(self, field).all().values() + d[field] = values return d class Meta: @@ -21,6 +34,28 @@ class UUIDModel: uuid = fields.UUIDField(unique=True, pk=False) +class CustomDatetimeField(fields.DatetimeField): + def to_python_value(self, value: Any) -> Optional[datetime.datetime]: + if value is None: + value = None + else: + if isinstance(value, datetime.datetime): + value = value.strftime("%Y-%m-%d %H:%M:%S") + elif isinstance(value, int): + value = datetime.datetime.fromtimestamp(value) + value = value.strftime("%Y-%m-%d %H:%M:%S") + else: + value = parse_datetime(value) + if timezone.is_naive(value): + value = timezone.make_aware(value, get_timezone()) + value = value.strftime("%Y-%m-%d %H:%M:%S") + else: + value = localtime(value) + value = value.strftime("%Y-%m-%d %H:%M:%S") + self.validate(value) + return value + + class TimestampMixin: - created_at = fields.DatetimeField(auto_now_add=True) - updated_at = fields.DatetimeField(auto_now=True) + created_at = CustomDatetimeField(auto_now_add=True) + updated_at = CustomDatetimeField(auto_now=True) diff --git a/app/schemas/apis.py b/app/schemas/apis.py index 2ee5586..cae5631 100644 --- a/app/schemas/apis.py +++ b/app/schemas/apis.py @@ -18,4 +18,4 @@ class ApiUpdate(BaseApi): id: int def update_dict(self): - return self.dict(exclude_unset=True, exclude={"id"}) + return self.model_dump(exclude_unset=True, exclude={"id"}) diff --git a/app/schemas/base.py b/app/schemas/base.py index 25a8fb9..bbb69b8 100644 --- a/app/schemas/base.py +++ b/app/schemas/base.py @@ -1,26 +1,52 @@ -from typing import Generic, Optional, TypeVar +from typing import Any, Optional -from pydantic import BaseModel -from pydantic.generics import GenericModel - -DataT = TypeVar("DataT") +from fastapi.responses import JSONResponse -class BaseResponse(GenericModel, BaseModel, Generic[DataT]): - code: int - msg: str = "" - data: Optional[DataT] = None +class Success(JSONResponse): + def __init__( + self, + code: int = 200, + msg: Optional[str] = "OK", + data: Optional[Any] = None, + **kwargs, + ): + content = {"code": code, "msg": msg, "data": data} + content.update(kwargs) + super().__init__(content=content, status_code=code) -class Success(BaseResponse): - code: int = 200 +class Fail(JSONResponse): + def __init__( + self, + code: int = 400, + msg: Optional[str] = None, + data: Optional[Any] = None, + **kwargs, + ): + content = {"code": code, "msg": msg, "data": data} + content.update(kwargs) + super().__init__(content=content, status_code=code) -class Fail(BaseResponse): - code: int = -1 - - -class SuccessExtra(Success): - total: int - page: int - page_size: int +class SuccessExtra(JSONResponse): + def __init__( + self, + code: int = 200, + msg: Optional[str] = None, + data: Optional[Any] = None, + total: int = 0, + page: int = 1, + page_size: int = 20, + **kwargs, + ): + content = { + "code": code, + "msg": msg, + "data": data, + "total": total, + "page": page, + "page_size": page_size, + } + content.update(kwargs) + super().__init__(content=content, status_code=code) diff --git a/app/schemas/login.py b/app/schemas/login.py index eaefafc..67cd483 100644 --- a/app/schemas/login.py +++ b/app/schemas/login.py @@ -1,7 +1,6 @@ from datetime import datetime -from typing import Optional -from pydantic import BaseModel, EmailStr, Field +from pydantic import BaseModel, Field class CredentialsSchema(BaseModel): diff --git a/app/schemas/menus.py b/app/schemas/menus.py index 86aa364..a83402a 100644 --- a/app/schemas/menus.py +++ b/app/schemas/menus.py @@ -1,10 +1,8 @@ from enum import Enum -from typing import List, Optional +from typing import Optional from pydantic import BaseModel, Field -from .base import BaseResponse, SuccessExtra - class MenuType(str, Enum): CATALOG = "catalog" # 目录 @@ -30,7 +28,6 @@ class BaseMenu(BaseModel): class MenuCreate(BaseModel): menu_type: MenuType = Field(default=MenuType.CATALOG.value) name: str = Field(example="用户管理") - remark: Optional[dict] = Field(example={}) icon: Optional[str] = "ph:user-list-bold" path: str = Field(example="/system/user") order: Optional[int] = Field(example=1) @@ -45,7 +42,6 @@ class MenuUpdate(BaseModel): id: int menu_type: Optional[MenuType] = Field(example=MenuType.CATALOG.value) name: Optional[str] = Field(example="用户管理") - remark: Optional[dict] = Field(example={}) icon: Optional[str] = "ph:user-list-bold" path: Optional[str] = Field(example="/system/user") order: Optional[int] = Field(example=1) @@ -56,15 +52,4 @@ class MenuUpdate(BaseModel): redirect: Optional[str] = "" def update_dict(self): - return self.dict(exclude_unset=True, exclude={"id"}) - - -"""Response""" - - -class MenuOutList(SuccessExtra): - data: Optional[List[BaseMenu]] - - -class MenuOut(BaseResponse): - data: Optional[BaseMenu] + return self.model_dump(exclude_unset=True, exclude={"id"}) diff --git a/app/schemas/roles.py b/app/schemas/roles.py index 9c6ed2a..2ff0d19 100644 --- a/app/schemas/roles.py +++ b/app/schemas/roles.py @@ -1,10 +1,8 @@ from datetime import datetime -from typing import List, Optional +from typing import Optional from pydantic import BaseModel, Field -from .base import BaseResponse, SuccessExtra - class BaseRole(BaseModel): id: int @@ -28,21 +26,10 @@ class RoleUpdate(BaseModel): desc: Optional[str] = Field(example="管理员角色") def update_dict(self): - return self.dict(exclude_unset=True, exclude={"id"}) + return self.model_dump(exclude_unset=True, exclude={"id"}) class RoleUpdateMenusApis(BaseModel): id: int - menu_ids: List[int] = [] - api_infos: List[dict] = [] - - -"""Response""" - - -class RoleOutList(SuccessExtra): - data: Optional[List[BaseRole]] - - -class RoleOut(BaseResponse): - data: Optional[BaseRole] + menu_ids: list[int] = [] + api_infos: list[dict] = [] diff --git a/app/schemas/users.py b/app/schemas/users.py index 3b91905..c060ab4 100644 --- a/app/schemas/users.py +++ b/app/schemas/users.py @@ -3,8 +3,6 @@ from typing import List, Optional from pydantic import BaseModel, EmailStr, Field -from app.schemas.base import BaseResponse, SuccessExtra - class BaseUser(BaseModel): id: int @@ -27,7 +25,7 @@ class UserCreate(BaseModel): roles: Optional[List[int]] = [] def create_dict(self): - return self.dict(exclude_unset=True, exclude={"roles"}) + return self.model_dump(exclude_unset=True, exclude={"roles"}) class UserUpdate(BaseModel): @@ -40,21 +38,10 @@ class UserUpdate(BaseModel): roles: Optional[List[int]] = [] def update_dict(self): - return self.dict(exclude_unset=True, exclude={"roles", "id"}) + return self.model_dump(exclude_unset=True, exclude={"roles", "id"}) class UpdatePassword(BaseModel): id: int = Field(description="用户ID") old_password: str = Field(description="旧密码") new_password: str = Field(description="新密码") - - -"""Response""" - - -class UserOutList(SuccessExtra): - data: Optional[List[BaseUser]] - - -class UserOut(BaseResponse): - data: Optional[BaseUser] diff --git a/app/settings/config.py b/app/settings/config.py index e91161e..4c4ed53 100644 --- a/app/settings/config.py +++ b/app/settings/config.py @@ -1,7 +1,7 @@ import os import typing -from pydantic import BaseSettings +from pydantic_settings import BaseSettings class Settings(BaseSettings): @@ -15,7 +15,7 @@ class Settings(BaseSettings): CORS_ALLOW_METHODS: typing.List = ["*"] CORS_ALLOW_HEADERS: typing.List = ["*"] - DEBUG = True + DEBUG: bool = True DB_URL: str = "sqlite://db.sqlite3" DB_CONNECTIONS: dict = { "default": { @@ -37,7 +37,7 @@ class Settings(BaseSettings): SECRET_KEY: str = "3488a63e1765035d386f05409663f55c83bfae3b3c61a932744b20ad14244dcf" # openssl rand -hex 32 JWT_ALGORITHM: str = "HS256" JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 7 # 7 day - TORTOISE_ORM = { + TORTOISE_ORM: dict = { "connections": { "sqlite": { "engine": "tortoise.backends.sqlite", diff --git a/poetry.lock b/poetry.lock index ed8333a..1c387bf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -20,14 +20,30 @@ url = "https://pypi.tuna.tsinghua.edu.cn/simple" reference = "tsinghua" [[package]] -name = "anyio" -version = "3.7.1" -description = "High level compatibility layer for multiple asynchronous event loop implementations" +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.7" files = [ - {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, - {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + +[package.source] +type = "legacy" +url = "https://pypi.tuna.tsinghua.edu.cn/simple" +reference = "tsinghua" + +[[package]] +name = "anyio" +version = "4.0.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"}, + {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"}, ] [package.dependencies] @@ -35,9 +51,9 @@ idna = ">=2.8" sniffio = ">=1.1" [package.extras] -doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] -test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (<0.22)"] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.22)"] [package.source] type = "legacy" @@ -85,33 +101,33 @@ reference = "tsinghua" [[package]] name = "black" -version = "23.7.0" +version = "23.9.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, - {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, - {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, - {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, - {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, - {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, - {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, - {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, - {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, - {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, - {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, - {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, - {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, + {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, + {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, + {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, + {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, + {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, + {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, + {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, + {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, + {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, + {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, ] [package.dependencies] @@ -134,13 +150,13 @@ reference = "tsinghua" [[package]] name = "click" -version = "8.1.6" +version = "8.1.7" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"}, - {file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] @@ -307,13 +323,13 @@ reference = "tsinghua" [[package]] name = "loguru" -version = "0.7.0" +version = "0.7.2" description = "Python logging made (stupidly) simple" optional = false python-versions = ">=3.5" files = [ - {file = "loguru-0.7.0-py3-none-any.whl", hash = "sha256:b93aa30099fa6860d4727f1b81f8718e965bb96253fa190fab2077aaad6d15d3"}, - {file = "loguru-0.7.0.tar.gz", hash = "sha256:1612053ced6ae84d7959dd7d5e431a0532642237ec21f7fd83ac73fe539e03e1"}, + {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, + {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, ] [package.dependencies] @@ -321,7 +337,7 @@ colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] -dev = ["Sphinx (==5.3.0)", "colorama (==0.4.5)", "colorama (==0.4.6)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v0.990)", "pre-commit (==3.2.1)", "pytest (==6.1.2)", "pytest (==7.2.1)", "pytest-cov (==2.12.1)", "pytest-cov (==4.0.0)", "pytest-mypy-plugins (==1.10.1)", "pytest-mypy-plugins (==1.9.3)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.2.0)", "tox (==3.27.1)", "tox (==4.4.6)"] +dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"] [package.source] type = "legacy" @@ -420,55 +436,165 @@ reference = "tsinghua" [[package]] name = "pydantic" -version = "1.10.12" -description = "Data validation and settings management using python type hints" +version = "2.3.0" +description = "Data validation using Python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"}, - {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"}, - {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"}, - {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"}, - {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"}, - {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"}, - {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"}, - {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"}, - {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"}, - {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"}, - {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"}, - {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"}, - {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"}, - {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"}, - {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"}, - {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"}, - {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"}, - {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"}, - {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"}, - {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"}, - {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"}, - {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"}, - {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"}, - {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"}, - {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"}, - {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"}, - {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"}, - {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"}, - {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"}, - {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"}, - {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"}, - {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"}, - {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"}, - {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"}, - {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"}, - {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"}, + {file = "pydantic-2.3.0-py3-none-any.whl", hash = "sha256:45b5e446c6dfaad9444819a293b921a40e1db1aa61ea08aede0522529ce90e81"}, + {file = "pydantic-2.3.0.tar.gz", hash = "sha256:1607cc106602284cd4a00882986570472f193fde9cb1259bceeaedb26aa79a6d"}, ] [package.dependencies] -typing-extensions = ">=4.2.0" +annotated-types = ">=0.4.0" +pydantic-core = "2.6.3" +typing-extensions = ">=4.6.1" [package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] +email = ["email-validator (>=2.0.0)"] + +[package.source] +type = "legacy" +url = "https://pypi.tuna.tsinghua.edu.cn/simple" +reference = "tsinghua" + +[[package]] +name = "pydantic-core" +version = "2.6.3" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1a0ddaa723c48af27d19f27f1c73bdc615c73686d763388c8683fe34ae777bad"}, + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5cfde4fab34dd1e3a3f7f3db38182ab6c95e4ea91cf322242ee0be5c2f7e3d2f"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5493a7027bfc6b108e17c3383959485087d5942e87eb62bbac69829eae9bc1f7"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84e87c16f582f5c753b7f39a71bd6647255512191be2d2dbf49458c4ef024588"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:522a9c4a4d1924facce7270c84b5134c5cabcb01513213662a2e89cf28c1d309"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaafc776e5edc72b3cad1ccedb5fd869cc5c9a591f1213aa9eba31a781be9ac1"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a750a83b2728299ca12e003d73d1264ad0440f60f4fc9cee54acc489249b728"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e8b374ef41ad5c461efb7a140ce4730661aadf85958b5c6a3e9cf4e040ff4bb"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b594b64e8568cf09ee5c9501ede37066b9fc41d83d58f55b9952e32141256acd"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a20c533cb80466c1d42a43a4521669ccad7cf2967830ac62c2c2f9cece63e7e"}, + {file = "pydantic_core-2.6.3-cp310-none-win32.whl", hash = "sha256:04fe5c0a43dec39aedba0ec9579001061d4653a9b53a1366b113aca4a3c05ca7"}, + {file = "pydantic_core-2.6.3-cp310-none-win_amd64.whl", hash = "sha256:6bf7d610ac8f0065a286002a23bcce241ea8248c71988bda538edcc90e0c39ad"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50"}, + {file = "pydantic_core-2.6.3-cp311-none-win32.whl", hash = "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8"}, + {file = "pydantic_core-2.6.3-cp311-none-win_amd64.whl", hash = "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950"}, + {file = "pydantic_core-2.6.3-cp311-none-win_arm64.whl", hash = "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa"}, + {file = "pydantic_core-2.6.3-cp312-none-win32.whl", hash = "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1"}, + {file = "pydantic_core-2.6.3-cp312-none-win_amd64.whl", hash = "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881"}, + {file = "pydantic_core-2.6.3-cp312-none-win_arm64.whl", hash = "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:a53e3195f134bde03620d87a7e2b2f2046e0e5a8195e66d0f244d6d5b2f6d31b"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:f2969e8f72c6236c51f91fbb79c33821d12a811e2a94b7aa59c65f8dbdfad34a"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:672174480a85386dd2e681cadd7d951471ad0bb028ed744c895f11f9d51b9ebe"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:002d0ea50e17ed982c2d65b480bd975fc41086a5a2f9c924ef8fc54419d1dea3"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ccc13afee44b9006a73d2046068d4df96dc5b333bf3509d9a06d1b42db6d8bf"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:439a0de139556745ae53f9cc9668c6c2053444af940d3ef3ecad95b079bc9987"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d63b7545d489422d417a0cae6f9898618669608750fc5e62156957e609e728a5"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b44c42edc07a50a081672e25dfe6022554b47f91e793066a7b601ca290f71e42"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1c721bfc575d57305dd922e6a40a8fe3f762905851d694245807a351ad255c58"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e4a2cf8c4543f37f5dc881de6c190de08096c53986381daebb56a355be5dfe6"}, + {file = "pydantic_core-2.6.3-cp37-none-win32.whl", hash = "sha256:d9b4916b21931b08096efed090327f8fe78e09ae8f5ad44e07f5c72a7eedb51b"}, + {file = "pydantic_core-2.6.3-cp37-none-win_amd64.whl", hash = "sha256:a8acc9dedd304da161eb071cc7ff1326aa5b66aadec9622b2574ad3ffe225525"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5e9c068f36b9f396399d43bfb6defd4cc99c36215f6ff33ac8b9c14ba15bdf6b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e61eae9b31799c32c5f9b7be906be3380e699e74b2db26c227c50a5fc7988698"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85463560c67fc65cd86153a4975d0b720b6d7725cf7ee0b2d291288433fc21b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9616567800bdc83ce136e5847d41008a1d602213d024207b0ff6cab6753fe645"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e9b65a55bbabda7fccd3500192a79f6e474d8d36e78d1685496aad5f9dbd92c"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f468d520f47807d1eb5d27648393519655eadc578d5dd862d06873cce04c4d1b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9680dd23055dd874173a3a63a44e7f5a13885a4cfd7e84814be71be24fba83db"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a718d56c4d55efcfc63f680f207c9f19c8376e5a8a67773535e6f7e80e93170"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8ecbac050856eb6c3046dea655b39216597e373aa8e50e134c0e202f9c47efec"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:788be9844a6e5c4612b74512a76b2153f1877cd845410d756841f6c3420230eb"}, + {file = "pydantic_core-2.6.3-cp38-none-win32.whl", hash = "sha256:07a1aec07333bf5adebd8264047d3dc518563d92aca6f2f5b36f505132399efc"}, + {file = "pydantic_core-2.6.3-cp38-none-win_amd64.whl", hash = "sha256:621afe25cc2b3c4ba05fff53525156d5100eb35c6e5a7cf31d66cc9e1963e378"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:813aab5bfb19c98ae370952b6f7190f1e28e565909bfc219a0909db168783465"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:50555ba3cb58f9861b7a48c493636b996a617db1a72c18da4d7f16d7b1b9952b"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e20f8baedd7d987bd3f8005c146e6bcbda7cdeefc36fad50c66adb2dd2da48"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b0a5d7edb76c1c57b95df719af703e796fc8e796447a1da939f97bfa8a918d60"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f06e21ad0b504658a3a9edd3d8530e8cea5723f6ea5d280e8db8efc625b47e49"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea053cefa008fda40f92aab937fb9f183cf8752e41dbc7bc68917884454c6362"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:171a4718860790f66d6c2eda1d95dd1edf64f864d2e9f9115840840cf5b5713f"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ed7ceca6aba5331ece96c0e328cd52f0dcf942b8895a1ed2642de50800b79d3"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:acafc4368b289a9f291e204d2c4c75908557d4f36bd3ae937914d4529bf62a76"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1aa712ba150d5105814e53cb141412217146fedc22621e9acff9236d77d2a5ef"}, + {file = "pydantic_core-2.6.3-cp39-none-win32.whl", hash = "sha256:44b4f937b992394a2e81a5c5ce716f3dcc1237281e81b80c748b2da6dd5cf29a"}, + {file = "pydantic_core-2.6.3-cp39-none-win_amd64.whl", hash = "sha256:9b33bf9658cb29ac1a517c11e865112316d09687d767d7a0e4a63d5c640d1b17"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149"}, + {file = "pydantic_core-2.6.3.tar.gz", hash = "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[package.source] +type = "legacy" +url = "https://pypi.tuna.tsinghua.edu.cn/simple" +reference = "tsinghua" + +[[package]] +name = "pydantic-settings" +version = "2.0.3" +description = "Settings management using Pydantic" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_settings-2.0.3-py3-none-any.whl", hash = "sha256:ddd907b066622bd67603b75e2ff791875540dc485b7307c4fffc015719da8625"}, + {file = "pydantic_settings-2.0.3.tar.gz", hash = "sha256:962dc3672495aad6ae96a4390fac7e593591e144625e5112d359f8f67fb75945"}, +] + +[package.dependencies] +pydantic = ">=2.0.1" +python-dotenv = ">=0.21.0" [package.source] type = "legacy" @@ -513,15 +639,34 @@ type = "legacy" url = "https://pypi.tuna.tsinghua.edu.cn/simple" reference = "tsinghua" +[[package]] +name = "python-dotenv" +version = "1.0.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, + {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[package.source] +type = "legacy" +url = "https://pypi.tuna.tsinghua.edu.cn/simple" +reference = "tsinghua" + [[package]] name = "pytz" -version = "2023.3" +version = "2023.3.post1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, - {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, ] [package.source] @@ -689,4 +834,4 @@ reference = "tsinghua" [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "59b09802b9b8df810377480c8da534798638993c3441bb55814f0e41e33bd054" +content-hash = "e66116a325977520e14789d0c4e84ed9ac2267c8a5f8dc3c5f245794dd3a6083" diff --git a/pyproject.toml b/pyproject.toml index a5be32e..1c84a28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ python = "^3.11" fastapi = "^0.100.0" uvicorn = "^0.23.1" tortoise-orm = "^0.19.3" -pydantic = "^1.10.5" +pydantic = "^2.3.0" email-validator = "^2.0.0.post2" passlib = "^1.7.4" pyjwt = "^2.7.0" @@ -19,6 +19,7 @@ black = "^23.7.0" isort = "^5.12.0" ruff = "^0.0.281" loguru = "^0.7.0" +pydantic-settings = "^2.0.3" [tool.black] line-length = 120 diff --git a/web/src/utils/http/interceptors.js b/web/src/utils/http/interceptors.js index 93228fe..e782eba 100644 --- a/web/src/utils/http/interceptors.js +++ b/web/src/utils/http/interceptors.js @@ -1,5 +1,6 @@ import { getToken } from '@/utils' import { resolveResError } from './helpers' +import { useUserStore } from '@/store' export function reqResolve(config) { // 处理不需要token的请求 @@ -31,8 +32,6 @@ export function resResolve(response) { return Promise.resolve(data) } -let isDialogShow = false //解决多个请求弹出多个dialog - export async function resReject(error) { if (!error || !error.response) { const code = error?.code @@ -42,30 +41,12 @@ export async function resReject(error) { return Promise.reject({ code, message, error }) } const { data, status } = error.response + if (data?.code === 401) { - if (isDialogShow) return try { - isDialogShow = true - await new Promise((resolve, reject) => { - $dialog.confirm({ - title: '系统提示', - type: 'warning', - content: '账号登录已过期,您可以继续留在该页面,或者重新登录', - positiveText: '重新登录', - negativeText: '取消', - confirm() { - isDialogShow = false - location.reload() - resolve() // 解决 Promise 以继续执行 - }, - cancel() { - isDialogShow = false - reject(new Error('对话框已取消')) // 拒绝 Promise 以停止执行 - }, - }) - }) + const userStore = useUserStore() + userStore.logout() } catch (error) { - isDialogShow = false console.log('resReject error', error) return }