fix: 修复 mypy 类型检查错误并升级到 Python 3.14

主要变更:
- 修复 1483 个 mypy 类型检查错误
- 添加缺失的类型注解 (Any, Callable, Session 等)
- 修复隐式 Optional 类型 (param: Type = None -> param: Type | None = None)
- 修复 __new__ 单例模式返回类型
- 添加 type: ignore 注释处理第三方库类型问题
- 更新 pyproject.toml 依赖到 Python 3.14 兼容版本
- 更新 mypy/black 配置为 Python 3.14
This commit is contained in:
fawney19
2026-01-30 14:30:57 +08:00
parent 7066166757
commit 5603c72f40
142 changed files with 2864 additions and 1853 deletions

View File

@@ -4,6 +4,7 @@
提供系统支持的能力列表,供前端展示和配置使用。
"""
from typing import Any
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
@@ -17,7 +18,7 @@ router = APIRouter(prefix="/api/capabilities", tags=["System Catalog"])
@router.get("")
async def list_capabilities():
async def list_capabilities() -> Any:
"""
获取所有能力定义
@@ -49,7 +50,7 @@ async def list_capabilities():
@router.get("/user-configurable")
async def list_user_configurable_capabilities():
async def list_user_configurable_capabilities() -> Any:
"""
获取用户可配置的能力列表
@@ -84,7 +85,7 @@ async def list_user_configurable_capabilities():
async def get_model_supported_capabilities(
model_name: str,
db: Session = Depends(get_db),
):
) -> Any:
"""
获取指定模型支持的能力列表

View File

@@ -3,6 +3,9 @@
不包含敏感信息,普通用户可访问
"""
from __future__ import annotations
from typing import Any
from collections import defaultdict
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
@@ -35,6 +38,7 @@ from src.models.endpoint_models import (
PublicHealthEvent,
)
from src.services.health.endpoint import EndpointHealthService
from src.api.base.context import ApiRequestContext
router = APIRouter(prefix="/api/public", tags=["System Catalog"])
pipeline = ApiRequestPipeline()
@@ -47,7 +51,7 @@ async def get_public_providers(
skip: int = Query(0, description="跳过记录数"),
limit: int = Query(100, description="返回记录数限制"),
db: Session = Depends(get_db),
):
) -> Any:
"""
获取提供商列表(用户视图)
@@ -84,7 +88,7 @@ async def get_public_models(
skip: int = Query(0, description="跳过记录数"),
limit: int = Query(100, description="返回记录数限制"),
db: Session = Depends(get_db),
):
) -> Any:
"""
获取模型列表(用户视图)
@@ -122,7 +126,7 @@ async def get_public_models(
@router.get("/stats", response_model=ProviderStatsResponse)
async def get_public_stats(request: Request, db: Session = Depends(get_db)):
async def get_public_stats(request: Request, db: Session = Depends(get_db)) -> Any:
"""
获取系统统计信息
@@ -147,7 +151,7 @@ async def search_models(
provider_id: int | None = Query(None, description="提供商ID过滤"),
limit: int = Query(20, description="返回记录数限制"),
db: Session = Depends(get_db),
):
) -> Any:
"""
搜索模型
@@ -189,7 +193,7 @@ async def get_public_api_format_health(
lookback_hours: int = Query(6, ge=1, le=168, description="回溯小时数"),
per_format_limit: int = Query(100, ge=10, le=500, description="每个格式的事件数限制"),
db: Session = Depends(get_db),
):
) -> Any:
"""
获取各 API 格式的健康监控数据
@@ -236,7 +240,7 @@ async def get_public_global_models(
is_active: bool | None = Query(None, description="过滤活跃状态"),
search: str | None = Query(None, description="搜索关键词"),
db: Session = Depends(get_db),
):
) -> Any:
"""
获取全局模型GlobalModel列表
@@ -276,7 +280,7 @@ async def get_public_global_models(
class PublicApiAdapter(ApiAdapter):
mode = ApiMode.PUBLIC
def authorize(self, context): # type: ignore[override]
def authorize(self, context: ApiRequestContext) -> None: # type: ignore[override]
return None
@@ -286,7 +290,7 @@ class PublicProvidersAdapter(PublicApiAdapter):
skip: int
limit: int
async def handle(self, context): # type: ignore[override]
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
db = context.db
logger.debug("公共API请求提供商列表")
query = db.query(Provider)
@@ -342,7 +346,7 @@ class PublicModelsAdapter(PublicApiAdapter):
skip: int
limit: int
async def handle(self, context): # type: ignore[override]
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
db = context.db
logger.debug("公共API请求模型列表")
query = (
@@ -391,7 +395,7 @@ class PublicModelsAdapter(PublicApiAdapter):
class PublicStatsAdapter(PublicApiAdapter):
async def handle(self, context): # type: ignore[override]
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
db = context.db
logger.debug("公共API请求系统统计信息")
active_providers = db.query(Provider).filter(Provider.is_active.is_(True)).count()
@@ -428,7 +432,7 @@ class PublicSearchModelsAdapter(PublicApiAdapter):
provider_id: int | None
limit: int
async def handle(self, context): # type: ignore[override]
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
db = context.db
logger.debug(f"公共API搜索模型: {self.query}")
query_stmt = (
@@ -490,7 +494,7 @@ class PublicApiFormatHealthMonitorAdapter(PublicApiAdapter):
lookback_hours: int
per_format_limit: int
async def handle(self, context): # type: ignore[override]
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
db = context.db
now = datetime.now(timezone.utc)
since = now - timedelta(hours=self.lookback_hours)
@@ -651,7 +655,7 @@ class PublicGlobalModelsAdapter(PublicApiAdapter):
is_active: bool | None
search: str | None
async def handle(self, context): # type: ignore[override]
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
db = context.db
logger.debug("公共API请求 GlobalModel 列表")

View File

@@ -7,6 +7,7 @@ Claude API 端点
注意: /v1/models 端点由 models.py 统一处理,根据请求头返回对应格式
"""
from typing import Any
from fastapi import APIRouter, Depends, Request
from sqlalchemy.orm import Session
@@ -27,7 +28,7 @@ pipeline = ApiRequestPipeline()
async def create_message(
http_request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
Claude Messages API
@@ -63,7 +64,7 @@ async def create_message(
async def count_tokens(
http_request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
Claude Token Count API

View File

@@ -10,6 +10,7 @@ Gemini API 专属端点
- /v1beta/models (列表) 和 /v1beta/models/{model} (详情) 由 models.py 统一处理
"""
from typing import Any
from fastapi import APIRouter, Depends, Request
from sqlalchemy.orm import Session
@@ -53,7 +54,7 @@ async def generate_content(
model: str,
http_request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
Gemini generateContent API
@@ -95,7 +96,7 @@ async def stream_generate_content(
model: str,
http_request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
Gemini streamGenerateContent API
@@ -133,7 +134,7 @@ async def generate_content_v1(
model: str,
http_request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
Gemini generateContent API (v1 兼容)
@@ -147,7 +148,7 @@ async def stream_generate_content_v1(
model: str,
http_request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
Gemini streamGenerateContent API (v1 兼容)

View File

@@ -403,7 +403,7 @@ async def _proxy_request(
async def upload_file(
request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
上传文件到 Gemini Files API
@@ -463,7 +463,7 @@ async def list_files(
db: Session = Depends(get_db),
pageSize: int | None = None,
pageToken: str | None = None,
):
) -> Any:
"""
列出已上传的文件
@@ -524,7 +524,7 @@ async def get_file(
file_name: str,
request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
获取指定文件的元数据
@@ -580,7 +580,7 @@ async def delete_file(
file_name: str,
request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
删除指定文件

View File

@@ -1,6 +1,7 @@
"""公开模块状态 API供登录页等使用"""
from typing import Any
from fastapi import APIRouter, Depends
from pydantic import BaseModel
from sqlalchemy.orm import Session
@@ -20,7 +21,7 @@ class AuthModuleInfo(BaseModel):
@router.get("/auth-status", response_model=list[AuthModuleInfo])
async def get_auth_modules_status(db: Session = Depends(get_db)):
async def get_auth_modules_status(db: Session = Depends(get_db)) -> Any:
"""
获取认证模块状态(公开接口)

View File

@@ -7,6 +7,7 @@ OpenAI API 端点
注意: /v1/models 端点由 models.py 统一处理,根据请求头返回对应格式
"""
from typing import Any
from fastapi import APIRouter, Depends, Request
from sqlalchemy.orm import Session
@@ -25,7 +26,7 @@ pipeline = ApiRequestPipeline()
async def create_chat_completion(
http_request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
OpenAI Chat Completions API
@@ -58,7 +59,7 @@ async def create_chat_completion(
async def create_responses(
http_request: Request,
db: Session = Depends(get_db),
):
) -> Any:
"""
OpenAI Responses API (CLI)

View File

@@ -4,6 +4,8 @@ System Catalog / 健康检查相关端点
这些是系统工具端点,不需要复杂的 Adapter 抽象。
"""
from __future__ import annotations
from datetime import datetime, timezone
from typing import Any
@@ -97,7 +99,7 @@ def _select_provider(db: Session, provider_name: str | None) -> Provider | None:
@router.get("/v1/health")
async def service_health(db: Session = Depends(get_db)):
async def service_health(db: Session = Depends(get_db)) -> Any:
"""返回服务健康状态与依赖信息"""
active_providers = (
db.query(func.count(Provider.id)).filter(Provider.is_active == True).scalar() or 0
@@ -130,7 +132,7 @@ async def service_health(db: Session = Depends(get_db)):
@router.get("/health")
async def health_check():
async def health_check() -> Any:
"""简单健康检查端点(无需认证)"""
try:
pool_status = get_pool_status()
@@ -156,7 +158,7 @@ async def health_check():
@router.get("/")
async def root(db: Session = Depends(get_db)):
async def root(db: Session = Depends(get_db)) -> Any:
"""Root endpoint - 服务信息概览"""
# 按优先级选择最高优先级的提供商
top_provider = (
@@ -189,7 +191,7 @@ async def list_providers(
include_models: bool = Query(False),
include_endpoints: bool = Query(False),
active_only: bool = Query(True),
):
) -> Any:
"""列出所有 Provider"""
load_options = []
if include_models:
@@ -219,7 +221,7 @@ async def provider_detail(
db: Session = Depends(get_db),
include_models: bool = Query(False),
include_endpoints: bool = Query(False),
):
) -> Any:
"""获取单个 Provider 详情"""
load_options = []
if include_models:
@@ -248,7 +250,7 @@ async def test_connection(
provider: str | None = Query(None),
model: str = Query("claude-3-haiku-20240307"),
api_format: str | None = Query(None),
):
) -> Any:
"""测试 Provider 连接"""
selected_provider = _select_provider(db, provider)
if not selected_provider:
@@ -269,7 +271,7 @@ async def test_connection(
orchestrator = FallbackOrchestrator(db, redis_client)
# 定义请求函数
async def test_request_func(_prov, endpoint, key, _candidate):
async def test_request_func(_prov: Any, endpoint: Any, key: str, _candidate: Any) -> Any:
from src.api.handlers.base.request_builder import get_provider_auth
# 获取认证信息(处理 Service Account 等异步认证场景)