mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 09:50:21 +08:00
chore: 升级到 Python 3.14 并现代化代码
- 升级 Docker 基础镜像从 Python 3.12 到 3.14 - 更新 pyproject.toml 支持 Python 3.13/3.14 - 移除 Python 3.8/3.9/3.10/3.11 分类器 - 更新 black 和 mypy 配置目标版本 - 将 get_event_loop() 替换为 get_running_loop() 加上 RuntimeError 处理 - 简化 compute_cost_sync 中的 asyncio.run 使用 - Dict/List/Tuple/Set → dict/list/tuple/set (PEP 585) - Optional[T] → T | None (PEP 604) - Union[A, B] → A | B (PEP 604) - 移除废弃的 typing 导入 - 移除不必要的字符串引号注解
This commit is contained in:
@@ -3,14 +3,14 @@ API密钥管理服务
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.core.crypto import crypto_service
|
||||
from src.core.logger import logger
|
||||
from src.models.database import ApiKey, Usage, User
|
||||
from src.models.database import ApiKey, Usage
|
||||
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@ class ApiKeyService:
|
||||
def create_api_key(
|
||||
db: Session,
|
||||
user_id: str, # UUID
|
||||
name: Optional[str] = None,
|
||||
allowed_providers: Optional[List[str]] = None,
|
||||
allowed_api_formats: Optional[List[str]] = None,
|
||||
allowed_models: Optional[List[str]] = None,
|
||||
rate_limit: Optional[int] = None,
|
||||
name: str | None = None,
|
||||
allowed_providers: list[str] | None = None,
|
||||
allowed_api_formats: list[str] | None = None,
|
||||
allowed_models: list[str] | None = None,
|
||||
rate_limit: int | None = None,
|
||||
concurrent_limit: int = 5,
|
||||
expire_days: Optional[int] = None,
|
||||
expires_at: Optional[datetime] = None, # 直接传入过期时间,优先于 expire_days
|
||||
initial_balance_usd: Optional[float] = None,
|
||||
expire_days: int | None = None,
|
||||
expires_at: datetime | None = None, # 直接传入过期时间,优先于 expire_days
|
||||
initial_balance_usd: float | None = None,
|
||||
is_standalone: bool = False,
|
||||
auto_delete_on_expiry: bool = False,
|
||||
) -> tuple[ApiKey, str]:
|
||||
@@ -89,20 +89,20 @@ class ApiKeyService:
|
||||
return api_key, key # 返回密钥对象和明文密钥
|
||||
|
||||
@staticmethod
|
||||
def get_api_key(db: Session, key_id: str) -> Optional[ApiKey]: # UUID
|
||||
def get_api_key(db: Session, key_id: str) -> ApiKey | None: # UUID
|
||||
"""获取API密钥"""
|
||||
return db.query(ApiKey).filter(ApiKey.id == key_id).first()
|
||||
|
||||
@staticmethod
|
||||
def get_api_key_by_key(db: Session, key: str) -> Optional[ApiKey]:
|
||||
def get_api_key_by_key(db: Session, key: str) -> ApiKey | None:
|
||||
"""通过密钥字符串获取API密钥"""
|
||||
key_hash = ApiKey.hash_key(key)
|
||||
return db.query(ApiKey).filter(ApiKey.key_hash == key_hash).first()
|
||||
|
||||
@staticmethod
|
||||
def list_user_api_keys(
|
||||
db: Session, user_id: str, is_active: Optional[bool] = None # UUID
|
||||
) -> List[ApiKey]:
|
||||
db: Session, user_id: str, is_active: bool | None = None # UUID
|
||||
) -> list[ApiKey]:
|
||||
"""列出用户的所有API密钥(不包括独立Key)"""
|
||||
query = db.query(ApiKey).filter(
|
||||
ApiKey.user_id == user_id, ApiKey.is_standalone == False # 排除独立Key
|
||||
@@ -114,7 +114,7 @@ class ApiKeyService:
|
||||
return query.order_by(ApiKey.created_at.desc()).all()
|
||||
|
||||
@staticmethod
|
||||
def list_standalone_api_keys(db: Session, is_active: Optional[bool] = None) -> List[ApiKey]:
|
||||
def list_standalone_api_keys(db: Session, is_active: bool | None = None) -> list[ApiKey]:
|
||||
"""列出所有独立余额Key(仅管理员可用)"""
|
||||
query = db.query(ApiKey).filter(ApiKey.is_standalone == True)
|
||||
|
||||
@@ -124,7 +124,7 @@ class ApiKeyService:
|
||||
return query.order_by(ApiKey.created_at.desc()).all()
|
||||
|
||||
@staticmethod
|
||||
def update_api_key(db: Session, key_id: str, **kwargs) -> Optional[ApiKey]: # UUID
|
||||
def update_api_key(db: Session, key_id: str, **kwargs) -> ApiKey | None: # UUID
|
||||
"""更新API密钥"""
|
||||
api_key = db.query(ApiKey).filter(ApiKey.id == key_id).first()
|
||||
if not api_key:
|
||||
@@ -186,7 +186,7 @@ class ApiKeyService:
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def get_remaining_balance(api_key: ApiKey) -> Optional[float]:
|
||||
def get_remaining_balance(api_key: ApiKey) -> float | None:
|
||||
"""计算剩余余额(仅用于独立Key)
|
||||
|
||||
Returns:
|
||||
@@ -203,7 +203,7 @@ class ApiKeyService:
|
||||
return max(0, remaining) # 不能为负数
|
||||
|
||||
@staticmethod
|
||||
def check_balance(api_key: ApiKey) -> tuple[bool, Optional[float]]:
|
||||
def check_balance(api_key: ApiKey) -> tuple[bool, float | None]:
|
||||
"""检查余额限制(仅用于独立Key)
|
||||
|
||||
Returns:
|
||||
@@ -259,7 +259,7 @@ class ApiKeyService:
|
||||
return is_allowed, api_key.rate_limit - request_count
|
||||
|
||||
@staticmethod
|
||||
def add_balance(db: Session, key_id: str, amount_usd: float) -> Optional[ApiKey]:
|
||||
def add_balance(db: Session, key_id: str, amount_usd: float) -> ApiKey | None:
|
||||
"""为独立余额Key调整余额
|
||||
|
||||
Args:
|
||||
@@ -355,9 +355,9 @@ class ApiKeyService:
|
||||
def get_api_key_stats(
|
||||
db: Session,
|
||||
key_id: str, # UUID
|
||||
start_date: Optional[datetime] = None,
|
||||
end_date: Optional[datetime] = None,
|
||||
) -> Dict[str, Any]:
|
||||
start_date: datetime | None = None,
|
||||
end_date: datetime | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""获取API密钥使用统计"""
|
||||
|
||||
api_key = db.query(ApiKey).filter(ApiKey.id == key_id).first()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
用户偏好设置服务
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@@ -42,15 +41,15 @@ class PreferenceService:
|
||||
def update_preferences(
|
||||
db: Session,
|
||||
user_id: str, # UUID
|
||||
avatar_url: Optional[str] = None,
|
||||
bio: Optional[str] = None,
|
||||
default_provider_id: Optional[str] = None, # UUID
|
||||
theme: Optional[str] = None,
|
||||
language: Optional[str] = None,
|
||||
timezone: Optional[str] = None,
|
||||
email_notifications: Optional[bool] = None,
|
||||
usage_alerts: Optional[bool] = None,
|
||||
announcement_notifications: Optional[bool] = None,
|
||||
avatar_url: str | None = None,
|
||||
bio: str | None = None,
|
||||
default_provider_id: str | None = None, # UUID
|
||||
theme: str | None = None,
|
||||
language: str | None = None,
|
||||
timezone: str | None = None,
|
||||
email_notifications: bool | None = None,
|
||||
usage_alerts: bool | None = None,
|
||||
announcement_notifications: bool | None = None,
|
||||
) -> UserPreference:
|
||||
"""更新用户偏好设置"""
|
||||
preferences = PreferenceService.get_or_create_preferences(db, user_id)
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any, Dict, List, Optional
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import and_, func
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -25,15 +25,15 @@ class UserService:
|
||||
@retry_on_database_error(max_retries=3)
|
||||
def create_user(
|
||||
db: Session,
|
||||
email: Optional[str],
|
||||
email: str | None,
|
||||
username: str,
|
||||
password: str,
|
||||
role: UserRole = UserRole.USER,
|
||||
quota_usd: Optional[float] = 10.0,
|
||||
quota_usd: float | None = 10.0,
|
||||
email_verified: bool = False,
|
||||
allowed_providers: Optional[List[str]] = None,
|
||||
allowed_api_formats: Optional[List[str]] = None,
|
||||
allowed_models: Optional[List[str]] = None,
|
||||
allowed_providers: list[str] | None = None,
|
||||
allowed_api_formats: list[str] | None = None,
|
||||
allowed_models: list[str] | None = None,
|
||||
) -> User:
|
||||
"""创建新用户,quota_usd 为 None 表示无限制,email 为 None 表示无邮箱"""
|
||||
|
||||
@@ -90,7 +90,7 @@ class UserService:
|
||||
password: str,
|
||||
api_key_name: str = "默认密钥",
|
||||
role: UserRole = UserRole.USER,
|
||||
quota_usd: Optional[float] = 10.0,
|
||||
quota_usd: float | None = 10.0,
|
||||
concurrent_limit: int = 5,
|
||||
) -> tuple[User, ApiKey]:
|
||||
"""
|
||||
@@ -131,7 +131,7 @@ class UserService:
|
||||
return user, api_key, plain_key
|
||||
|
||||
@staticmethod
|
||||
def get_user(db: Session, user_id: str) -> Optional[User]:
|
||||
def get_user(db: Session, user_id: str) -> User | None:
|
||||
"""获取用户"""
|
||||
import random
|
||||
import time
|
||||
@@ -152,7 +152,7 @@ class UserService:
|
||||
raise e
|
||||
|
||||
@staticmethod
|
||||
def get_user_by_email(db: Session, email: str) -> Optional[User]:
|
||||
def get_user_by_email(db: Session, email: str) -> User | None:
|
||||
"""通过邮箱获取用户"""
|
||||
return db.query(User).filter(User.email == email).first()
|
||||
|
||||
@@ -161,9 +161,9 @@ class UserService:
|
||||
db: Session,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
role: Optional[UserRole] = None,
|
||||
is_active: Optional[bool] = None,
|
||||
) -> List[User]:
|
||||
role: UserRole | None = None,
|
||||
is_active: bool | None = None,
|
||||
) -> list[User]:
|
||||
"""列出用户"""
|
||||
query = db.query(User)
|
||||
|
||||
@@ -176,7 +176,7 @@ class UserService:
|
||||
|
||||
@staticmethod
|
||||
@transactional()
|
||||
def update_user(db: Session, user_id: str, **kwargs) -> Optional[User]:
|
||||
def update_user(db: Session, user_id: str, **kwargs) -> User | None:
|
||||
"""更新用户信息"""
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
@@ -322,8 +322,8 @@ class UserService:
|
||||
def update_user_quota(
|
||||
db: Session,
|
||||
user_id: str,
|
||||
quota_usd: Optional[float] = None,
|
||||
) -> Optional[User]:
|
||||
quota_usd: float | None = None,
|
||||
) -> User | None:
|
||||
"""更新用户配额"""
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
@@ -345,9 +345,9 @@ class UserService:
|
||||
def get_user_usage_stats(
|
||||
db: Session,
|
||||
user_id: str,
|
||||
start_date: Optional[datetime] = None,
|
||||
end_date: Optional[datetime] = None,
|
||||
) -> Dict[str, Any]:
|
||||
start_date: datetime | None = None,
|
||||
end_date: datetime | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""获取用户使用统计"""
|
||||
|
||||
query = db.query(Usage).filter(Usage.user_id == user_id)
|
||||
@@ -404,7 +404,7 @@ class UserService:
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get_user_available_models(db: Session, user: User) -> List[Model]:
|
||||
def get_user_available_models(db: Session, user: User) -> list[Model]:
|
||||
"""获取用户可用的模型
|
||||
|
||||
通过 GlobalModel + Model 关联查询用户可用模型
|
||||
|
||||
Reference in New Issue
Block a user