style: normalize python formatting gates

This commit is contained in:
Xiaoxia AI
2026-06-21 06:52:19 +08:00
parent 0809a079c5
commit bfbaddbd9a
129 changed files with 3024 additions and 2485 deletions
+1 -3
View File
@@ -5,6 +5,4 @@ package is kept only as a migration marker; do not import it in application,
API, worker, or new tests.
"""
raise RuntimeError(
"packages.adapters.postgres is deprecated; use packages.adapters.sqlalchemy_impl instead"
)
raise RuntimeError("packages.adapters.postgres is deprecated; use packages.adapters.sqlalchemy_impl instead")
+19 -5
View File
@@ -1,6 +1,7 @@
"""
Asset PostgreSQL Repository 实现
"""
import json
from sqlalchemy import and_, func, select
@@ -24,7 +25,7 @@ class PostgresAssetRepository(AssetRepository):
project_id=asset.project_id,
asset_library_id=asset.library_id,
name=asset.name,
file_type=asset.mime_type.split("/")[0] if "/" in asset.mime_type else asset.mime_type,
file_type=(asset.mime_type.split("/")[0] if "/" in asset.mime_type else asset.mime_type),
file_size=asset.file_size,
file_url=asset.storage_key,
thumbnail_url=asset.thumbnail_url,
@@ -35,7 +36,7 @@ class PostgresAssetRepository(AssetRepository):
codec=asset.codec,
status=asset.status.value,
classification_status=asset.classification_status.value,
classification_result=json.dumps(asset.metadata) if asset.metadata else None,
classification_result=(json.dumps(asset.metadata) if asset.metadata else None),
quality_score=asset.quality_score,
uploaded_by_user_id=asset.uploaded_by_user_id or "system",
created_at=asset.created_at,
@@ -59,7 +60,12 @@ class PostgresAssetRepository(AssetRepository):
) -> list[Asset]:
result = await self.session.execute(
select(AssetModel)
.where(and_(AssetModel.project_id == project_id, AssetModel.workspace_id == workspace_id))
.where(
and_(
AssetModel.project_id == project_id,
AssetModel.workspace_id == workspace_id,
)
)
.order_by(AssetModel.created_at.desc())
.offset(skip)
.limit(limit)
@@ -75,7 +81,12 @@ class PostgresAssetRepository(AssetRepository):
) -> list[Asset]:
result = await self.session.execute(
select(AssetModel)
.where(and_(AssetModel.asset_library_id == library_id, AssetModel.workspace_id == workspace_id))
.where(
and_(
AssetModel.asset_library_id == library_id,
AssetModel.workspace_id == workspace_id,
)
)
.order_by(AssetModel.created_at.desc())
.offset(skip)
.limit(limit)
@@ -118,7 +129,10 @@ class PostgresAssetRepository(AssetRepository):
async def count_by_project(self, project_id: str, workspace_id: str) -> int:
result = await self.session.execute(
select(func.count(AssetModel.id)).where(
and_(AssetModel.project_id == project_id, AssetModel.workspace_id == workspace_id)
and_(
AssetModel.project_id == project_id,
AssetModel.workspace_id == workspace_id,
)
)
)
return result.scalar() or 0
+12 -10
View File
@@ -1,7 +1,9 @@
"""
数据库连接池管理
"""
from typing import Optional
import psycopg2
from psycopg2 import pool
from psycopg2.extras import RealDictCursor
@@ -9,15 +11,15 @@ from psycopg2.extras import RealDictCursor
class DatabaseConnectionPool:
"""PostgreSQL 连接池"""
_instance: Optional['DatabaseConnectionPool'] = None
_instance: Optional["DatabaseConnectionPool"] = None
_pool: Optional[pool.ThreadedConnectionPool] = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def initialize(
self,
connection_string: str,
@@ -31,18 +33,18 @@ class DatabaseConnectionPool:
maxconn=maxconn,
dsn=connection_string,
)
def get_connection(self):
"""从连接池获取连接"""
if self._pool is None:
raise RuntimeError("Connection pool not initialized")
return self._pool.getconn()
def put_connection(self, conn):
"""将连接归还到连接池"""
if self._pool is not None:
self._pool.putconn(conn)
def close_all(self):
"""关闭所有连接"""
if self._pool is not None:
@@ -56,17 +58,17 @@ db_pool = DatabaseConnectionPool()
class PooledConnection:
"""连接池上下文管理器"""
def __init__(self, cursor_factory=RealDictCursor):
self.cursor_factory = cursor_factory
self.conn = None
def __enter__(self):
self.conn = db_pool.get_connection()
if self.cursor_factory:
self.conn.cursor_factory = self.cursor_factory
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
if self.conn:
if exc_type is not None:
@@ -1,7 +1,9 @@
"""
PostgreSQL Project Repository 实现
"""
from typing import Optional, List
from typing import List, Optional
import psycopg2
from psycopg2.extras import RealDictCursor
@@ -11,21 +13,23 @@ from packages.ports.project_repository import ProjectRepository
class PostgresProjectRepository(ProjectRepository):
"""Project 仓储 PostgreSQL 实现"""
def __init__(self, connection_string: str):
self.connection_string = connection_string
def _get_connection(self):
"""获取数据库连接(使用连接池)"""
from packages.adapters.postgres.connection_pool import PooledConnection
return PooledConnection()
def save(self, project: Project) -> None:
"""保存项目"""
conn = self._get_connection()
try:
with conn.cursor() as cur:
cur.execute("""
cur.execute(
"""
INSERT INTO projects (
id, workspace_id, name, description, status,
created_by, created_at, updated_at
@@ -38,20 +42,22 @@ class PostgresProjectRepository(ProjectRepository):
description = EXCLUDED.description,
status = EXCLUDED.status,
updated_at = EXCLUDED.updated_at
""", {
"id": project.id,
"workspace_id": project.workspace_id,
"name": project.name,
"description": project.description,
"status": project.status,
"created_by": project.created_by,
"created_at": project.created_at,
"updated_at": project.updated_at,
})
""",
{
"id": project.id,
"workspace_id": project.workspace_id,
"name": project.name,
"description": project.description,
"status": project.status,
"created_by": project.created_by,
"created_at": project.created_at,
"updated_at": project.updated_at,
},
)
conn.commit()
finally:
conn.close()
def find_by_id(self, project_id: str) -> Optional[Project]:
"""根据 ID 查找项目"""
conn = self._get_connection()
@@ -62,7 +68,7 @@ class PostgresProjectRepository(ProjectRepository):
return self._row_to_project(row) if row else None
finally:
conn.close()
def find_by_workspace(self, workspace_id: str) -> List[Project]:
"""根据 workspace 查找所有项目"""
conn = self._get_connection()
@@ -70,13 +76,13 @@ class PostgresProjectRepository(ProjectRepository):
with conn.cursor() as cur:
cur.execute(
"SELECT * FROM projects WHERE workspace_id = %s ORDER BY created_at DESC",
(workspace_id,)
(workspace_id,),
)
rows = cur.fetchall()
return [self._row_to_project(row) for row in rows]
finally:
conn.close()
def find_by_creator(self, user_id: str) -> List[Project]:
"""根据创建者查找项目"""
conn = self._get_connection()
@@ -84,13 +90,13 @@ class PostgresProjectRepository(ProjectRepository):
with conn.cursor() as cur:
cur.execute(
"SELECT * FROM projects WHERE created_by = %s ORDER BY created_at DESC",
(user_id,)
(user_id,),
)
rows = cur.fetchall()
return [self._row_to_project(row) for row in rows]
finally:
conn.close()
def count_by_workspace(self, workspace_id: str) -> int:
"""统计 workspace 的项目数量"""
conn = self._get_connection()
@@ -98,12 +104,12 @@ class PostgresProjectRepository(ProjectRepository):
with conn.cursor() as cur:
cur.execute(
"SELECT COUNT(*) FROM projects WHERE workspace_id = %s",
(workspace_id,)
(workspace_id,),
)
return cur.fetchone()["count"]
finally:
conn.close()
def delete(self, project_id: str) -> bool:
"""删除项目"""
conn = self._get_connection()
@@ -115,7 +121,7 @@ class PostgresProjectRepository(ProjectRepository):
return deleted
finally:
conn.close()
def _row_to_project(self, row: dict) -> Project:
"""将数据库行转换为 Project 对象"""
return Project(
+37 -31
View File
@@ -1,10 +1,12 @@
"""
PostgreSQL User Repository 实现
"""
from datetime import datetime
from typing import Optional
import psycopg2
from psycopg2.extras import RealDictCursor
from datetime import datetime
from packages.domain.entities import User
from packages.ports.user_repository import UserRepository
@@ -12,22 +14,24 @@ from packages.ports.user_repository import UserRepository
class PostgresUserRepository(UserRepository):
"""User 仓储 PostgreSQL 实现"""
def __init__(self, connection_string: str):
self.connection_string = connection_string
def _get_connection(self):
"""获取数据库连接(使用连接池)"""
from packages.adapters.postgres.connection_pool import PooledConnection
return PooledConnection()
def save(self, user: User) -> None:
"""保存用户"""
conn = self._get_connection()
try:
with conn.cursor() as cur:
# Upsert (插入或更新)
cur.execute("""
cur.execute(
"""
INSERT INTO users (
id, email, display_name, username, password_hash,
email_verified, email_verification_token,
@@ -50,24 +54,26 @@ class PostgresUserRepository(UserRepository):
password_reset_expires_at = EXCLUDED.password_reset_expires_at,
last_login_at = EXCLUDED.last_login_at,
last_login_ip = EXCLUDED.last_login_ip
""", {
"id": user.id,
"email": user.email,
"display_name": user.display_name,
"username": user.username,
"password_hash": user.password_hash,
"email_verified": user.email_verified,
"email_verification_token": user.email_verification_token,
"password_reset_token": user.password_reset_token,
"password_reset_expires_at": user.password_reset_expires_at,
"last_login_at": user.last_login_at,
"last_login_ip": user.last_login_ip,
"created_at": user.created_at,
})
""",
{
"id": user.id,
"email": user.email,
"display_name": user.display_name,
"username": user.username,
"password_hash": user.password_hash,
"email_verified": user.email_verified,
"email_verification_token": user.email_verification_token,
"password_reset_token": user.password_reset_token,
"password_reset_expires_at": user.password_reset_expires_at,
"last_login_at": user.last_login_at,
"last_login_ip": user.last_login_ip,
"created_at": user.created_at,
},
)
conn.commit()
finally:
conn.close()
def find_by_id(self, user_id: str) -> Optional[User]:
"""根据 ID 查找用户"""
conn = self._get_connection()
@@ -75,13 +81,13 @@ class PostgresUserRepository(UserRepository):
with conn.cursor() as cur:
cur.execute("SELECT * FROM users WHERE id = %s", (user_id,))
row = cur.fetchone()
if row:
return self._row_to_user(row)
return None
finally:
conn.close()
def find_by_email(self, email: str) -> Optional[User]:
"""根据邮箱查找用户"""
conn = self._get_connection()
@@ -89,13 +95,13 @@ class PostgresUserRepository(UserRepository):
with conn.cursor() as cur:
cur.execute("SELECT * FROM users WHERE email = %s", (email.lower(),))
row = cur.fetchone()
if row:
return self._row_to_user(row)
return None
finally:
conn.close()
def find_by_username(self, username: str) -> Optional[User]:
"""根据用户名查找用户"""
conn = self._get_connection()
@@ -103,13 +109,13 @@ class PostgresUserRepository(UserRepository):
with conn.cursor() as cur:
cur.execute("SELECT * FROM users WHERE username = %s", (username.lower(),))
row = cur.fetchone()
if row:
return self._row_to_user(row)
return None
finally:
conn.close()
def find_by_verification_token(self, token: str) -> Optional[User]:
"""根据邮箱验证令牌查找用户"""
conn = self._get_connection()
@@ -117,13 +123,13 @@ class PostgresUserRepository(UserRepository):
with conn.cursor() as cur:
cur.execute("SELECT * FROM users WHERE email_verification_token = %s", (token,))
row = cur.fetchone()
if row:
return self._row_to_user(row)
return None
finally:
conn.close()
def find_by_password_reset_token(self, token: str) -> Optional[User]:
"""根据密码重置令牌查找用户"""
conn = self._get_connection()
@@ -131,13 +137,13 @@ class PostgresUserRepository(UserRepository):
with conn.cursor() as cur:
cur.execute("SELECT * FROM users WHERE password_reset_token = %s", (token,))
row = cur.fetchone()
if row:
return self._row_to_user(row)
return None
finally:
conn.close()
def delete(self, user_id: str) -> bool:
"""删除用户"""
conn = self._get_connection()
@@ -149,7 +155,7 @@ class PostgresUserRepository(UserRepository):
return deleted
finally:
conn.close()
def _row_to_user(self, row: dict) -> User:
"""将数据库行转换为 User 对象"""
return User(
@@ -1,7 +1,9 @@
"""
PostgreSQL WorkspaceInvitation Repository 实现
"""
from typing import Optional, List
from typing import List, Optional
import psycopg2
from psycopg2.extras import RealDictCursor
@@ -11,21 +13,23 @@ from packages.ports.workspace_invitation_repository import WorkspaceInvitationRe
class PostgresWorkspaceInvitationRepository(WorkspaceInvitationRepository):
"""WorkspaceInvitation 仓储 PostgreSQL 实现"""
def __init__(self, connection_string: str):
self.connection_string = connection_string
def _get_connection(self):
"""获取数据库连接(使用连接池)"""
from packages.adapters.postgres.connection_pool import PooledConnection
return PooledConnection()
def save(self, invitation: WorkspaceInvitation) -> None:
"""保存邀请"""
conn = self._get_connection()
try:
with conn.cursor() as cur:
cur.execute("""
cur.execute(
"""
INSERT INTO workspace_invitations (
id, workspace_id, email, role, token,
invited_by, expires_at, status, created_at
@@ -35,32 +39,37 @@ class PostgresWorkspaceInvitationRepository(WorkspaceInvitationRepository):
)
ON CONFLICT (id) DO UPDATE SET
status = EXCLUDED.status
""", {
"id": invitation.id,
"workspace_id": invitation.workspace_id,
"email": invitation.email,
"role": invitation.role,
"token": invitation.token,
"invited_by": invitation.invited_by,
"expires_at": invitation.expires_at,
"status": invitation.status,
"created_at": invitation.created_at,
})
""",
{
"id": invitation.id,
"workspace_id": invitation.workspace_id,
"email": invitation.email,
"role": invitation.role,
"token": invitation.token,
"invited_by": invitation.invited_by,
"expires_at": invitation.expires_at,
"status": invitation.status,
"created_at": invitation.created_at,
},
)
conn.commit()
finally:
conn.close()
def find_by_id(self, invitation_id: str) -> Optional[WorkspaceInvitation]:
"""根据 ID 查找邀请"""
conn = self._get_connection()
try:
with conn.cursor() as cur:
cur.execute("SELECT * FROM workspace_invitations WHERE id = %s", (invitation_id,))
cur.execute(
"SELECT * FROM workspace_invitations WHERE id = %s",
(invitation_id,),
)
row = cur.fetchone()
return self._row_to_invitation(row) if row else None
finally:
conn.close()
def find_by_token(self, token: str) -> Optional[WorkspaceInvitation]:
"""根据 token 查找邀请"""
conn = self._get_connection()
@@ -71,7 +80,7 @@ class PostgresWorkspaceInvitationRepository(WorkspaceInvitationRepository):
return self._row_to_invitation(row) if row else None
finally:
conn.close()
def find_by_email(self, email: str) -> List[WorkspaceInvitation]:
"""根据邮箱查找所有邀请"""
conn = self._get_connection()
@@ -79,28 +88,31 @@ class PostgresWorkspaceInvitationRepository(WorkspaceInvitationRepository):
with conn.cursor() as cur:
cur.execute(
"SELECT * FROM workspace_invitations WHERE email = %s ORDER BY created_at DESC",
(email,)
(email,),
)
rows = cur.fetchall()
return [self._row_to_invitation(row) for row in rows]
finally:
conn.close()
def find_pending_by_email(self, email: str) -> List[WorkspaceInvitation]:
"""查找邮箱的待处理邀请"""
conn = self._get_connection()
try:
with conn.cursor() as cur:
cur.execute("""
cur.execute(
"""
SELECT * FROM workspace_invitations
WHERE email = %s AND status = 'pending' AND expires_at > NOW()
ORDER BY created_at DESC
""", (email,))
""",
(email,),
)
rows = cur.fetchall()
return [self._row_to_invitation(row) for row in rows]
finally:
conn.close()
def delete(self, invitation_id: str) -> bool:
"""删除邀请"""
conn = self._get_connection()
@@ -112,7 +124,7 @@ class PostgresWorkspaceInvitationRepository(WorkspaceInvitationRepository):
return deleted
finally:
conn.close()
def _row_to_invitation(self, row: dict) -> WorkspaceInvitation:
"""将数据库行转换为 WorkspaceInvitation 对象"""
return WorkspaceInvitation(
@@ -1,7 +1,9 @@
"""
PostgreSQL WorkspaceMember Repository 实现
"""
from typing import Optional, List
from typing import List, Optional
import psycopg2
from psycopg2.extras import RealDictCursor
@@ -11,21 +13,23 @@ from packages.ports.workspace_member_repository import WorkspaceMemberRepository
class PostgresWorkspaceMemberRepository(WorkspaceMemberRepository):
"""WorkspaceMember 仓储 PostgreSQL 实现"""
def __init__(self, connection_string: str):
self.connection_string = connection_string
def _get_connection(self):
"""获取数据库连接(使用连接池)"""
from packages.adapters.postgres.connection_pool import PooledConnection
return PooledConnection()
def save(self, member: WorkspaceMember) -> None:
"""保存成员"""
conn = self._get_connection()
try:
with conn.cursor() as cur:
cur.execute("""
cur.execute(
"""
INSERT INTO workspace_members (
id, workspace_id, user_id, role, invited_by, joined_at
) VALUES (
@@ -34,18 +38,20 @@ class PostgresWorkspaceMemberRepository(WorkspaceMemberRepository):
)
ON CONFLICT (workspace_id, user_id) DO UPDATE SET
role = EXCLUDED.role
""", {
"id": member.id,
"workspace_id": member.workspace_id,
"user_id": member.user_id,
"role": member.role,
"invited_by": member.invited_by,
"joined_at": member.joined_at,
})
""",
{
"id": member.id,
"workspace_id": member.workspace_id,
"user_id": member.user_id,
"role": member.role,
"invited_by": member.invited_by,
"joined_at": member.joined_at,
},
)
conn.commit()
finally:
conn.close()
def find_by_id(self, member_id: str) -> Optional[WorkspaceMember]:
"""根据 ID 查找成员"""
conn = self._get_connection()
@@ -56,7 +62,7 @@ class PostgresWorkspaceMemberRepository(WorkspaceMemberRepository):
return self._row_to_member(row) if row else None
finally:
conn.close()
def find_by_workspace_and_user(
self,
workspace_id: str,
@@ -68,13 +74,13 @@ class PostgresWorkspaceMemberRepository(WorkspaceMemberRepository):
with conn.cursor() as cur:
cur.execute(
"SELECT * FROM workspace_members WHERE workspace_id = %s AND user_id = %s",
(workspace_id, user_id)
(workspace_id, user_id),
)
row = cur.fetchone()
return self._row_to_member(row) if row else None
finally:
conn.close()
def find_by_user(self, user_id: str) -> List[WorkspaceMember]:
"""查找用户的所有成员记录"""
conn = self._get_connection()
@@ -82,13 +88,13 @@ class PostgresWorkspaceMemberRepository(WorkspaceMemberRepository):
with conn.cursor() as cur:
cur.execute(
"SELECT * FROM workspace_members WHERE user_id = %s ORDER BY joined_at DESC",
(user_id,)
(user_id,),
)
rows = cur.fetchall()
return [self._row_to_member(row) for row in rows]
finally:
conn.close()
def find_by_workspace(self, workspace_id: str) -> List[WorkspaceMember]:
"""查找 workspace 的所有成员"""
conn = self._get_connection()
@@ -96,13 +102,13 @@ class PostgresWorkspaceMemberRepository(WorkspaceMemberRepository):
with conn.cursor() as cur:
cur.execute(
"SELECT * FROM workspace_members WHERE workspace_id = %s ORDER BY joined_at",
(workspace_id,)
(workspace_id,),
)
rows = cur.fetchall()
return [self._row_to_member(row) for row in rows]
finally:
conn.close()
def count_by_workspace(self, workspace_id: str) -> int:
"""统计 workspace 的成员数量"""
conn = self._get_connection()
@@ -110,12 +116,12 @@ class PostgresWorkspaceMemberRepository(WorkspaceMemberRepository):
with conn.cursor() as cur:
cur.execute(
"SELECT COUNT(*) FROM workspace_members WHERE workspace_id = %s",
(workspace_id,)
(workspace_id,),
)
return cur.fetchone()["count"]
finally:
conn.close()
def delete(self, member_id: str) -> bool:
"""删除成员"""
conn = self._get_connection()
@@ -127,7 +133,7 @@ class PostgresWorkspaceMemberRepository(WorkspaceMemberRepository):
return deleted
finally:
conn.close()
def _row_to_member(self, row: dict) -> WorkspaceMember:
"""将数据库行转换为 WorkspaceMember 对象"""
return WorkspaceMember(
@@ -1,7 +1,9 @@
"""
PostgreSQL Workspace Repository 实现
"""
from typing import Optional
import psycopg2
from psycopg2.extras import RealDictCursor
@@ -11,21 +13,23 @@ from packages.ports.workspace_repository import WorkspaceRepository
class PostgresWorkspaceRepository(WorkspaceRepository):
"""Workspace 仓储 PostgreSQL 实现"""
def __init__(self, connection_string: str):
self.connection_string = connection_string
def _get_connection(self):
"""获取数据库连接(使用连接池)"""
from packages.adapters.postgres.connection_pool import PooledConnection
return PooledConnection()
def save(self, workspace: Workspace) -> None:
"""保存工作空间"""
conn = self._get_connection()
try:
with conn.cursor() as cur:
cur.execute("""
cur.execute(
"""
INSERT INTO workspaces (
id, name, owner_user_id, subscription_plan,
subscription_status, subscription_expires_at,
@@ -43,22 +47,24 @@ class PostgresWorkspaceRepository(WorkspaceRepository):
max_projects = EXCLUDED.max_projects,
max_storage_gb = EXCLUDED.max_storage_gb,
used_storage_gb = EXCLUDED.used_storage_gb
""", {
"id": workspace.id,
"name": workspace.name,
"owner_user_id": workspace.owner_user_id,
"subscription_plan": workspace.subscription_plan,
"subscription_status": workspace.subscription_status,
"subscription_expires_at": workspace.subscription_expires_at,
"max_projects": workspace.max_projects,
"max_storage_gb": workspace.max_storage_gb,
"used_storage_gb": workspace.used_storage_gb,
"created_at": workspace.created_at,
})
""",
{
"id": workspace.id,
"name": workspace.name,
"owner_user_id": workspace.owner_user_id,
"subscription_plan": workspace.subscription_plan,
"subscription_status": workspace.subscription_status,
"subscription_expires_at": workspace.subscription_expires_at,
"max_projects": workspace.max_projects,
"max_storage_gb": workspace.max_storage_gb,
"used_storage_gb": workspace.used_storage_gb,
"created_at": workspace.created_at,
},
)
conn.commit()
finally:
conn.close()
def find_by_id(self, workspace_id: str) -> Optional[Workspace]:
"""根据 ID 查找工作空间"""
conn = self._get_connection()
@@ -66,13 +72,13 @@ class PostgresWorkspaceRepository(WorkspaceRepository):
with conn.cursor() as cur:
cur.execute("SELECT * FROM workspaces WHERE id = %s", (workspace_id,))
row = cur.fetchone()
if row:
return self._row_to_workspace(row)
return None
finally:
conn.close()
def delete(self, workspace_id: str) -> bool:
"""删除工作空间"""
conn = self._get_connection()
@@ -84,7 +90,7 @@ class PostgresWorkspaceRepository(WorkspaceRepository):
return deleted
finally:
conn.close()
def _row_to_workspace(self, row: dict) -> Workspace:
"""将数据库行转换为 Workspace 对象"""
return Workspace(