diff --git a/.gitignore b/.gitignore index 1e99ef4..1c2320a 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,9 @@ config # chongming-utils utils + +# vscode +.vscode + +# .agents +.agents \ No newline at end of file diff --git a/README.md b/README.md index 6084ee2..d1eedae 100644 --- a/README.md +++ b/README.md @@ -54,4 +54,4 @@ uv run serve ## 更多文档 - Worker 开发指南(待补充) -- [配置说明](http://124.71.68.6:3000/chongming/chongming-config.git/README.md) +- [配置说明](http://124.71.68.6:3000/chongming/chongming-config/src/branch/master/README.md) diff --git a/config.toml b/config.toml index d46a363..a1ea445 100644 --- a/config.toml +++ b/config.toml @@ -26,10 +26,7 @@ job_store_path = "scheduler_jobs.db" cache_store_path = "./cache_data" [security] -access_token_expire_minutes = 1440 algorithm = "HS256" -max_sessions_per_user = 5 -refresh_token_expire_days = 7 secret_key = "your-secret-key-change-in-production" [development] @@ -79,6 +76,11 @@ base = [ "nanio", "boto3", "modelvault", + "volcenginesdkarkruntime", + "chongming_jwt", + "chongming-database", + "aiosqlite", + "sqlmodel", ] linux = [ "gunicorn.glogging", diff --git a/pyproject.toml b/pyproject.toml index 96b80d4..8225aba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,12 +8,11 @@ dependencies = [ "boto3", "chongming-jwt", "chongming-request", - "chongming-worker", + "chongming-database", "diskcache", "eclipse-zenoh", "fastapi[uvicorn]", "gunicorn", - "modelvault", "module-bank", "nanio", "openai", @@ -24,6 +23,9 @@ dependencies = [ "typing-extensions", "uvicorn", "volcengine-python-sdk[ark]>=5.0.41", + "chongming-config", + "chongming-password", + "chongming-worker", ] description = "基于 modules-bank 的 fastapi 打包脚手架" name = "chongming-zenoh" @@ -45,17 +47,13 @@ packages = ["src/chongming"] [[tool.uv.index]] url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" -[tool.uv.workspace] -members = [ - "utils/worker", - "utils/request", - "utils/jwt", -] - [tool.uv.sources] -chongming-request = { workspace = true } -chongming-worker = { workspace = true } -chongming-jwt = { workspace = true } +chongming-request = { git = "http://124.71.68.6:3000/chongming/chongming-utils-request.git" } +chongming-jwt = { git = "http://124.71.68.6:3000/chongming/chongming-utils-jwt.git" } +chongming-database = { git = "http://124.71.68.6:3000/chongming/chongming-utils-database.git" } +chongming-config = { git = "http://124.71.68.6:3000/chongming/chongming-utils-config.git" } +chongming-password = { git = "http://124.71.68.6:3000/chongming/chongming-utils-password.git" } +chongming-worker = { git = "http://124.71.68.6:3000/chongming/chongming-utils-worker.git" } [project.scripts] build = "chongming.scripts.build:build" diff --git a/src/chongming/__init__.py b/src/chongming/__init__.py index 37f052d..191de7f 100644 --- a/src/chongming/__init__.py +++ b/src/chongming/__init__.py @@ -1,5 +1,5 @@ import uvicorn -from .app.core.config import load_config +from chongming_config import load_config from .app.core.logger import get_logger @@ -22,7 +22,6 @@ def serve(): logger.info(f"启动日志: {log_config}") uvicorn.run("chongming.app:app", **server_config) - def gunicorn_serve(): """ 使用 gunicorn 启动服务 diff --git a/src/chongming/app/__init__.py b/src/chongming/app/__init__.py index 0ce1014..6b8759f 100644 --- a/src/chongming/app/__init__.py +++ b/src/chongming/app/__init__.py @@ -15,7 +15,7 @@ from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from fastapi.middleware.cors import CORSMiddleware -from .core.config import get_config +from chongming_config import get_config from .core.logger import get_logger from .core.static_files import SVFSStaticFiles from .core import lifespan_setup diff --git a/src/chongming/app/core/auth.py b/src/chongming/app/core/auth.py new file mode 100644 index 0000000..99fd896 --- /dev/null +++ b/src/chongming/app/core/auth.py @@ -0,0 +1,42 @@ +from fastapi import Depends, HTTPException, status, Request +from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer +from chongming_jwt import JWT +from chongming_config import get_config + + +security_scheme = HTTPBearer(auto_error=False) + + +def jwt_auth_dependency( + credentials: HTTPAuthorizationCredentials = Depends(security_scheme) +) -> dict: + """JWT 校验依赖,返回解码后的 payload,校验失败抛出 401""" + config =get_config() + secret = config["security"]["secret_key"] + algorithm = config["security"]["algorithm"] + jwt = JWT(secret, algorithm) + + if not credentials: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Missing authorization header", + headers={"WWW-Authenticate": "Bearer"}, + ) + token = credentials.credentials + try: + payload_str = jwt.decode(token) + import json + payload = json.loads(payload_str) + return payload + except Exception as e: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=f"Invalid token: {str(e)}", + headers={"WWW-Authenticate": "Bearer"}, + ) + +async def store_user_to_request( + request: Request, + user: dict = Depends(jwt_auth_dependency) +) -> None: + request.state.user = user diff --git a/src/chongming/app/core/config.py b/src/chongming/app/core/config_.py similarity index 100% rename from src/chongming/app/core/config.py rename to src/chongming/app/core/config_.py diff --git a/src/chongming/app/core/lifespan_setup.py b/src/chongming/app/core/lifespan_setup.py index 0e37cd8..8f30192 100644 --- a/src/chongming/app/core/lifespan_setup.py +++ b/src/chongming/app/core/lifespan_setup.py @@ -1,8 +1,10 @@ import os - import inspect -import subprocess +import time +import multiprocessing import asyncio +import socket +import sys import boto3 from botocore.exceptions import ClientError @@ -11,7 +13,7 @@ from diskcache import Cache from fastapi import FastAPI import zenoh -from ..core.config import get_config, get_workers_config +from chongming_config import get_config, get_workers_config from ..core.logger import get_logger from ..core.route_generator import register_dynamic_routes from ..core.worker_manager import WorkerManager @@ -24,26 +26,61 @@ try: except KeyError: # pragma: no cover raise ValueError("配置不存在") -def setup_nanio(app: FastAPI): - """启动 nanio 子进程作为 S3 兼容存储服务。""" - nanio_config = config.get("nanio", {}) - env = os.environ.copy() - env["NANIO_ACCESS_KEY"] = nanio_config.get("nanio_access_key", "minioadmin") - env["NANIO_SECRET_KEY"] = nanio_config.get("nanio_secret_key", "minioadmin") +def is_port_in_use(port: int, host: str = "127.0.0.1") -> bool: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.settimeout(0.5) + return s.connect_ex((host, port)) == 0 - proc = subprocess.Popen( - [ - "nanio", - "serve", - "--data-dir", - nanio_config.get("storage_path", "./data/storage") - ], - env=env, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL - ) +def _run_nanio(): + """子进程入口:直接调用 nanio.cli.main()""" + # 设置环境变量(从主进程继承,但重新设置确保有效) + os.environ.setdefault("NANIO_ACCESS_KEY", "minioadmin") + os.environ.setdefault("NANIO_SECRET_KEY", "minioadmin") + os.environ.setdefault("NANIO_DATA_DIR", "./data/storage") + os.environ.setdefault("NANIO_HOST", "127.0.0.1") + os.environ.setdefault("NANIO_PORT", "9000") + # 伪造 sys.argv 使 nanio 认为是以 `nanio serve` 启动 + sys.argv = ["nanio", "serve"] + try: + from nanio.cli import main + main() + except Exception as e: + with open("nanio_error.log", "w") as f: + f.write(f"Nanio server failed: {e}\n") + import traceback + traceback.print_exc(file=f) + raise + +def setup_nanio(app: FastAPI): + if is_port_in_use(9000, "127.0.0.1"): + logger.info("Nanio 已在 127.0.0.1:9000 运行,跳过") + return + + # 启动子进程 + proc = multiprocessing.Process(target=_run_nanio, daemon=False) + proc.start() app.state.nanio_process = proc - logger.info("Nanio 进程已启动") + logger.info("Nanio 子进程已启动 (PID: %s)", proc.pid) + + # 等待端口可用 + for _ in range(50): # 最多等待 5 秒 + if is_port_in_use(9000, "127.0.0.1"): + logger.info("Nanio 已监听 9000 端口") + return + time.sleep(0.1) + + # 超时或进程退出 + if not proc.is_alive(): + try: + with open("nanio_error.log", "r") as f: + err = f.read() + except FileNotFoundError: + err = "无错误日志" + logger.error("Nanio 进程已退出,错误: %s", err) + raise RuntimeError("Nanio 进程启动失败") + else: + logger.error("Nanio 进程启动超时(仍在运行但未监听端口)") + raise RuntimeError("Nanio 端口未就绪") def setup_s3(app: FastAPI): """初始化 S3 客户端,并确保 bucket 存在。""" @@ -56,12 +93,19 @@ def setup_s3(app: FastAPI): config=Config(signature_version=nanio_config.get("signature_version", "s3v4")), region_name=nanio_config.get("region_name", "us-east-1") ) + bucket = nanio_config.get("bucket", "chongming") try: - s3_client.head_bucket(Bucket=nanio_config.get("bucket", "chongming")) + s3_client.head_bucket(Bucket=bucket) except ClientError as e: if e.response["Error"]["Code"] == "404": - s3_client.create_bucket(Bucket="chongming") - logger.info("Bucket 'chongming' 已创建") + try: + s3_client.create_bucket(Bucket=bucket) + logger.info(f"Bucket '{bucket}' 已创建") + except ClientError as create_err: + if create_err.response["Error"]["Code"] in ("BucketAlreadyOwnedByYou", "BucketAlreadyExists"): + logger.info(f"Bucket '{bucket}' 已存在(由其他进程创建),忽略") + else: + raise else: raise @@ -141,9 +185,11 @@ async def register_routes(app: FastAPI, manager: WorkerManager): async def shutdown_nanio(app: FastAPI): """终止 nanio 进程。""" proc = getattr(app.state, "nanio_process", None) - if proc: + if proc and proc.is_alive(): proc.terminate() - proc.wait() + proc.join(timeout=5) + if proc.is_alive(): + proc.kill() logger.info("Nanio 进程已终止") async def cleanup_workers(app: FastAPI): @@ -170,4 +216,5 @@ async def cleanup_workers(app: FastAPI): else: cleanup(worker_id) except Exception as e: - logger.error(f"cleanup 调用失败 {module_name}: {e}") \ No newline at end of file + logger.error(f"cleanup 调用失败 {module_name}: {e}") + \ No newline at end of file diff --git a/src/chongming/app/core/logger.py b/src/chongming/app/core/logger.py index 2472958..617b049 100644 --- a/src/chongming/app/core/logger.py +++ b/src/chongming/app/core/logger.py @@ -4,7 +4,7 @@ import datetime from pathlib import Path from logging.handlers import RotatingFileHandler -from ..core.config import get_config +from chongming_config import get_config config = get_config() diff --git a/src/chongming/app/core/route_generator.py b/src/chongming/app/core/route_generator.py index bfbbe26..0b9c510 100644 --- a/src/chongming/app/core/route_generator.py +++ b/src/chongming/app/core/route_generator.py @@ -5,16 +5,15 @@ 为每个端点生成带有正确 Pydantic 类型注解的处理函数,确保 OpenAPI 文档 正确反映参数类型、响应结构,并注册到 components/schemas。 """ -import asyncio -import json -from typing import Any, Dict, List, Optional, get_type_hints +from typing import Any, Dict, List, Optional from inspect import Parameter, Signature -from fastapi import FastAPI, HTTPException, APIRouter, Query, Path as FastAPIPath, Depends +from fastapi import FastAPI, HTTPException, APIRouter, Query, Path as FastAPIPath, Request, Depends from pydantic import create_model, Field, BaseModel from .worker_manager import WorkerManager from .logger import get_logger +from .auth import store_user_to_request logger = get_logger("route_generator") @@ -89,6 +88,7 @@ class RouteConfig: self.docstring: str = data.get("docstring", "") self.timeout: float = data.get("timeout", 3.0) self.cacheable: bool = data.get("cacheable", False) + self.auth_required: bool = data.get("auth_required", True) def parse_params(self) -> Dict[str, str]: """解析 params 列表为 {name: type} 字典""" @@ -261,11 +261,15 @@ def _make_body_endpoint(worker_manager: WorkerManager, rc: RouteConfig, worker_t cacheable = rc.cacheable async def endpoint( + request: Request, body: RequestModel, # type: ignore ) -> Any: try: payload = body.model_dump() payload.setdefault("_method", http_method) + user_info = getattr(request.state, "user", None) + if user_info: + payload["user_info"] = user_info result = await worker_manager.call( worker_type=worker_type, subject=subject, @@ -304,12 +308,17 @@ def _make_query_endpoint(worker_manager: WorkerManager, rc: RouteConfig, worker_ # 无参数情况 if not param_spec_combined: - async def _simple_endpoint() -> Any: + async def _simple_endpoint(request: Request) -> Any: + payload = {} + payload.setdefault("_method", http_method) + user_info = getattr(request.state, "user", None) + if user_info: + payload["user_info"] = user_info try: result = await worker_manager.call( worker_type=worker_type, subject=subject, - payload={"_method": http_method}, + payload=payload, timeout=timeout, cacheable=cacheable, ) @@ -324,9 +333,12 @@ def _make_query_endpoint(worker_manager: WorkerManager, rc: RouteConfig, worker_ # 构造参数名列表(用于从 kwargs 中提取) param_names = list(param_spec_combined.keys()) - async def endpoint(**kwargs: Any) -> Any: + async def endpoint(request: Request, **kwargs: Any) -> Any: payload = {k: kwargs[k] for k in param_names} payload.setdefault("_method", http_method) + user_info = getattr(request.state, "user", None) + if user_info: + payload["user_info"] = user_info try: result = await worker_manager.call( worker_type=worker_type, @@ -343,7 +355,9 @@ def _make_query_endpoint(worker_manager: WorkerManager, rc: RouteConfig, worker_ raise HTTPException(status_code=500, detail="内部服务器错误") # 构建带类型注解的 Parameter 列表 - params: List[Parameter] = [] + params: List[Parameter] = [ + Parameter("request", Parameter.POSITIONAL_OR_KEYWORD, annotation=Request) + ] annotations: Dict[str, Any] = {} for name, type_str in param_spec_combined.items(): py_type = _parse_python_type(type_str) @@ -403,6 +417,10 @@ def _register_single_route( extra_schemas[request_model_name] = RequestModel endpoint = _make_query_endpoint(worker_manager, rc, worker_type, path_params, query_params) + dependencies = [] + if rc.auth_required: + dependencies.append(Depends(store_user_to_request)) + # 注册路由 - 使用 worker_type 作为 OpenAPI 分组标签 # 每个 worker 类型自动成为一个独立的分组,显示在 Swagger UI 中 router.add_api_route( @@ -414,5 +432,6 @@ def _register_single_route( response_model=ResponseModel, tags=[worker_type], include_in_schema=True, + dependencies=dependencies, ) logger.info(f"已注册动态路由: {rc.method} {rc.path} -> worker {worker_type}.{rc.subject} | tags=[{worker_type}]") diff --git a/src/chongming/scripts/build.py b/src/chongming/scripts/build.py index fe93548..17e7fd3 100644 --- a/src/chongming/scripts/build.py +++ b/src/chongming/scripts/build.py @@ -25,7 +25,7 @@ from module_bank import PythonToSQLite from module_bank.encryption import Encryption from sqlite_vfs.core import SQLiteVFS from sqlite_vfs.folder_packer import FolderPacker -from ..app.core.config import get_config, Config +from chongming_config import get_config, Config # ── 常量 ──────────────────────────────────────────────────────────────────── @@ -262,6 +262,9 @@ def _stage_pyinstaller(config: Config) -> tuple[str, str]: cmd.extend(["--icon", str(icon)]) for imp in build_imports: cmd.extend(["--hidden-import", imp]) + + cmd.append("--collect-all") + cmd.append("nanio") cmd.append("main.py") diff --git a/test.mp4 b/test.mp4 deleted file mode 100644 index 0fe4de7..0000000 Binary files a/test.mp4 and /dev/null differ diff --git a/test_jwt.py b/test_jwt.py deleted file mode 100644 index af0e31b..0000000 --- a/test_jwt.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -import json -from chongming_jwt import JWT - -# 使用与 config.toml 相同的密钥(可从配置读取) -SECRET = "your-secret-key-change-in-production" - -jwt = JWT(SECRET, "HS256") - -# 1. 生成 token -payload = json.dumps({"sub": "test_user", "role": "admin"}) -token = jwt.encode(payload, expires_in_seconds=3600) -print(f"✅ Token: {token}") - -# 2. 解码验证 -decoded = jwt.decode(token) -print(f"✅ Decoded: {decoded}") - -# 3. 仅验证(不返回内容) -is_valid = jwt.validate(token) -print(f"✅ Valid: {is_valid}") - -# 4. 测试无效 token -try: - jwt.decode(token + "invalid") -except Exception as e: - print(f"❌ Invalid token caught: {e}") \ No newline at end of file diff --git a/uv.lock b/uv.lock index 24fb80d..c916343 100644 --- a/uv.lock +++ b/uv.lock @@ -2,14 +2,6 @@ version = 1 revision = 3 requires-python = ">=3.12" -[manifest] -members = [ - "chongming-jwt", - "chongming-request", - "chongming-worker", - "chongming-zenoh", -] - [[package]] name = "aiofiles" version = "25.1.0" @@ -19,6 +11,15 @@ wheels = [ { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/8a/340a1555ae33d7354dbca4faa54948d76d89a27ceef032c8c3bc661d003e/aiofiles-25.1.0-py3-none-any.whl", hash = "sha256:abe311e527c862958650f9438e859c1fa7568a141b22abcd015e120e86a85695", size = 14668, upload-time = "2025-10-09T20:51:03.174Z" }, ] +[[package]] +name = "aiosqlite" +version = "0.22.1" +source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4e/8a/64761f4005f17809769d23e518d915db74e6310474e733e3593cfc854ef1/aiosqlite-0.22.1.tar.gz", hash = "sha256:043e0bd78d32888c0a9ca90fc788b38796843360c855a7262a532813133a0650", size = 14821, upload-time = "2025-12-23T19:25:43.997Z" } +wheels = [ + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/b7/e3bf5133d697a08128598c8d0abc5e16377b51465a33756de24fa7dee953/aiosqlite-0.22.1-py3-none-any.whl", hash = "sha256:21c002eb13823fad740196c5a2e9d8e62f6243bd9e7e4a1f87fb5e44ecb4fceb", size = 17405, upload-time = "2025-12-23T19:25:42.139Z" }, +] + [[package]] name = "altgraph" version = "0.17.5" @@ -193,36 +194,51 @@ wheels = [ { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a0/17/1073b53b68c9b5ca6914adf5f8bf55aacc2d3be102418c90700160ea8605/cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210", size = 186405, upload-time = "2026-07-06T21:34:24.857Z" }, ] +[[package]] +name = "chongming-config" +version = "0.1.0" +source = { git = "http://124.71.68.6:3000/chongming/chongming-utils-config.git#33470637c7346e8ef049bef2b0b202d7ed272c3d" } +dependencies = [ + { name = "tomli" }, + { name = "typing-extensions" }, +] + +[[package]] +name = "chongming-database" +version = "0.1.0" +source = { git = "http://124.71.68.6:3000/chongming/chongming-utils-database.git#b318f0f3cbdd85c98b86eec38a1fc51e8603d8da" } +dependencies = [ + { name = "aiosqlite" }, + { name = "sqlmodel" }, +] + [[package]] name = "chongming-jwt" -source = { editable = "utils/jwt" } +version = "0.1.0" +source = { git = "http://124.71.68.6:3000/chongming/chongming-utils-jwt.git#09489e74e6140859e7bbe5bd09343fbe5faf8a9a" } + +[[package]] +name = "chongming-password" +version = "0.1.0" +source = { git = "http://124.71.68.6:3000/chongming/chongming-utils-password.git#589a56765f2e60cbb76e050047e5195023b6857d" } [[package]] name = "chongming-request" version = "0.1.0" -source = { editable = "utils/request" } +source = { git = "http://124.71.68.6:3000/chongming/chongming-utils-request.git#a3b8dd032331660af7256eef360f075b45d6222d" } dependencies = [ { name = "eclipse-zenoh" }, ] -[package.metadata] -requires-dist = [{ name = "eclipse-zenoh", specifier = ">=1.9.0" }] - [[package]] name = "chongming-worker" version = "0.1.0" -source = { editable = "utils/worker" } +source = { git = "http://124.71.68.6:3000/chongming/chongming-utils-worker.git#4b8985d5bd4fc45894bc3e27ecbd541277b83e2f" } dependencies = [ { name = "eclipse-zenoh" }, { name = "tomli" }, ] -[package.metadata] -requires-dist = [ - { name = "eclipse-zenoh", specifier = ">=1.9.0" }, - { name = "tomli", specifier = ">=2.4.1" }, -] - [[package]] name = "chongming-zenoh" version = "0.1.0" @@ -230,14 +246,16 @@ source = { editable = "." } dependencies = [ { name = "apscheduler" }, { name = "boto3" }, + { name = "chongming-config" }, + { name = "chongming-database" }, { name = "chongming-jwt" }, + { name = "chongming-password" }, { name = "chongming-request" }, { name = "chongming-worker" }, { name = "diskcache" }, { name = "eclipse-zenoh" }, { name = "fastapi" }, { name = "gunicorn" }, - { name = "modelvault" }, { name = "module-bank" }, { name = "nanio" }, { name = "openai" }, @@ -262,14 +280,16 @@ dev = [ requires-dist = [ { name = "apscheduler" }, { name = "boto3" }, - { name = "chongming-jwt", editable = "utils/jwt" }, - { name = "chongming-request", editable = "utils/request" }, - { name = "chongming-worker", editable = "utils/worker" }, + { name = "chongming-config", git = "http://124.71.68.6:3000/chongming/chongming-utils-config.git" }, + { name = "chongming-database", git = "http://124.71.68.6:3000/chongming/chongming-utils-database.git" }, + { name = "chongming-jwt", git = "http://124.71.68.6:3000/chongming/chongming-utils-jwt.git" }, + { name = "chongming-password", git = "http://124.71.68.6:3000/chongming/chongming-utils-password.git" }, + { name = "chongming-request", git = "http://124.71.68.6:3000/chongming/chongming-utils-request.git" }, + { name = "chongming-worker", git = "http://124.71.68.6:3000/chongming/chongming-utils-worker.git" }, { name = "diskcache" }, { name = "eclipse-zenoh" }, { name = "fastapi", extras = ["uvicorn"] }, { name = "gunicorn" }, - { name = "modelvault" }, { name = "module-bank" }, { name = "nanio" }, { name = "openai" }, @@ -420,6 +440,61 @@ wheels = [ { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/7c/8e3c6ad324ea5cb36604fc3f968554887891c316d9dfde57761611d907ad/fastapi-0.139.0-py3-none-any.whl", hash = "sha256:cf15e1e9e667ddb0ad63811e60bd11390d1aac838ca4a7a23f421807b2308189", size = 130339, upload-time = "2026-07-01T16:35:32.19Z" }, ] +[[package]] +name = "greenlet" +version = "3.5.3" +source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e2/f1/fbbfef6af0bad0548f09bc28948ea3c275b4edb19e17fc5ca9900a6a634d/greenlet-3.5.3.tar.gz", hash = "sha256:a61efc018fd3eb317eeca31aba90ee9e7f26f22884a79b6c6ec715bf71bb62f1", size = 200270, upload-time = "2026-06-26T19:28:24.832Z" } +wheels = [ + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/6e/4c37d51a2b7f82d2ff11bb6b5f7d766d9a011726624af255e843727627a3/greenlet-3.5.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:719757059f5a53fd0dde23f78cffeafcdd97b21c850ddb7ca684a3c1a1f122e2", size = 288685, upload-time = "2026-06-26T18:22:08.977Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/73/815dd90131c1b71ebdf53dbc7c276cafec2a1173b97559f97aba72724a87/greenlet-3.5.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:efa9f765dd09f9d0cdac651ffdf631ee59ec5dc6ee7a73e0c012ba9c52fbdf5b", size = 604761, upload-time = "2026-06-26T19:07:10.114Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/57/079cfe76bcef36b153b25607ee91c6fcb58f17f8b23c86bbbeabe0c88d72/greenlet-3.5.3-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7faba15ac005376e02a0384504e0243be3370ce010296a44a820feb342b505ab", size = 617044, upload-time = "2026-06-26T19:10:07.25Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/37/87/b4d095775a3fb1bcafbb483fc206b27ebb785724c83051447737085dc54e/greenlet-3.5.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:87142215824be6ac05e2e8e2786eec307ccbc27c36723c3881959df654af6861", size = 614244, upload-time = "2026-06-26T18:32:17.594Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/70/7559b609683650fa2b95b8ab84b4ab0b26556a635d19675e12aa832d826d/greenlet-3.5.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:215275b1b49320987352e6c1b054acca0064f965a2c66992bed9a6f7d913f149", size = 1574210, upload-time = "2026-06-26T19:09:03.077Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ae/73/be55392074c60fc37655ca40fa6022457bfbf6718e9e342a7b0b41f96dd2/greenlet-3.5.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6b1b0eed82364b0e32c4ea0f221452d33e6bb17ae094d9f72aed9851812747ea", size = 1638627, upload-time = "2026-06-26T18:31:44.748Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/40/c57489acf8e37d74e2913d4eff63aa0dba17acccc4bdeef874dde2dbbec9/greenlet-3.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:cde8adafa2365676f74a979744629589999093bc86e2484214f58e61df08902c", size = 239882, upload-time = "2026-06-26T18:23:27.518Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/fd/6fea0e3d6600f785069481ee637e09378dd4118acdfd38ad88ae2db31c98/greenlet-3.5.3-cp312-cp312-win_arm64.whl", hash = "sha256:c4e7b79d83805475f0102008843f6eb45fd3bb0b2e88c774adab5fbaab27117d", size = 238211, upload-time = "2026-06-26T18:22:37.671Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9b/ff/a620267401db30a50cc8450ee90730e2d4a85658c055c0e760d4ed47fb13/greenlet-3.5.3-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:c8d87c2134d871df96ecdea9cec7cbaab286dadab0f56476e57aaf9e8ac11550", size = 287609, upload-time = "2026-06-26T18:21:14.724Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/fa/5401ac78021c826a25b6dde0c705e0a8f29b617509f9185a31dac15fbe1b/greenlet-3.5.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2d185dd1621757e70c3861cceffd5317ab4e7ed7eb09c82994828468527ade5", size = 607435, upload-time = "2026-06-26T19:07:11.412Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/76/1dc144a2e56e65d36405078ed774224375ea520a1870a6e46e08bb4ac7bf/greenlet-3.5.3-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1c514a468149bf8fbbab874188a3535cd8a48a3e353eb53a3d424296f8dbacd3", size = 619787, upload-time = "2026-06-26T19:10:08.396Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/87/c298cee62df1de4ad7fec32abda73526cff347fd143a6ed4ac369246668a/greenlet-3.5.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:915f887cf2682b66419b879423a2e072634aa7b7dce6f3ada4957cfced3f1e9a", size = 616786, upload-time = "2026-06-26T18:32:19.128Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/2e/e6f009885ed0705ccf33fe0583c117cfd03cde77e31a596dd5785a30762b/greenlet-3.5.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:766cfd421c13e450feb340cd472a3ed9957d438727b7b4593ad7c76c5d2b0deb", size = 1574316, upload-time = "2026-06-26T19:09:04.273Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ef/fe/43fd110b01e40da0adb7c90ac7ea744bef2d43dca00de5095fd2351c2a68/greenlet-3.5.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2ecda9ec22edf38fa389369eaed8c3d37c05f3c54e69f69438dbb2cc1de1458b", size = 1638614, upload-time = "2026-06-26T18:31:46.297Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/7c/062447147a61f8b4337b156fe70d32a165fcf2f89d7ca6255e572806705c/greenlet-3.5.3-cp313-cp313-win_amd64.whl", hash = "sha256:c82304750f057167ff60d188df1d0cc1764ce9567eadf03e6a7443bcedd0b30b", size = 239850, upload-time = "2026-06-26T18:21:54.613Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/7e/220a7f5824a64a60443fc03b39dfac4ea63a7fb6d481efa27eafa928e7f4/greenlet-3.5.3-cp313-cp313-win_arm64.whl", hash = "sha256:dc133a1569ee667b2a6ef56ce551084aeefd87a5acbc4736d336d1e2edc6cfc4", size = 238141, upload-time = "2026-06-26T18:22:48.507Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c3/93/43e116ee114b28737ba7e12952a0d4e2f55944d0f84e42bc91ba7192a3c9/greenlet-3.5.3-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:fd2e02fa07485778536a036222d616ab957b1d533f36b3ed98ce725d9c9d3117", size = 288202, upload-time = "2026-06-26T18:23:49.604Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/82/2f/146d218299046a43d1f029fd544b3d110d0f175a09c715c7e8da4a4a345d/greenlet-3.5.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df0a0628d1597eb0897b62f55d1343f772405fd25f3b2a796c76874b0c2e22e8", size = 654096, upload-time = "2026-06-26T19:07:12.71Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a0/cc/04738cafb3f45fa991ea44f9de94c47dcec964f5a972300988a6751f49d9/greenlet-3.5.3-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ebd933a6adabc298bab47731a130fe6bfb888bd934eee37810f151159544540d", size = 666304, upload-time = "2026-06-26T19:10:09.503Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/aa/4e0dad5e605c270c784ab911c43da6adb136ccd4d81180f763ca429a723d/greenlet-3.5.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4b9d501b40e80b70e32323c799dd9b420a5577a9601469d362ae1ffb690f3a7c", size = 663635, upload-time = "2026-06-26T18:32:20.802Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/50/13efdbea246fe3d3b735e191fec08fb50809f53cd2383ebe123d0809e44b/greenlet-3.5.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a1fad1d11e7d6aab184107baa8e4ece11ccba3ec9599cd7efa5ff4d70d43256a", size = 1621252, upload-time = "2026-06-26T19:09:05.647Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f7/22/c0a336ae4a1410fd5f5121098e5bfbf1865f64c5ef80b4b5412886c4a332/greenlet-3.5.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:fad5aec764399f1b5cc347ad250a59660f20c8f8888ea6bae1f93b769cce1154", size = 1684824, upload-time = "2026-06-26T18:31:47.738Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/94/91aec0030bea75c4b3244251d0de60a1f3432d1ecb53ab6c437fb5c3ba61/greenlet-3.5.3-cp314-cp314-win_amd64.whl", hash = "sha256:7669aa24cf2a1041d6f7899575b494a3ab4cf68bfcc8609b1dc0be7272db835e", size = 240754, upload-time = "2026-06-26T18:22:15.669Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/06/68d0983e79e02138f64b4d303c500c27ddb48e5e77f3debb80888a921eae/greenlet-3.5.3-cp314-cp314-win_arm64.whl", hash = "sha256:5b4807c4082c9d1b6d9eed56fcd041863e37f2228106eef24c30ca096e238605", size = 239549, upload-time = "2026-06-26T18:22:42.996Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/91/95/3e161213d7f1d378d15aa9e792093e9bfe01844680d04b7fd6e0107c9098/greenlet-3.5.3-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:271a8ea7c1024e8a0d7dd2be66dd66dda8a07193f41a17b9e924f7600f5b62be", size = 296389, upload-time = "2026-06-26T18:22:20.657Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/92/715c44721abe2b4d1ae9abde4179411868a5bff312479f54e105d372f131/greenlet-3.5.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19131729ae0ddc3c2e1ef85e650169b5e37ee32e400f215f78b94d7b0d567310", size = 653382, upload-time = "2026-06-26T19:07:14.209Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a0/83/37a10372a1090a6624cca8e74c12df1a36c2dc36429ed0255b7fb1aeee23/greenlet-3.5.3-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1540dd8e5fc2a5aec40fbb98ef8e149fa47c89a4b4a1cf2575a14d3d1869d7a8", size = 659401, upload-time = "2026-06-26T19:10:10.876Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/db/e2/d1509cad4207da559cc42986ecdd8fc67ad0d1bba2bf03023c467fd5e0f3/greenlet-3.5.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e81fa194a1d20967877bdf9c7794db2bc99063e5be36aee710c08f04c5bb087f", size = 656969, upload-time = "2026-06-26T18:32:22.272Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/86/7d/eaf70de20aadca3a5884aec58362861c64ce45e7b277f47ed026926a3b89/greenlet-3.5.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:55cf4d777485d43110e47133cbba6d74a8885a87ec1227ef0267f9ee80c5aa21", size = 1617822, upload-time = "2026-06-26T19:09:06.893Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/f9/414d38fc400ae4350d4185eaad1827676f7cf5287b9136e0ed1cbbe20a7f/greenlet-3.5.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:12a248ba75f6a9a236375f52296c498c89ff1d8badf32deb9eca7abd5853f7da", size = 1677983, upload-time = "2026-06-26T18:31:49.396Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e4/15/7edb977e08f9bff702fe42d6c902702786ff6b9694058b4e6a2a6ac90e57/greenlet-3.5.3-cp314-cp314t-win_amd64.whl", hash = "sha256:efc6bd60ea02e085862c74a3ef64b147ffc6f1a5ea7d9f26e7a939943f68c1e3", size = 243626, upload-time = "2026-06-26T18:24:41.485Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/8a/93928dce91e6b3598b5e779e8d1fd6576a504640c58e78627077f6a7a91a/greenlet-3.5.3-cp315-cp315-macosx_11_0_universal2.whl", hash = "sha256:ea03f2f04367845d6b58eeed276e1e56e51f0b97d8ad5a88a7d20a91dc9056cc", size = 288860, upload-time = "2026-06-26T18:22:48.07Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4f/ca/69db42d447a1378043e2c8f19c09cbbd1263371505053c496b49066d3d16/greenlet-3.5.3-cp315-cp315-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78dbef602fda6d97d957eb7937f70c9ce9e9527330347f8f6b6f9e554a9e7a47", size = 659747, upload-time = "2026-06-26T19:07:15.565Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a8/0b/af7ac2ef8dd41e3da1a40dda6305c23b9a03e13ba975ec916357b50f8575/greenlet-3.5.3-cp315-cp315-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f73857adb8fee13fa56c172bd11262f888c0c648f9fea113e777bb2c7904a81", size = 670419, upload-time = "2026-06-26T19:10:12.293Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/51/1e/1d51640cacbfc455dbe9f9a9f594c49e4e244f63b9971a2f4764e46cc53d/greenlet-3.5.3-cp315-cp315-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:232fec92e823addaf02d9472cf7381e24a1d046a6ced1103c5caa4c21b9dfc1d", size = 668787, upload-time = "2026-06-26T18:32:24.298Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/21/66/4030d5b0b5894500023f003bb054d9bb354dfbd1e186c3a296759172f5f5/greenlet-3.5.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:2421c3564da9429d5586d46ca31ebb26516b5498a802cf65c041a8e8a8980d34", size = 1626305, upload-time = "2026-06-26T19:09:08.281Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/50/5221371c7550108dfa3c378debc41d032aa9c78e89abb01d8011cfc93289/greenlet-3.5.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e0f0d160f0b2e558e6c75f7930967183255dc9735e5f5b8cae58ee09c9576d8b", size = 1688631, upload-time = "2026-06-26T18:31:51.278Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/5d/00d469daae3c65d2bf620b10eee82eb022127d483c6bc8c69fae6f3fbf17/greenlet-3.5.3-cp315-cp315-win_amd64.whl", hash = "sha256:dd99329bbc15ca78dcc583dba05d0b1b0bae01ab6c2174989f5aaee3e41ac930", size = 241027, upload-time = "2026-06-26T18:22:38.203Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/e8/883785b44c5780ed71e83d3e4437e710470be17a2e181e8b601e2da0dc4a/greenlet-3.5.3-cp315-cp315-win_arm64.whl", hash = "sha256:499fef2acede88c1864a57bb586b4bf533c81e1b82df7ab93451cdb47dfec227", size = 240085, upload-time = "2026-06-26T18:23:54.217Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/da/4f4a8450962fad137c1c8981a3f1b8919d06c829993d4d476f9c525d5173/greenlet-3.5.3-cp315-cp315t-macosx_11_0_universal2.whl", hash = "sha256:176bc16a721fa5fc294d70b87b4dfa5fbdd251b3da5d5372735ecef9bd7d6d0c", size = 297221, upload-time = "2026-06-26T18:23:27.176Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/66/b3bfae3e220a9b63ea539a0eea681800c69ab1aada757eae8789f183e7ce/greenlet-3.5.3-cp315-cp315t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:629b614d2b786e89c50440e246f33eea78f58a962d0bdbbcc809e6d13605903f", size = 657221, upload-time = "2026-06-26T19:07:16.973Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7b/81/b6d4d73a709684fc77e7fa034d7c2fe82cffa9fc920fadcaa659c2626213/greenlet-3.5.3-cp315-cp315t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2b2e857ae16f5f72142edf75f9f176fe7526ba19a2841df1420516f83831c9f2", size = 663226, upload-time = "2026-06-26T19:10:13.723Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/07/e210b02b589f16e74ff48b730690e4a34ffe984219fce4f3c1a0e7ec8545/greenlet-3.5.3-cp315-cp315t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e515757e2e36bcbf1fad09a46e1557e8b1ae1797d4b44d09da7deed88ad28608", size = 660802, upload-time = "2026-06-26T18:32:26.081Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/2e/5303eb3fa06bca089060f479707182a93e360683bc252acf846c3090d34e/greenlet-3.5.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:b363d46ed1ea431825fdb01471bb024fc08399bad1572a616e853c7684415adb", size = 1622157, upload-time = "2026-06-26T19:09:09.527Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/70/50de47a488f14df260b50ae34fb5d56016e308b098eab02c878b5223c26a/greenlet-3.5.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:e44da2f5bbdaabaf7d80b73dbb430c7035771e9f244e3c8b769715c9d8fa0a16", size = 1681159, upload-time = "2026-06-26T18:31:52.986Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/13/1055e1dda7882073eda533e2b96c62e55bbd2db7fda6d5ece992febc7071/greenlet-3.5.3-cp315-cp315t-win_amd64.whl", hash = "sha256:8ff8bed3e3baa20a3ea261ce00526f1898ad4801d4886fd2220580ee0ad8fadf", size = 244007, upload-time = "2026-06-26T18:22:04.353Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b4/0d/ca7d15afbdc397e3401134c9e1800d51d12b829661786187a4ad08fe484f/greenlet-3.5.3-cp315-cp315t-win_arm64.whl", hash = "sha256:b7068bd09f761f3f5b4d214c2bed063186b2a86148c740b3873e3f56d79bac31", size = 242586, upload-time = "2026-06-26T18:23:37.93Z" }, +] + [[package]] name = "gunicorn" version = "26.0.0" @@ -603,22 +678,6 @@ wheels = [ { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl", hash = "sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea", size = 38117, upload-time = "2025-11-22T08:28:36.939Z" }, ] -[[package]] -name = "modelvault" -version = "0.16.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/c8/e2d64e9d80040efd1e01fe25ef121f5faa473ce40631c34dbe4e66c1f271/modelvault-0.16.0.tar.gz", hash = "sha256:aa8378dbb9f6beffa76ae8cbbfacf549486d0e195a72e28ca299b737cc839eef", size = 236231, upload-time = "2026-06-08T01:04:07.736Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a9/21/2ce73f22e30413f9167324e5e61bcad4dd7a50b038c2b08c3aa0150774e8/modelvault-0.16.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:a0a33a00387d2bf41c8aa69532a4669275614ba758decd502f5d6ec0f417442d", size = 2314107, upload-time = "2026-06-08T01:03:57.258Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/ec/2a83eca634b8576494a9aa795d8da6b204003ebf17e63d44f33ef368c4e0/modelvault-0.16.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec12950aa612690991692d7973e74f4e15bbb3f8d67e92d11532eb436d42f39d", size = 2207973, upload-time = "2026-06-08T01:03:33.756Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/44/27fcfc8ac0536e0a20cc8bb9ee01a87063b2ff2cef43d916f48bfa171f4f/modelvault-0.16.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1245e57151e7508606fd34e4d8510a460c1f3810157c09a4449936cf3a798bde", size = 2442060, upload-time = "2026-06-08T01:04:06.264Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/35/a3/0042eb943d36b449d45b2d617ec02db11459328f4111a48683c2965331dd/modelvault-0.16.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:55f1e962e785da4c896b15476897f81b300d7147f6d5b51f6666497c5d8d3674", size = 2481291, upload-time = "2026-06-08T01:04:08.08Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/e9/96e0a637d080419b221e63a4ee393d18aaef3b9132bcecfaa528b5c6f55f/modelvault-0.16.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5cafa8505f9c0e4d15eaa43e320430c688551968bbe8cfe7510d2c9f63afab68", size = 1957214, upload-time = "2026-06-08T01:03:52.779Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/ed/a8c0b32454e5a315e55ad3f3b70671b9f66495915d658419aa8484c46cd7/modelvault-0.16.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1b2b65d4017f83675f9c1a8c0c9b9e8e1ea541526776e57c6e698e81f677b4a2", size = 2075934, upload-time = "2026-06-08T01:04:01.389Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/29/e250a6edd613451c680dbf20ddcbe528c68762d369f0f5bf3ac31090796a/modelvault-0.16.0-cp39-abi3-win_amd64.whl", hash = "sha256:95e42e53aba0de5c8f798863ab25a3271ef8405c51728a15399977e39a187a66", size = 2091287, upload-time = "2026-06-08T01:05:47.349Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a9/44/352248e4a1723994dd3b6ccd1306b74b3c6c2bd5b8e02c66572626e5ae66/modelvault-0.16.0-cp39-abi3-win_arm64.whl", hash = "sha256:7b3defb3ce620039e63eef90bb7973d727b42ab8e3bc8303490429f9bc32c96b", size = 1894605, upload-time = "2026-06-08T01:05:34.93Z" }, -] - [[package]] name = "module-bank" version = "0.3.2" @@ -1113,6 +1172,47 @@ wheels = [ { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, ] +[[package]] +name = "sqlalchemy" +version = "2.0.51" +source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +dependencies = [ + { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/f1/a7a892f18d4d224e6b26f706531eafccc41e37594d37d304786969ee13cb/sqlalchemy-2.0.51.tar.gz", hash = "sha256:804dccd8a4a6242c4e30ad961e540e18a588f6527202f2d6791b01845d59fdc9", size = 9912201, upload-time = "2026-06-15T15:41:20.012Z" } +wheels = [ + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d5/70/e868bc5412acd101a8280f25c95f10eeae0771c4eb806b02491142810ee8/sqlalchemy-2.0.51-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d78702b26ba1c18b2d0fb2ea940ba7f17a9581b42e8361ff93920ebbee1235a", size = 2160291, upload-time = "2026-06-15T16:08:48.918Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/1c/71ee0f8a6b9d7316a1ccd30430b4c62b6c2e36adc96017a4e3a72dce49d6/sqlalchemy-2.0.51-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581921d849d6e6f994d560389192955e80e2950e18fcdfe2ccea863e01158e6e", size = 3343835, upload-time = "2026-06-15T16:19:42.613Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2b/7c/7ab9f9aadc5944fdd06612484ed7918fe376ad871a5f50404dc1536e0194/sqlalchemy-2.0.51-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1d21ce524ab86c23046e992a5b81cb54c21079c6df6e78b8fc77d77cac70a6b9", size = 3358470, upload-time = "2026-06-15T16:26:38.011Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/7d/ff77169fee6186de145a7f2b87006c39638391130abbab2b1f63ac6ea583/sqlalchemy-2.0.51-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c5d98a2709840027f5a347c3af0a7c3d5f6c1ff93af2ca1c54494e23cba8f389", size = 3289874, upload-time = "2026-06-15T16:19:45.212Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6f/3b/6c505903710d781b55bc3141ee34a062bf9745a6b5bc7333305b9ed63b33/sqlalchemy-2.0.51-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1181256e0f16479691b5616d36375dc2620ad8332b25978763c3d206ad3f3f1d", size = 3321692, upload-time = "2026-06-15T16:26:39.747Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3c/b7/c5ffe50aa2f4d947c9250e1519d939260329a07fe6272edfccd784b3d007/sqlalchemy-2.0.51-cp312-cp312-win32.whl", hash = "sha256:9f380393be5abeb6815f68fd39271b95127173511b6706b0a630a9995d53f8f5", size = 2119674, upload-time = "2026-06-15T16:23:09.543Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/dc/46a65916af68a06ef6b972c6050ba4c8f97070fe3fb33097d34229d9bef6/sqlalchemy-2.0.51-cp312-cp312-win_amd64.whl", hash = "sha256:2cf39aabdf48e87c1c2c2ed6d20d33ffa0733b3071ce9c5f66357947dd009080", size = 2146670, upload-time = "2026-06-15T16:23:11.048Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/fe/a210d52fd1a90ecfae8a78e9d8b27e18d733d60818a8bf250ff690b75120/sqlalchemy-2.0.51-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7c2056838b6685b72fdb36c99996cf862753461a62f2e84f4196371d3b2d6a07", size = 2157184, upload-time = "2026-06-15T16:08:50.374Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/6b/2dce8369b199cb855110e056032f94a9f66dacc2237d3d39c115a86eac56/sqlalchemy-2.0.51-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:483b11bd46bf35fc14c52faf338b04300c9e6ce554bce9b11be85bfec3bc3195", size = 3284735, upload-time = "2026-06-15T16:19:46.934Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/53/ff/dbc495b8a14da840faffb353857a72d4190113cac33727906fb997047f0f/sqlalchemy-2.0.51-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1bed1ee8b01da6088210aa9412023326fb98a599ba502e6118308601dcbef77f", size = 3302756, upload-time = "2026-06-15T16:26:41.336Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cf/d5/fde8f4dddcf518ee15ab35a7c6a28acc32c8ba548d1d2aa451f96e6dbb0b/sqlalchemy-2.0.51-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:72ca54c952107ba5cd58854b67a5a6268631289d21651a1235396f3b98b47400", size = 3232055, upload-time = "2026-06-15T16:19:49.286Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/67/d1/43d3a0ac955a58601c24fa23038b1c55ee3a1ec02c0f96ebb1eae2bcf614/sqlalchemy-2.0.51-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b3e693d15533a45cd5906f0589f9c35090bef6ef45bf1e8195c424aa0ae06a8d", size = 3269850, upload-time = "2026-06-15T16:26:43.017Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/94/df/de669c7054cd47c4439ac34b1b2ee8b804a794791fbb10720e997a2c87c7/sqlalchemy-2.0.51-cp313-cp313-win32.whl", hash = "sha256:b93ab07b5292dbe7e6b8da89475275e7042744283921344b56105f3eeb0f828b", size = 2117721, upload-time = "2026-06-15T16:23:12.36Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/8a/403c51d064196bae20a0bc2476577f83a3f8dd299719a97417086b7f2ec5/sqlalchemy-2.0.51-cp313-cp313-win_amd64.whl", hash = "sha256:0f053118c30e53161857a953e4de667d90e274980dccbe5dd3829bbbeece72a5", size = 2143615, upload-time = "2026-06-15T16:23:13.906Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b1/49/a739be2e1d02a96a658eb71ab45d921c874249252358ad24a5bffdd02525/sqlalchemy-2.0.51-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6ea306caaae6bd5afd0a46050003c88f6bf33227377a49298c498c3cb88ff491", size = 2158999, upload-time = "2026-06-15T16:08:51.759Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/23/6b/2e0e38cf75c8780eca78d9b2e78164f8bcfd70125e5caa588ff5cbb9c9f4/sqlalchemy-2.0.51-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c45a496d6bc05dec41dcd4c3a2b183723f47473255c159cd80b503c8f246424d", size = 3282539, upload-time = "2026-06-15T16:19:51.065Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dd/a1/e77854cb5336fd37dc3c6ae3b71de242c98caac5725120be0b526b31cbd0/sqlalchemy-2.0.51-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4004ada0aafe8ae1991b2cd1d99c6d9146126e123bd6f883c260d974aa012e54", size = 3287545, upload-time = "2026-06-15T16:26:44.735Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f6/ab/9e17272fd4dac8df3b83c4fbe52b998a1c9d89a843c8c35ff29b74ff7364/sqlalchemy-2.0.51-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0f6bcad487aee1c638d707235682fc96f741de00663619881ab235400d03289e", size = 3230929, upload-time = "2026-06-15T16:19:52.625Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/3c/52f408ea701781caee975606beccc48845f2aee8711ac29843d612c0306c/sqlalchemy-2.0.51-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:39a76529db6305693d8d4affa58ad5b5e2e18edd62daea628b29b97930b3513d", size = 3252888, upload-time = "2026-06-15T16:26:46.454Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/16/3efd2ee6bc4ca4693a30a1dd17a91b606cae15d517d2a4746611d9b73ce8/sqlalchemy-2.0.51-cp314-cp314-win32.whl", hash = "sha256:08a204d8b5638717c26a24df18fcf40af45a6b22e35b70b1d62f0113c2e278e8", size = 2120551, upload-time = "2026-06-15T16:23:15.629Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7b/78/55b12e70f45bccc40d9e483925c065027b3b98ea4cbbdf6f8c2546feaf6c/sqlalchemy-2.0.51-cp314-cp314-win_amd64.whl", hash = "sha256:96747bfbadb055466e5b46d572618170046b45ce5a4879167f50d70a5319a499", size = 2146318, upload-time = "2026-06-15T16:23:17.108Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/21/db/a9574ed40fed418924b1b1a3e54f47ee3963053b3d3d325a0d36b41f2c08/sqlalchemy-2.0.51-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5ea1a213be1fcd5e49d9904c3b9939211ded90bc2a64e93f4c01963474285de", size = 2178920, upload-time = "2026-06-15T15:59:56.285Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/90/a1bb5c7cbba76b7bc1fbd586d0a5479a7bc9c27b4a8298f22ec9423b2bb3/sqlalchemy-2.0.51-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c6b36ed71f41942bdcd2ad2522be46bfce09d5705be5640ecf19bbc7660e4b7", size = 3566534, upload-time = "2026-06-15T15:58:35.024Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/15/4b/481f1fed30e0e9e8dd24aecbb49f29eb57fe7657ece5cf06ee9b84bb97d8/sqlalchemy-2.0.51-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c2c62877097e1a0db401fba5cb4debee33265e5b2a55c4ccb489c02c53b4f72", size = 3535844, upload-time = "2026-06-15T16:02:43.973Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/71/0aa64aeda645510af0a43f7d9ee70932f0d1dc4263aed34c50ee891d9df3/sqlalchemy-2.0.51-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0378d055e9e8cd6ce4d8dff683bdd3d7d413533c4ee51d67a2b1e0f9eacc0f23", size = 3475355, upload-time = "2026-06-15T15:58:36.592Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/db/6061db32316446135a3abae5f308d144ab988a34234726042da3e58b1c63/sqlalchemy-2.0.51-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6e46fc36029eff666391e0531e5387b62ce6c4f1d8e50b3fb3099eaca1b42522", size = 3486591, upload-time = "2026-06-15T16:02:45.346Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/c9/f14fdf71bb8957e0c7e39db69bbdf12b5c80f4ef775fdfa127bf4e0d6760/sqlalchemy-2.0.51-cp314-cp314t-win32.whl", hash = "sha256:9161cfc9efce70d1715f47d6ff40f79c6778c00d53be4fbc09d70301e4b83ba7", size = 2151313, upload-time = "2026-06-15T16:03:39.127Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/c6/673e618e6f4f297e126d9b56ea2f6478708f6c1af4e3223835c22e2c3697/sqlalchemy-2.0.51-cp314-cp314t-win_amd64.whl", hash = "sha256:159bb6ba32059f57ad7375a8f50d844dd2f19d14954ecf820cd33e20debd46b2", size = 2186280, upload-time = "2026-06-15T16:03:40.569Z" }, + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e2/22/dbf013a12ec759e54a34a119e9e217435b3f71b2dd5c61a7ade0a25dae87/sqlalchemy-2.0.51-py3-none-any.whl", hash = "sha256:bb024d8b621d0be75f4f44ecc7c950450026e76d66dc8f791bb5331d7fed59d5", size = 1944334, upload-time = "2026-06-15T16:09:22.418Z" }, +] + [[package]] name = "sqlite-vfs" version = "0.1.0" @@ -1122,6 +1222,20 @@ wheels = [ { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ef/26/a3f51ea9d10efe2c4f85cac78dcbd898b437d2331cf25d470f804e4498b7/sqlite_vfs-0.1.0-py3-none-any.whl", hash = "sha256:c6e27a35e504bb6360fb0d9083d79572367a903788b3b14aea5f1188130e9314", size = 10768, upload-time = "2025-11-08T08:15:18.588Z" }, ] +[[package]] +name = "sqlmodel" +version = "0.0.39" +source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "sqlalchemy" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/ee/22a0559283c3cf6048678e787ed5d4959dcd00dedd8ba4567eeae684eeb1/sqlmodel-0.0.39.tar.gz", hash = "sha256:23d8e50a8d8ee936032ed79c55023a5d618dd6bc3c510bbf4909d1a7a605a570", size = 91057, upload-time = "2026-06-25T13:01:38.475Z" } +wheels = [ + { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cf/7d/b9813a582d4eb310be35e1fc7dfaae71207d7b62e9e53be314ebd251b53b/sqlmodel-0.0.39-py3-none-any.whl", hash = "sha256:90ebe92ce5cc11d7fff8dc7cb594790a102333c8fe7c14865254f6fc5c939795", size = 29680, upload-time = "2026-06-25T13:01:37.494Z" }, +] + [[package]] name = "starlette" version = "1.3.1"