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

@@ -7,6 +7,7 @@
- 关键数据(计费)仍然立即 commit
"""
from typing import Any
import asyncio
from src.core.logger import logger
@@ -26,13 +27,13 @@ class BatchCommitter:
self._lock = asyncio.Lock()
self._task = None
async def start(self):
async def start(self) -> Any:
"""启动后台批量提交任务"""
if self._task is None:
self._task = asyncio.create_task(self._batch_commit_loop())
logger.info(f"批量提交器已启动,间隔: {self.interval_seconds}s")
async def stop(self):
async def stop(self) -> Any:
"""停止后台任务"""
if self._task:
self._task.cancel()
@@ -43,7 +44,7 @@ class BatchCommitter:
self._task = None
logger.info("批量提交器已停止")
def mark_dirty(self, session: Session):
def mark_dirty(self, session: Session) -> Any:
"""标记 Session 有待提交的更改"""
# 请求级事务由中间件统一 commit/rollback避免后台任务在请求中途误提交。
if session is None:
@@ -52,7 +53,7 @@ class BatchCommitter:
return
self._pending_sessions.add(session)
async def _batch_commit_loop(self):
async def _batch_commit_loop(self) -> None:
"""后台批量提交循环"""
while True:
try:
@@ -65,7 +66,7 @@ class BatchCommitter:
except Exception as e:
logger.error(f"批量提交出错: {e}")
async def _commit_all(self):
async def _commit_all(self) -> None:
"""提交所有待处理的 Session"""
async with self._lock:
if not self._pending_sessions:
@@ -107,13 +108,13 @@ def get_batch_committer() -> BatchCommitter:
return _batch_committer
async def init_batch_committer():
async def init_batch_committer() -> None:
"""初始化并启动批量提交器"""
committer = get_batch_committer()
await committer.start()
async def shutdown_batch_committer():
async def shutdown_batch_committer() -> None:
"""关闭批量提交器"""
committer = get_batch_committer()
await committer.stop()

View File

@@ -2,6 +2,8 @@
缓存服务 - 统一的缓存抽象层
"""
from __future__ import annotations
import json
from typing import Any

View File

@@ -4,6 +4,8 @@
from __future__ import annotations
def extract_error_message(error: Exception, status_code: int | None = None) -> str:
"""
从异常中提取错误消息,优先使用上游原始响应(用于链路追踪/调试)

View File

@@ -7,6 +7,9 @@
- 开发环境可返回详细信息用于调试
"""
from __future__ import annotations
from starlette.requests import Request
import asyncio
import re
import traceback
@@ -140,7 +143,7 @@ def translate_pydantic_errors(errors: list[dict[str, Any]]) -> str:
# 延迟导入韧性管理器,避免循环导入
def get_resilience_manager():
def get_resilience_manager() -> Any:
try:
from ..core.resilience import resilience_manager
@@ -173,7 +176,7 @@ class ProviderException(ProxyException):
message: str,
provider_name: str | None = None,
request_metadata: Any | None = None,
**kwargs,
**kwargs: Any,
):
self.request_metadata = request_metadata # 保存元数据以便传递
details = {"provider": provider_name} if provider_name else {}
@@ -537,7 +540,7 @@ class ThinkingSignatureException(UpstreamClientException):
message: str,
provider_name: str | None = None,
upstream_error: str | None = None,
request_metadata: Any = None,
request_metadata: Any | None = None,
):
super().__init__(
message=message,
@@ -688,17 +691,17 @@ class ExceptionHandlers:
"""FastAPI异常处理器"""
@staticmethod
async def handle_proxy_exception(request, exc: ProxyException):
async def handle_proxy_exception(request: Request, exc: ProxyException) -> None:
"""处理代理异常"""
return ErrorResponse.from_exception(exc)
@staticmethod
async def handle_http_exception(request, exc: HTTPException):
async def handle_http_exception(request: Request, exc: HTTPException) -> None:
"""处理HTTP异常"""
return ErrorResponse.from_exception(exc)
@staticmethod
async def handle_generic_exception(request, exc: Exception):
async def handle_generic_exception(request: Request, exc: Exception) -> None:
"""处理通用异常 - 集成韧性管理"""
# 首先检查是否为HTTPException如果是则委托给HTTP异常处理器

View File

@@ -21,6 +21,8 @@
logger.exception("异常,带堆栈")
"""
from __future__ import annotations
import logging
import os
import sys
@@ -115,19 +117,19 @@ if not DISABLE_FILE_LOG:
file_log_config["diagnose"] = False
# 主日志文件 - 所有级别
logger.add(
logger.add( # type: ignore[call-overload]
log_dir / "app.log",
level="DEBUG",
**file_log_config, # type: ignore[arg-type]
**file_log_config,
)
# 错误日志文件 - 仅 ERROR 及以上
error_log_config = file_log_config.copy()
error_log_config["rotation"] = "50 MB"
logger.add(
logger.add( # type: ignore[call-overload]
log_dir / "error.log",
level="ERROR",
**error_log_config, # type: ignore[arg-type]
**error_log_config,
)
# ============================================================================

View File

@@ -35,7 +35,7 @@ class ModuleRegistry:
_instance: ModuleRegistry | None = None
def __init__(self):
def __init__(self) -> None:
self._modules: dict[str, ModuleDefinition] = {}
self._initialized: set[str] = set()

View File

@@ -21,11 +21,11 @@ class TokenCounter:
"claude-2": "cl100k_base",
}
def __init__(self):
def __init__(self) -> None:
self._encodings = {}
self._default_encoding = None
def _get_encoding(self, model: str):
def _get_encoding(self, model: str) -> Any:
"""获取模型对应的编码器"""
# 标准化模型名称
model_base = model.lower().split("-")[0]

View File

@@ -3,6 +3,8 @@
提供全局的错误处理、自动恢复、降级策略和用户友好的错误体验
"""
from __future__ import annotations
import asyncio
import functools
import threading
@@ -75,7 +77,7 @@ class CircuitBreaker:
self.state = "closed" # closed, open, half-open
self._lock = threading.Lock()
def call(self, func: Callable, *args, **kwargs):
def call(self, func: Callable[..., Any], *args: Any, **kwargs: Any) -> Any:
"""执行函数调用,应用熔断逻辑"""
with self._lock:
if self.state == "open":
@@ -98,12 +100,12 @@ class CircuitBreaker:
return True
return time.time() - self.last_failure_time >= self.timeout
def _on_success(self):
def _on_success(self) -> None:
"""成功时重置计数器"""
self.failure_count = 0
self.state = "closed"
def _on_failure(self):
def _on_failure(self) -> None:
"""失败时增加计数器"""
self.failure_count += 1
self.last_failure_time = time.time()
@@ -114,14 +116,14 @@ class CircuitBreaker:
class ResilienceManager:
"""系统韧性管理器"""
def __init__(self):
def __init__(self) -> None:
self.error_patterns: list[ErrorPattern] = []
self.circuit_breakers: dict[str, CircuitBreaker] = {}
self.error_stats: dict[str, int] = {}
self.last_errors: list[dict[str, Any]] = []
self._setup_default_patterns()
def _setup_default_patterns(self):
def _setup_default_patterns(self) -> None:
"""设置默认错误处理模式"""
# 数据库连接错误 - 只捕获特定的数据库相关异常
@@ -187,7 +189,7 @@ class ResilienceManager:
)
)
def add_error_pattern(self, pattern: ErrorPattern):
def add_error_pattern(self, pattern: ErrorPattern) -> None:
"""添加错误处理模式"""
self.error_patterns.append(pattern)
@@ -277,12 +279,12 @@ resilience_manager = ResilienceManager()
def resilient_operation(
operation_name: str = None,
max_retries: int = None,
retry_delay: float = None,
circuit_breaker_key: str = None,
operation_name: str | None = None,
max_retries: int | None = None,
retry_delay: float | None = None,
circuit_breaker_key: str | None = None,
context: dict[str, Any] = None,
):
) -> Any:
"""
韧性操作装饰器
自动处理重试、熔断、错误记录等
@@ -290,7 +292,7 @@ def resilient_operation(
def decorator(func: Callable) -> Callable:
@functools.wraps(func)
async def async_wrapper(*args, **kwargs):
async def async_wrapper(*args: Any, **kwargs: Any) -> Any:
op_name = operation_name or f"{func.__module__}.{func.__name__}"
retries = max_retries or 3
delay = retry_delay or 1.0
@@ -342,7 +344,7 @@ def resilient_operation(
raise last_error
@functools.wraps(func)
def sync_wrapper(*args, **kwargs):
def sync_wrapper(*args: Any, **kwargs: Any) -> None:
# 对于同步函数,创建异步包装器并运行
return asyncio.run(async_wrapper(*args, **kwargs))
@@ -356,7 +358,7 @@ def resilient_operation(
@asynccontextmanager
async def safe_operation(operation_name: str, context: dict[str, Any] = None):
async def safe_operation(operation_name: str, context: dict[str, Any] = None) -> Any:
"""
安全操作上下文管理器
自动处理异常并提供用户友好的错误信息
@@ -381,7 +383,7 @@ async def safe_operation(operation_name: str, context: dict[str, Any] = None):
logger.warning(f"操作警告 [{error_result['error_id']}]: {error_result['user_message']}")
def graceful_degradation(fallback_func: Callable = None, fallback_value: Any = None):
def graceful_degradation(fallback_func: Callable | None = None, fallback_value: Any | None = None) -> Any:
"""
优雅降级装饰器
当主要功能失败时,自动切换到备用方案
@@ -389,7 +391,7 @@ def graceful_degradation(fallback_func: Callable = None, fallback_value: Any = N
def decorator(func: Callable) -> Callable:
@functools.wraps(func)
async def async_wrapper(*args, **kwargs):
async def async_wrapper(*args: Any, **kwargs: Any) -> Any:
try:
if asyncio.iscoroutinefunction(func):
return await func(*args, **kwargs)