Refactor test files for improved readability and consistency
- Removed unnecessary blank lines and adjusted formatting in test files. - Ensured consistent use of commas in function calls and assertions across various test cases. - Updated import statements for better organization and clarity. - Enhanced mock setups in tests for better isolation and reliability. - Improved assertions to follow a consistent style for better readability.
This commit is contained in:
@@ -30,7 +30,7 @@ class InsufficientCreditsError(Exception):
|
||||
self.required = required
|
||||
self.available = available
|
||||
super().__init__(
|
||||
f"Insufficient credits: {required} required, {available} available"
|
||||
f"Insufficient credits: {required} required, {available} available",
|
||||
)
|
||||
|
||||
|
||||
@@ -138,10 +138,10 @@ class CreditService:
|
||||
|
||||
"""
|
||||
action = get_credit_action(action_type)
|
||||
|
||||
|
||||
# Only deduct if action requires success and was successful, or doesn't require success
|
||||
should_deduct = (action.requires_success and success) or not action.requires_success
|
||||
|
||||
|
||||
if not should_deduct:
|
||||
logger.info(
|
||||
"Skipping credit deduction for user %s: action %s failed and requires success",
|
||||
@@ -150,7 +150,7 @@ class CreditService:
|
||||
)
|
||||
# Still create a transaction record for auditing
|
||||
return await self._create_transaction_record(
|
||||
user_id, action, 0, success, metadata
|
||||
user_id, action, 0, success, metadata,
|
||||
)
|
||||
|
||||
session = self.db_session_factory()
|
||||
@@ -380,4 +380,4 @@ class CreditService:
|
||||
raise ValueError(msg)
|
||||
return user.credits
|
||||
finally:
|
||||
await session.close()
|
||||
await session.close()
|
||||
|
||||
@@ -10,7 +10,6 @@ from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.logging import get_logger
|
||||
from app.models.extraction import Extraction
|
||||
from app.models.sound import Sound
|
||||
from app.repositories.extraction import ExtractionRepository
|
||||
from app.repositories.sound import SoundRepository
|
||||
@@ -155,7 +154,7 @@ class ExtractionService:
|
||||
|
||||
# Check if extraction already exists for this service
|
||||
existing = await self.extraction_repo.get_by_service_and_id(
|
||||
service_info["service"], service_info["service_id"]
|
||||
service_info["service"], service_info["service_id"],
|
||||
)
|
||||
if existing and existing.id != extraction_id:
|
||||
error_msg = (
|
||||
@@ -180,7 +179,7 @@ class ExtractionService:
|
||||
|
||||
# Extract audio and thumbnail
|
||||
audio_file, thumbnail_file = await self._extract_media(
|
||||
extraction_id, extraction_url
|
||||
extraction_id, extraction_url,
|
||||
)
|
||||
|
||||
# Move files to final locations
|
||||
@@ -238,7 +237,7 @@ class ExtractionService:
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
logger.exception(
|
||||
"Failed to process extraction %d: %s", extraction_id, error_msg
|
||||
"Failed to process extraction %d: %s", extraction_id, error_msg,
|
||||
)
|
||||
|
||||
# Update extraction with error
|
||||
@@ -262,14 +261,14 @@ class ExtractionService:
|
||||
}
|
||||
|
||||
async def _extract_media(
|
||||
self, extraction_id: int, extraction_url: str
|
||||
self, extraction_id: int, extraction_url: str,
|
||||
) -> tuple[Path, Path | None]:
|
||||
"""Extract audio and thumbnail using yt-dlp."""
|
||||
temp_dir = Path(settings.EXTRACTION_TEMP_DIR)
|
||||
|
||||
# Create unique filename based on extraction ID
|
||||
output_template = str(
|
||||
temp_dir / f"extraction_{extraction_id}_%(title)s.%(ext)s"
|
||||
temp_dir / f"extraction_{extraction_id}_%(title)s.%(ext)s",
|
||||
)
|
||||
|
||||
# Configure yt-dlp options
|
||||
@@ -304,8 +303,8 @@ class ExtractionService:
|
||||
# Find the extracted files
|
||||
audio_files = list(
|
||||
temp_dir.glob(
|
||||
f"extraction_{extraction_id}_*.{settings.EXTRACTION_AUDIO_FORMAT}"
|
||||
)
|
||||
f"extraction_{extraction_id}_*.{settings.EXTRACTION_AUDIO_FORMAT}",
|
||||
),
|
||||
)
|
||||
thumbnail_files = (
|
||||
list(temp_dir.glob(f"extraction_{extraction_id}_*.webp"))
|
||||
@@ -342,7 +341,7 @@ class ExtractionService:
|
||||
"""Move extracted files to their final locations."""
|
||||
# Generate clean filename based on title and service
|
||||
safe_title = self._sanitize_filename(
|
||||
title or f"{service or 'unknown'}_{service_id or 'unknown'}"
|
||||
title or f"{service or 'unknown'}_{service_id or 'unknown'}",
|
||||
)
|
||||
|
||||
# Move audio file
|
||||
|
||||
@@ -46,9 +46,9 @@ class ExtractionProcessor:
|
||||
if self.processor_task and not self.processor_task.done():
|
||||
try:
|
||||
await asyncio.wait_for(self.processor_task, timeout=30.0)
|
||||
except asyncio.TimeoutError:
|
||||
except TimeoutError:
|
||||
logger.warning(
|
||||
"Extraction processor did not stop gracefully, cancelling..."
|
||||
"Extraction processor did not stop gracefully, cancelling...",
|
||||
)
|
||||
self.processor_task.cancel()
|
||||
try:
|
||||
@@ -66,7 +66,7 @@ class ExtractionProcessor:
|
||||
# The processor will pick it up on the next cycle
|
||||
else:
|
||||
logger.warning(
|
||||
"Extraction %d is already being processed", extraction_id
|
||||
"Extraction %d is already being processed", extraction_id,
|
||||
)
|
||||
|
||||
async def _process_queue(self) -> None:
|
||||
@@ -81,7 +81,7 @@ class ExtractionProcessor:
|
||||
try:
|
||||
await asyncio.wait_for(self.shutdown_event.wait(), timeout=5.0)
|
||||
break # Shutdown requested
|
||||
except asyncio.TimeoutError:
|
||||
except TimeoutError:
|
||||
continue # Continue processing
|
||||
|
||||
except Exception as e:
|
||||
@@ -90,7 +90,7 @@ class ExtractionProcessor:
|
||||
try:
|
||||
await asyncio.wait_for(self.shutdown_event.wait(), timeout=10.0)
|
||||
break # Shutdown requested
|
||||
except asyncio.TimeoutError:
|
||||
except TimeoutError:
|
||||
continue
|
||||
|
||||
logger.info("Extraction queue processor stopped")
|
||||
@@ -125,13 +125,13 @@ class ExtractionProcessor:
|
||||
|
||||
# Start processing this extraction in the background
|
||||
task = asyncio.create_task(
|
||||
self._process_single_extraction(extraction_id)
|
||||
self._process_single_extraction(extraction_id),
|
||||
)
|
||||
task.add_done_callback(
|
||||
lambda t, eid=extraction_id: self._on_extraction_completed(
|
||||
eid,
|
||||
t,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
logger.info(
|
||||
|
||||
@@ -49,7 +49,7 @@ class PlaylistService:
|
||||
if not main_playlist:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Main playlist not found. Make sure to run database seeding."
|
||||
detail="Main playlist not found. Make sure to run database seeding.",
|
||||
)
|
||||
|
||||
return main_playlist
|
||||
@@ -179,7 +179,7 @@ class PlaylistService:
|
||||
return await self.playlist_repo.get_playlist_sounds(playlist_id)
|
||||
|
||||
async def add_sound_to_playlist(
|
||||
self, playlist_id: int, sound_id: int, user_id: int, position: int | None = None
|
||||
self, playlist_id: int, sound_id: int, user_id: int, position: int | None = None,
|
||||
) -> None:
|
||||
"""Add a sound to a playlist."""
|
||||
# Verify playlist exists
|
||||
@@ -202,11 +202,11 @@ class PlaylistService:
|
||||
|
||||
await self.playlist_repo.add_sound_to_playlist(playlist_id, sound_id, position)
|
||||
logger.info(
|
||||
"Added sound %s to playlist %s for user %s", sound_id, playlist_id, user_id
|
||||
"Added sound %s to playlist %s for user %s", sound_id, playlist_id, user_id,
|
||||
)
|
||||
|
||||
async def remove_sound_from_playlist(
|
||||
self, playlist_id: int, sound_id: int, user_id: int
|
||||
self, playlist_id: int, sound_id: int, user_id: int,
|
||||
) -> None:
|
||||
"""Remove a sound from a playlist."""
|
||||
# Verify playlist exists
|
||||
@@ -228,7 +228,7 @@ class PlaylistService:
|
||||
)
|
||||
|
||||
async def reorder_playlist_sounds(
|
||||
self, playlist_id: int, user_id: int, sound_positions: list[tuple[int, int]]
|
||||
self, playlist_id: int, user_id: int, sound_positions: list[tuple[int, int]],
|
||||
) -> None:
|
||||
"""Reorder sounds in a playlist."""
|
||||
# Verify playlist exists
|
||||
@@ -262,7 +262,7 @@ class PlaylistService:
|
||||
await self._unset_current_playlist(user_id)
|
||||
await self._set_main_as_current(user_id)
|
||||
logger.info(
|
||||
"Unset current playlist and set main as current for user %s", user_id
|
||||
"Unset current playlist and set main as current for user %s", user_id,
|
||||
)
|
||||
|
||||
async def get_playlist_stats(self, playlist_id: int) -> dict[str, Any]:
|
||||
@@ -290,7 +290,7 @@ class PlaylistService:
|
||||
|
||||
# Check if sound is already in main playlist
|
||||
if not await self.playlist_repo.is_sound_in_playlist(
|
||||
main_playlist.id, sound_id
|
||||
main_playlist.id, sound_id,
|
||||
):
|
||||
await self.playlist_repo.add_sound_to_playlist(main_playlist.id, sound_id)
|
||||
logger.info(
|
||||
|
||||
@@ -141,7 +141,7 @@ class SoundNormalizerService:
|
||||
ffmpeg.run(stream, quiet=True, overwrite_output=True)
|
||||
logger.info("One-pass normalization completed: %s", output_path)
|
||||
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logger.exception("One-pass normalization failed for %s", input_path)
|
||||
raise
|
||||
|
||||
@@ -153,7 +153,7 @@ class SoundNormalizerService:
|
||||
"""Normalize audio using two-pass loudnorm for better quality."""
|
||||
try:
|
||||
logger.info(
|
||||
"Starting two-pass normalization: %s -> %s", input_path, output_path
|
||||
"Starting two-pass normalization: %s -> %s", input_path, output_path,
|
||||
)
|
||||
|
||||
# First pass: analyze
|
||||
@@ -193,7 +193,7 @@ class SoundNormalizerService:
|
||||
json_match = re.search(r'\{[^{}]*"input_i"[^{}]*\}', analysis_output)
|
||||
if not json_match:
|
||||
logger.error(
|
||||
"Could not find JSON in loudnorm output: %s", analysis_output
|
||||
"Could not find JSON in loudnorm output: %s", analysis_output,
|
||||
)
|
||||
raise ValueError("Could not extract loudnorm analysis data")
|
||||
|
||||
@@ -260,7 +260,7 @@ class SoundNormalizerService:
|
||||
)
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logger.exception("Two-pass normalization failed for %s", input_path)
|
||||
raise
|
||||
|
||||
@@ -428,7 +428,7 @@ class SoundNormalizerService:
|
||||
"type": sound.type,
|
||||
"is_normalized": sound.is_normalized,
|
||||
"name": sound.name,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
# Process each sound using captured data
|
||||
@@ -476,7 +476,7 @@ class SoundNormalizerService:
|
||||
"normalized_hash": None,
|
||||
"id": sound_id,
|
||||
"error": str(e),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
logger.info("Normalization completed: %s", results)
|
||||
@@ -517,7 +517,7 @@ class SoundNormalizerService:
|
||||
"type": sound.type,
|
||||
"is_normalized": sound.is_normalized,
|
||||
"name": sound.name,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
# Process each sound using captured data
|
||||
@@ -565,7 +565,7 @@ class SoundNormalizerService:
|
||||
"normalized_hash": None,
|
||||
"id": sound_id,
|
||||
"error": str(e),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
logger.info("Type normalization completed: %s", results)
|
||||
|
||||
@@ -132,7 +132,7 @@ class SoundScannerService:
|
||||
"id": None,
|
||||
"error": str(e),
|
||||
"changes": None,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
# Delete sounds that no longer exist in directory
|
||||
@@ -153,7 +153,7 @@ class SoundScannerService:
|
||||
"id": sound.id,
|
||||
"error": None,
|
||||
"changes": None,
|
||||
}
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception("Error deleting sound %s", filename)
|
||||
@@ -169,7 +169,7 @@ class SoundScannerService:
|
||||
"id": sound.id,
|
||||
"error": str(e),
|
||||
"changes": None,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
logger.info("Sync completed: %s", results)
|
||||
@@ -219,7 +219,7 @@ class SoundScannerService:
|
||||
"id": sound.id,
|
||||
"error": None,
|
||||
"changes": None,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
elif existing_sound.hash != file_hash:
|
||||
@@ -246,7 +246,7 @@ class SoundScannerService:
|
||||
"id": existing_sound.id,
|
||||
"error": None,
|
||||
"changes": ["hash", "duration", "size", "name"],
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
else:
|
||||
@@ -264,7 +264,7 @@ class SoundScannerService:
|
||||
"id": existing_sound.id,
|
||||
"error": None,
|
||||
"changes": None,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async def scan_soundboard_directory(self) -> ScanResults:
|
||||
|
||||
@@ -6,7 +6,6 @@ from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from sqlmodel import select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
from app.core.logging import get_logger
|
||||
|
||||
Reference in New Issue
Block a user