Check import filetype; install black

This commit is contained in:
Keith Edmunds 2025-08-17 18:26:53 +01:00
parent 4fd9a0381f
commit 316b4708c6
4 changed files with 47 additions and 5 deletions

View File

@ -35,6 +35,7 @@ from classes import (
) )
from config import Config from config import Config
from helpers import ( from helpers import (
audio_file_extension,
file_is_unreadable, file_is_unreadable,
get_tags, get_tags,
show_OK, show_OK,
@ -202,8 +203,9 @@ class FileImporter:
self.sort_track_match_data(tfd) self.sort_track_match_data(tfd)
selection = self.get_user_choices(tfd) selection = self.get_user_choices(tfd)
if self.process_selection(tfd, selection): if self.process_selection(tfd, selection):
if self.validate_file_data(tfd): if self.extension_check(tfd):
tfd.import_this_file = True if self.validate_file_data(tfd):
tfd.import_this_file = True
return tfd return tfd
@ -237,6 +239,26 @@ class FileImporter:
return True return True
def extension_check(self, tfd: TrackFileData) -> bool:
"""
If we are replacing an existing file, check that the correct file
extension of the replacement file matches the existing file
extension and return True if it does (or if there is no exsting
file), else False.
"""
if not tfd.file_path_to_remove:
return True
if tfd.file_path_to_remove.endswith(audio_file_extension(tfd.source_path)):
return True
tfd.error = (
f"Existing file ({tfd.file_path_to_remove}) has a different "
f"extension to replacement file ({tfd.source_path})"
)
return False
def find_similar(self, tfd: TrackFileData) -> None: def find_similar(self, tfd: TrackFileData) -> None:
""" """
- Search title in existing tracks - Search title in existing tracks
@ -445,7 +467,8 @@ class FileImporter:
if tfd.track_id == 0 and tfd.destination_path != tfd.file_path_to_remove: if tfd.track_id == 0 and tfd.destination_path != tfd.file_path_to_remove:
while os.path.exists(tfd.destination_path): while os.path.exists(tfd.destination_path):
msg = ( msg = (
f"New import requested but default destination path ({tfd.destination_path})" "New import requested but default destination path"
f" ({tfd.destination_path})"
" already exists. Click OK and choose where to save this track" " already exists. Click OK and choose where to save this track"
) )
show_OK(title="Desintation path exists", msg=msg, parent=None) show_OK(title="Desintation path exists", msg=msg, parent=None)
@ -627,7 +650,8 @@ class DoTrackImport(QThread):
f"Importing {os.path.basename(self.import_file_path)}", 5000 f"Importing {os.path.basename(self.import_file_path)}", 5000
) )
# Get audio metadata in this thread rather than calling function to save interactive time # Get audio metadata in this thread rather than calling
# function to save interactive time
self.audio_metadata = helpers.get_audio_metadata(self.import_file_path) self.audio_metadata = helpers.get_audio_metadata(self.import_file_path)
# Remove old file if so requested # Remove old file if so requested

View File

@ -13,6 +13,7 @@ import tempfile
from PyQt6.QtWidgets import QInputDialog, QMainWindow, QMessageBox, QWidget from PyQt6.QtWidgets import QInputDialog, QMainWindow, QMessageBox, QWidget
# Third party imports # Third party imports
import filetype
from mutagen.flac import FLAC # type: ignore from mutagen.flac import FLAC # type: ignore
from mutagen.mp3 import MP3 # type: ignore from mutagen.mp3 import MP3 # type: ignore
from pydub import AudioSegment, effects from pydub import AudioSegment, effects
@ -50,6 +51,14 @@ def ask_yes_no(
return button == QMessageBox.StandardButton.Yes return button == QMessageBox.StandardButton.Yes
def audio_file_extension(fpath: str) -> str | None:
"""
Return the correct extension for this type of file.
"""
return filetype.guess(fpath).extension
def fade_point( def fade_point(
audio_segment: AudioSegment, audio_segment: AudioSegment,
fade_threshold: float = 0.0, fade_threshold: float = 0.0,
@ -72,7 +81,7 @@ def fade_point(
fade_threshold = max_vol fade_threshold = max_vol
while ( while (
audio_segment[trim_ms : trim_ms + chunk_size].dBFS < fade_threshold audio_segment[trim_ms: trim_ms + chunk_size].dBFS < fade_threshold
and trim_ms > 0 and trim_ms > 0
): # noqa W503 ): # noqa W503
trim_ms -= chunk_size trim_ms -= chunk_size
@ -94,6 +103,9 @@ def file_is_unreadable(path: Optional[str]) -> bool:
def get_audio_segment(path: str) -> Optional[AudioSegment]: def get_audio_segment(path: str) -> Optional[AudioSegment]:
if not path.endswith(audio_file_extension(path)):
return None
try: try:
if path.endswith(".mp3"): if path.endswith(".mp3"):
return AudioSegment.from_mp3(path) return AudioSegment.from_mp3(path)

View File

@ -34,6 +34,7 @@ dependencies = [
"dogpile-cache>=1.3.4", "dogpile-cache>=1.3.4",
"pdbpp>=0.10.3", "pdbpp>=0.10.3",
"filetype>=1.2.0", "filetype>=1.2.0",
"black>=25.1.0",
] ]
[dependency-groups] [dependency-groups]
@ -64,6 +65,9 @@ python_version = 3.11
warn_unused_configs = true warn_unused_configs = true
disallow_incomplete_defs = true disallow_incomplete_defs = true
[tool.pylsp.plugins.pycodestyle]
maxLineLength = 88
[tool.pytest.ini_options] [tool.pytest.ini_options]
addopts = "--exitfirst --showlocals --capture=no" addopts = "--exitfirst --showlocals --capture=no"
pythonpath = [".", "app"] pythonpath = [".", "app"]

View File

@ -492,6 +492,7 @@ dependencies = [
{ name = "alchemical" }, { name = "alchemical" },
{ name = "alembic" }, { name = "alembic" },
{ name = "audioop-lts" }, { name = "audioop-lts" },
{ name = "black" },
{ name = "colorlog" }, { name = "colorlog" },
{ name = "dogpile-cache" }, { name = "dogpile-cache" },
{ name = "filetype" }, { name = "filetype" },
@ -538,6 +539,7 @@ requires-dist = [
{ name = "alchemical", specifier = ">=1.0.2" }, { name = "alchemical", specifier = ">=1.0.2" },
{ name = "alembic", specifier = ">=1.14.0" }, { name = "alembic", specifier = ">=1.14.0" },
{ name = "audioop-lts", specifier = ">=0.2.1" }, { name = "audioop-lts", specifier = ">=0.2.1" },
{ name = "black", specifier = ">=25.1.0" },
{ name = "colorlog", specifier = ">=6.9.0" }, { name = "colorlog", specifier = ">=6.9.0" },
{ name = "dogpile-cache", specifier = ">=1.3.4" }, { name = "dogpile-cache", specifier = ">=1.3.4" },
{ name = "filetype", specifier = ">=1.2.0" }, { name = "filetype", specifier = ">=1.2.0" },