Fix false library match between normal and Extended Mix titles
Featuring cleanup after bracket flattening stripped version suffixes, so Download Missing treated distinct tracks (e.g. Latinamerica vs Extended Mix) as already in library. Remove feat blocks before flattening and bound unparenthesized feat removal; add regression tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
cd9e4abc7c
commit
6b7e6bff61
2 changed files with 96 additions and 5 deletions
|
|
@ -7296,6 +7296,22 @@ class MusicDatabase:
|
|||
cleaned = re.sub(r'\s*\(with\s+[^)]*\)', '', cleaned, flags=re.IGNORECASE)
|
||||
cleaned = re.sub(r'\s*\[with\s+[^\]]*\]', '', cleaned, flags=re.IGNORECASE)
|
||||
|
||||
# Featuring in parentheses/brackets — must run BEFORE bracket flattening.
|
||||
# Otherwise ``feat.`` removal after flattening is greedy and strips
|
||||
# version suffixes ("Extended Mix", "Radio Edit", …) from the same title.
|
||||
cleaned = re.sub(
|
||||
r'\s*\([^)]*(?:feat\.?|ft\.?|featuring)[^)]*\)',
|
||||
'',
|
||||
cleaned,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
cleaned = re.sub(
|
||||
r'\s*\[[^\]]*(?:feat\.?|ft\.?|featuring)[^\]]*\]',
|
||||
'',
|
||||
cleaned,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
|
||||
# STEP 1: Normalize bracket/dash styles for consistent matching
|
||||
# Convert all bracket styles to spaces for better matching
|
||||
cleaned = re.sub(r'\s*[\[\(]\s*', ' ', cleaned) # Convert opening brackets/parens to space
|
||||
|
|
@ -7311,11 +7327,6 @@ class MusicDatabase:
|
|||
r'\s*explicit\s*', # Remove explicit markers
|
||||
r'\s*clean\s*', # Remove clean markers
|
||||
|
||||
# Featuring/collaboration (metadata, not different version)
|
||||
r'\s*feat\..*', # Remove featuring
|
||||
r'\s*featuring.*', # Remove featuring
|
||||
r'\s*ft\..*', # Remove ft.
|
||||
|
||||
# Remasters (same recording, different mastering)
|
||||
r'\s*\d{4}\s*remaster.*', # Remove "2015 remaster"
|
||||
r'\s*remaster.*', # Remove "remaster/remastered"
|
||||
|
|
@ -7352,6 +7363,19 @@ class MusicDatabase:
|
|||
for pattern in patterns_to_remove:
|
||||
cleaned = re.sub(pattern, '', cleaned, flags=re.IGNORECASE).strip()
|
||||
|
||||
# Unparenthesized featuring (e.g. after bracket flatten) — bounded so
|
||||
# "feat. Vika - Extended Mix" keeps the version tail.
|
||||
_version_boundary = (
|
||||
r'(?:extended|radio|club|dub|instrumental|acoustic|live|remix|'
|
||||
r'original|edit|mix|version)\b'
|
||||
)
|
||||
cleaned = re.sub(
|
||||
rf'\s+(?:feat\.?|ft\.?|featuring)\s+.+?(?=\s+-\s+{_version_boundary}|\s+{_version_boundary}|$)',
|
||||
'',
|
||||
cleaned,
|
||||
flags=re.IGNORECASE,
|
||||
).strip()
|
||||
|
||||
# STEP 3: Clean up extra spaces
|
||||
cleaned = re.sub(r'\s+', ' ', cleaned).strip()
|
||||
|
||||
|
|
|
|||
67
tests/test_track_title_version_distinction.py
Normal file
67
tests/test_track_title_version_distinction.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
"""Regression: normal vs Extended Mix must not collapse to the same cleaned title."""
|
||||
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from database.music_database import DatabaseTrack, MusicDatabase
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db(tmp_path: Path):
|
||||
return MusicDatabase(database_path=str(tmp_path / "test.db"))
|
||||
|
||||
|
||||
def test_clean_title_preserves_extended_mix_after_feat(db):
|
||||
normal = db._clean_track_title_for_comparison("Latinamerica (feat. Vika)")
|
||||
extended = db._clean_track_title_for_comparison(
|
||||
"Latinamerica (feat. Vika) - Extended Mix"
|
||||
)
|
||||
assert normal == "latinamerica"
|
||||
assert extended == "latinamerica extended mix"
|
||||
assert normal != extended
|
||||
|
||||
|
||||
def test_normal_does_not_match_extended_in_library(db):
|
||||
extended_track = DatabaseTrack(
|
||||
id="t1",
|
||||
album_id="a1",
|
||||
artist_id="ar1",
|
||||
title="Latinamerica (feat. Vika) - Extended Mix",
|
||||
track_number=1,
|
||||
duration=300000,
|
||||
file_path="/music/ext.flac",
|
||||
bitrate=320,
|
||||
)
|
||||
extended_track.artist_name = "Raffa FL"
|
||||
extended_track.album_title = "Latinamerica (feat. Vika)"
|
||||
|
||||
confidence = db._calculate_track_confidence(
|
||||
"Latinamerica (feat. Vika)",
|
||||
"Raffa FL",
|
||||
extended_track,
|
||||
)
|
||||
assert confidence < 0.7
|
||||
|
||||
|
||||
def test_extended_matches_extended_in_library(db):
|
||||
extended_track = DatabaseTrack(
|
||||
id="t1",
|
||||
album_id="a1",
|
||||
artist_id="ar1",
|
||||
title="Latinamerica (feat. Vika) - Extended Mix",
|
||||
track_number=1,
|
||||
duration=300000,
|
||||
file_path="/music/ext.flac",
|
||||
bitrate=320,
|
||||
)
|
||||
extended_track.artist_name = "Raffa FL"
|
||||
extended_track.album_title = "Latinamerica (feat. Vika)"
|
||||
|
||||
confidence = db._calculate_track_confidence(
|
||||
"Latinamerica (feat. Vika) - Extended Mix",
|
||||
"Raffa FL",
|
||||
extended_track,
|
||||
)
|
||||
assert confidence >= 0.7
|
||||
Loading…
Reference in a new issue