fix: Lint fixes of api and repositories
All checks were successful
Backend CI / test (push) Successful in 3m58s

This commit is contained in:
JSC
2025-07-31 22:29:11 +02:00
parent 7ba52ad6fc
commit 95ccb76233
4 changed files with 104 additions and 80 deletions

View File

@@ -32,7 +32,7 @@ async def get_playlist_service(
@router.get("/") @router.get("/")
async def get_all_playlists( async def get_all_playlists(
current_user: Annotated[User, Depends(get_current_active_user_flexible)], current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)],
) -> list[PlaylistResponse]: ) -> list[PlaylistResponse]:
"""Get all playlists from all users.""" """Get all playlists from all users."""
@@ -52,7 +52,7 @@ async def get_user_playlists(
@router.get("/main") @router.get("/main")
async def get_main_playlist( async def get_main_playlist(
current_user: Annotated[User, Depends(get_current_active_user_flexible)], current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)],
) -> PlaylistResponse: ) -> PlaylistResponse:
"""Get the global main playlist.""" """Get the global main playlist."""
@@ -89,7 +89,7 @@ async def create_playlist(
@router.get("/{playlist_id}") @router.get("/{playlist_id}")
async def get_playlist( async def get_playlist(
playlist_id: int, playlist_id: int,
current_user: Annotated[User, Depends(get_current_active_user_flexible)], current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)],
) -> PlaylistResponse: ) -> PlaylistResponse:
"""Get a specific playlist.""" """Get a specific playlist."""
@@ -130,7 +130,7 @@ async def delete_playlist(
@router.get("/search/{query}") @router.get("/search/{query}")
async def search_playlists( async def search_playlists(
query: str, query: str,
current_user: Annotated[User, Depends(get_current_active_user_flexible)], current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)],
) -> list[PlaylistResponse]: ) -> list[PlaylistResponse]:
"""Search all playlists by name.""" """Search all playlists by name."""
@@ -152,7 +152,7 @@ async def search_user_playlists(
@router.get("/{playlist_id}/sounds") @router.get("/{playlist_id}/sounds")
async def get_playlist_sounds( async def get_playlist_sounds(
playlist_id: int, playlist_id: int,
current_user: Annotated[User, Depends(get_current_active_user_flexible)], current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)],
) -> list[PlaylistSoundResponse]: ) -> list[PlaylistSoundResponse]:
"""Get all sounds in a playlist.""" """Get all sounds in a playlist."""
@@ -233,7 +233,7 @@ async def unset_current_playlist(
@router.get("/{playlist_id}/stats") @router.get("/{playlist_id}/stats")
async def get_playlist_stats( async def get_playlist_stats(
playlist_id: int, playlist_id: int,
current_user: Annotated[User, Depends(get_current_active_user_flexible)], current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)],
) -> PlaylistStatsResponse: ) -> PlaylistStatsResponse:
"""Get statistics for a playlist.""" """Get statistics for a playlist."""

View File

@@ -1,5 +1,7 @@
"""Socket.IO API endpoints for WebSocket management.""" """Socket.IO API endpoints for WebSocket management."""
from typing import Annotated
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from app.core.dependencies import get_current_user from app.core.dependencies import get_current_user
@@ -10,7 +12,9 @@ router = APIRouter(prefix="/socket", tags=["socket"])
@router.get("/status") @router.get("/status")
async def get_socket_status(current_user: User = Depends(get_current_user)): async def get_socket_status(
current_user: Annotated[User, Depends(get_current_user)],
) -> dict[str, int | bool]:
"""Get current socket connection status.""" """Get current socket connection status."""
connected_users = socket_manager.get_connected_users() connected_users = socket_manager.get_connected_users()
@@ -25,8 +29,8 @@ async def get_socket_status(current_user: User = Depends(get_current_user)):
async def send_message_to_user( async def send_message_to_user(
target_user_id: int, target_user_id: int,
message: str, message: str,
current_user: User = Depends(get_current_user), current_user: Annotated[User, Depends(get_current_user)],
): ) -> dict[str, int | bool | str]:
"""Send a message to a specific user via WebSocket.""" """Send a message to a specific user via WebSocket."""
success = await socket_manager.send_to_user( success = await socket_manager.send_to_user(
str(target_user_id), str(target_user_id),
@@ -48,8 +52,8 @@ async def send_message_to_user(
@router.post("/broadcast") @router.post("/broadcast")
async def broadcast_message( async def broadcast_message(
message: str, message: str,
current_user: User = Depends(get_current_user), current_user: Annotated[User, Depends(get_current_user)],
): ) -> dict[str, bool | str]:
"""Broadcast a message to all connected users.""" """Broadcast a message to all connected users."""
await socket_manager.broadcast_to_all( await socket_manager.broadcast_to_all(
"broadcast_message", "broadcast_message",

View File

@@ -5,7 +5,7 @@ from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException, Query, status from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlmodel.ext.asyncio.session import AsyncSession from sqlmodel.ext.asyncio.session import AsyncSession
from app.core.database import get_db from app.core.database import get_db, get_session_factory
from app.core.dependencies import get_current_active_user_flexible from app.core.dependencies import get_current_active_user_flexible
from app.models.credit_action import CreditActionType from app.models.credit_action import CreditActionType
from app.models.user import User from app.models.user import User
@@ -43,13 +43,11 @@ async def get_extraction_service(
def get_vlc_player() -> VLCPlayerService: def get_vlc_player() -> VLCPlayerService:
"""Get the VLC player service.""" """Get the VLC player service."""
from app.core.database import get_session_factory
return get_vlc_player_service(get_session_factory()) return get_vlc_player_service(get_session_factory())
def get_credit_service() -> CreditService: def get_credit_service() -> CreditService:
"""Get the credit service.""" """Get the credit service."""
from app.core.database import get_session_factory
return CreditService(get_session_factory()) return CreditService(get_session_factory())
@@ -76,15 +74,16 @@ async def scan_sounds(
try: try:
results = await scanner_service.scan_soundboard_directory() results = await scanner_service.scan_soundboard_directory()
return {
"message": "Sound sync completed",
"results": results,
}
except Exception as e: except Exception as e:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to sync sounds: {e!s}", detail=f"Failed to sync sounds: {e!s}",
) from e ) from e
else:
return {
"message": "Sound sync completed",
"results": results,
}
@router.post("/scan/custom") @router.post("/scan/custom")
@@ -104,10 +103,6 @@ async def scan_custom_directory(
try: try:
results = await scanner_service.scan_directory(directory, sound_type) results = await scanner_service.scan_directory(directory, sound_type)
return {
"message": f"Sync of directory '{directory}' completed",
"results": results,
}
except ValueError as e: except ValueError as e:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
@@ -118,6 +113,11 @@ async def scan_custom_directory(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to sync directory: {e!s}", detail=f"Failed to sync directory: {e!s}",
) from e ) from e
else:
return {
"message": f"Sync of directory '{directory}' completed",
"results": results,
}
# NORMALIZE # NORMALIZE
@@ -127,12 +127,12 @@ async def normalize_all_sounds(
normalizer_service: Annotated[ normalizer_service: Annotated[
SoundNormalizerService, Depends(get_sound_normalizer_service), SoundNormalizerService, Depends(get_sound_normalizer_service),
], ],
force: bool = Query( force: Annotated[bool, Query( # noqa: FBT002
False, description="Force normalization of already normalized sounds", description="Force normalization of already normalized sounds",
), )] = False,
one_pass: bool | None = Query( one_pass: Annotated[bool | None, Query(
None, description="Use one-pass normalization (overrides config)", description="Use one-pass normalization (overrides config)",
), )] = None,
) -> dict[str, NormalizationResults | str]: ) -> dict[str, NormalizationResults | str]:
"""Normalize all unnormalized sounds.""" """Normalize all unnormalized sounds."""
# Only allow admins to normalize sounds # Only allow admins to normalize sounds
@@ -147,15 +147,16 @@ async def normalize_all_sounds(
force=force, force=force,
one_pass=one_pass, one_pass=one_pass,
) )
return {
"message": "Sound normalization completed",
"results": results,
}
except Exception as e: except Exception as e:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to normalize sounds: {e!s}", detail=f"Failed to normalize sounds: {e!s}",
) from e ) from e
else:
return {
"message": "Sound normalization completed",
"results": results,
}
@router.post("/normalize/type/{sound_type}") @router.post("/normalize/type/{sound_type}")
@@ -165,12 +166,12 @@ async def normalize_sounds_by_type(
normalizer_service: Annotated[ normalizer_service: Annotated[
SoundNormalizerService, Depends(get_sound_normalizer_service), SoundNormalizerService, Depends(get_sound_normalizer_service),
], ],
force: bool = Query( force: Annotated[bool, Query( # noqa: FBT002
False, description="Force normalization of already normalized sounds", description="Force normalization of already normalized sounds",
), )] = False,
one_pass: bool | None = Query( one_pass: Annotated[bool | None, Query(
None, description="Use one-pass normalization (overrides config)", description="Use one-pass normalization (overrides config)",
), )] = None,
) -> dict[str, NormalizationResults | str]: ) -> dict[str, NormalizationResults | str]:
"""Normalize all sounds of a specific type (SDB, TTS, EXT).""" """Normalize all sounds of a specific type (SDB, TTS, EXT)."""
# Only allow admins to normalize sounds # Only allow admins to normalize sounds
@@ -194,15 +195,16 @@ async def normalize_sounds_by_type(
force=force, force=force,
one_pass=one_pass, one_pass=one_pass,
) )
return {
"message": f"Normalization of {sound_type} sounds completed",
"results": results,
}
except Exception as e: except Exception as e:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to normalize {sound_type} sounds: {e!s}", detail=f"Failed to normalize {sound_type} sounds: {e!s}",
) from e ) from e
else:
return {
"message": f"Normalization of {sound_type} sounds completed",
"results": results,
}
@router.post("/normalize/{sound_id}") @router.post("/normalize/{sound_id}")
@@ -212,12 +214,12 @@ async def normalize_sound_by_id(
normalizer_service: Annotated[ normalizer_service: Annotated[
SoundNormalizerService, Depends(get_sound_normalizer_service), SoundNormalizerService, Depends(get_sound_normalizer_service),
], ],
force: bool = Query( force: Annotated[bool, Query( # noqa: FBT002
False, description="Force normalization of already normalized sound", description="Force normalization of already normalized sound",
), )] = False,
one_pass: bool | None = Query( one_pass: Annotated[bool | None, Query(
None, description="Use one-pass normalization (overrides config)", description="Use one-pass normalization (overrides config)",
), )] = None,
) -> dict[str, str]: ) -> dict[str, str]:
"""Normalize a specific sound by ID.""" """Normalize a specific sound by ID."""
# Only allow admins to normalize sounds # Only allow admins to normalize sounds
@@ -289,11 +291,6 @@ async def create_extraction(
# Queue the extraction for background processing # Queue the extraction for background processing
await extraction_processor.queue_extraction(extraction_info["id"]) await extraction_processor.queue_extraction(extraction_info["id"])
return {
"message": "Extraction queued successfully",
"extraction": extraction_info,
}
except ValueError as e: except ValueError as e:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
@@ -304,6 +301,11 @@ async def create_extraction(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to create extraction: {e!s}", detail=f"Failed to create extraction: {e!s}",
) from e ) from e
else:
return {
"message": "Extraction queued successfully",
"extraction": extraction_info,
}
@router.get("/extract/status") @router.get("/extract/status")
@@ -324,7 +326,7 @@ async def get_extraction_processor_status(
@router.get("/extract/{extraction_id}") @router.get("/extract/{extraction_id}")
async def get_extraction( async def get_extraction(
extraction_id: int, extraction_id: int,
current_user: Annotated[User, Depends(get_current_active_user_flexible)], current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
extraction_service: Annotated[ExtractionService, Depends(get_extraction_service)], extraction_service: Annotated[ExtractionService, Depends(get_extraction_service)],
) -> ExtractionInfo: ) -> ExtractionInfo:
"""Get extraction information by ID.""" """Get extraction information by ID."""
@@ -337,8 +339,6 @@ async def get_extraction(
detail=f"Extraction {extraction_id} not found", detail=f"Extraction {extraction_id} not found",
) )
return extraction_info
except HTTPException: except HTTPException:
raise raise
except Exception as e: except Exception as e:
@@ -346,6 +346,8 @@ async def get_extraction(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to get extraction: {e!s}", detail=f"Failed to get extraction: {e!s}",
) from e ) from e
else:
return extraction_info
@router.get("/extract") @router.get("/extract")
@@ -363,15 +365,15 @@ async def get_user_extractions(
extractions = await extraction_service.get_user_extractions(current_user.id) extractions = await extraction_service.get_user_extractions(current_user.id)
return {
"extractions": extractions,
}
except Exception as e: except Exception as e:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to get extractions: {e!s}", detail=f"Failed to get extractions: {e!s}",
) from e ) from e
else:
return {
"extractions": extractions,
}
# VLC PLAYER # VLC PLAYER
@@ -403,7 +405,10 @@ async def play_sound_with_vlc(
except InsufficientCreditsError as e: except InsufficientCreditsError as e:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_402_PAYMENT_REQUIRED, status_code=status.HTTP_402_PAYMENT_REQUIRED,
detail=f"Insufficient credits: {e.required} required, {e.available} available", detail=(
f"Insufficient credits: {e.required} required, "
f"{e.available} available"
),
) from e ) from e
# Play the sound using VLC # Play the sound using VLC
@@ -423,6 +428,14 @@ async def play_sound_with_vlc(
detail="Failed to launch VLC for sound playback", detail="Failed to launch VLC for sound playback",
) )
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to play sound: {e!s}",
) from e
else:
return { return {
"message": f"Sound '{sound.name}' is now playing via VLC", "message": f"Sound '{sound.name}' is now playing via VLC",
"sound_id": sound_id, "sound_id": sound_id,
@@ -431,25 +444,16 @@ async def play_sound_with_vlc(
"credits_deducted": 1, "credits_deducted": 1,
} }
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to play sound: {e!s}",
) from e
@router.post("/vlc/stop-all") @router.post("/vlc/stop-all")
async def stop_all_vlc_instances( async def stop_all_vlc_instances(
current_user: Annotated[User, Depends(get_current_active_user_flexible)], current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001
vlc_player: Annotated[VLCPlayerService, Depends(get_vlc_player)], vlc_player: Annotated[VLCPlayerService, Depends(get_vlc_player)],
) -> dict: ) -> dict:
"""Stop all running VLC instances.""" """Stop all running VLC instances."""
try: try:
result = await vlc_player.stop_all_vlc_instances() return await vlc_player.stop_all_vlc_instances()
return result
except Exception as e: except Exception as e:
raise HTTPException( raise HTTPException(

View File

@@ -1,6 +1,6 @@
"""Base repository with common CRUD operations.""" """Base repository with common CRUD operations."""
from typing import Any, Generic, TypeVar from typing import Any, TypeVar
from sqlmodel import select from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession from sqlmodel.ext.asyncio.session import AsyncSession
@@ -13,7 +13,7 @@ ModelType = TypeVar("ModelType")
logger = get_logger(__name__) logger = get_logger(__name__)
class BaseRepository(Generic[ModelType]): class BaseRepository[ModelType]:
"""Base repository with common CRUD operations.""" """Base repository with common CRUD operations."""
def __init__(self, model: type[ModelType], session: AsyncSession) -> None: def __init__(self, model: type[ModelType], session: AsyncSession) -> None:
@@ -42,7 +42,9 @@ class BaseRepository(Generic[ModelType]):
result = await self.session.exec(statement) result = await self.session.exec(statement)
return result.first() return result.first()
except Exception: except Exception:
logger.exception("Failed to get %s by ID: %s", self.model.__name__, entity_id) logger.exception(
"Failed to get %s by ID: %s", self.model.__name__, entity_id,
)
raise raise
async def get_all( async def get_all(
@@ -83,12 +85,17 @@ class BaseRepository(Generic[ModelType]):
self.session.add(entity) self.session.add(entity)
await self.session.commit() await self.session.commit()
await self.session.refresh(entity) await self.session.refresh(entity)
logger.info("Created new %s with ID: %s", self.model.__name__, getattr(entity, "id", "unknown"))
return entity
except Exception: except Exception:
await self.session.rollback() await self.session.rollback()
logger.exception("Failed to create %s", self.model.__name__) logger.exception("Failed to create %s", self.model.__name__)
raise raise
else:
logger.info(
"Created new %s with ID: %s",
self.model.__name__,
getattr(entity, "id", "unknown"),
)
return entity
async def update(self, entity: ModelType, update_data: dict[str, Any]) -> ModelType: async def update(self, entity: ModelType, update_data: dict[str, Any]) -> ModelType:
"""Update an entity. """Update an entity.
@@ -108,12 +115,17 @@ class BaseRepository(Generic[ModelType]):
self.session.add(entity) self.session.add(entity)
await self.session.commit() await self.session.commit()
await self.session.refresh(entity) await self.session.refresh(entity)
logger.info("Updated %s with ID: %s", self.model.__name__, getattr(entity, "id", "unknown"))
return entity
except Exception: except Exception:
await self.session.rollback() await self.session.rollback()
logger.exception("Failed to update %s", self.model.__name__) logger.exception("Failed to update %s", self.model.__name__)
raise raise
else:
logger.info(
"Updated %s with ID: %s",
self.model.__name__,
getattr(entity, "id", "unknown"),
)
return entity
async def delete(self, entity: ModelType) -> None: async def delete(self, entity: ModelType) -> None:
"""Delete an entity. """Delete an entity.
@@ -125,7 +137,11 @@ class BaseRepository(Generic[ModelType]):
try: try:
await self.session.delete(entity) await self.session.delete(entity)
await self.session.commit() await self.session.commit()
logger.info("Deleted %s with ID: %s", self.model.__name__, getattr(entity, "id", "unknown")) logger.info(
"Deleted %s with ID: %s",
self.model.__name__,
getattr(entity, "id", "unknown"),
)
except Exception: except Exception:
await self.session.rollback() await self.session.rollback()
logger.exception("Failed to delete %s", self.model.__name__) logger.exception("Failed to delete %s", self.model.__name__)