"with ",
"explicit",
)
+WITH_TITLE_WORDS = (
+ # words that, when following "with", indicate this is part of the song title
+ # not a featuring credit.
+ "someone",
+ "the",
+ "u",
+ "you",
+ "no",
+)
def filename_from_string(string: str) -> str:
version = track_version or ""
for regex in (r"\(.*?\)", r"\[.*?\]", r" - .*"):
for title_part in re.findall(regex, title):
+ # Extract the content without brackets/dashes for checking
+ clean_part = title_part.translate(str.maketrans("", "", "()[]-")).strip().lower()
+
+ # Check if this should be ignored (featuring/explicit parts)
+ should_ignore = False
for ignore_str in IGNORE_TITLE_PARTS:
- if ignore_str in title_part.lower():
+ if clean_part.startswith(ignore_str):
+ # Special handling for "with " - check if followed by title words
+ if ignore_str == "with ":
+ # Extract the word after "with "
+ after_with = (
+ clean_part[len("with ") :].split()[0]
+ if len(clean_part) > len("with ")
+ else ""
+ )
+ if after_with in WITH_TITLE_WORDS:
+ # This is part of the title (e.g., "with you"), don't ignore
+ break
+ # Remove this part from the title
title = title.replace(title_part, "").strip()
- continue
+ should_ignore = True
+ break
+
+ if should_ignore:
+ continue
+
+ # Check if this part is a version
for version_str in VERSION_PARTS:
- if version_str not in title_part.lower():
- continue
- version = (
- title_part.replace("(", "")
- .replace(")", "")
- .replace("[", "")
- .replace("]", "")
- .replace("-", "")
- .strip()
- )
- title = title.replace(title_part, "").strip()
- return (title, version)
+ if version_str in clean_part:
+ # Preserve original casing for output
+ version = title_part.strip("()[]- ").strip()
+ title = title.replace(title_part, "").strip()
+ return title, version
return title, version
title, version = util.parse_title_and_version(test_str)
assert title == "SuperSong"
assert version == ""
+ # Version keywords in main title should NOT be stripped (only in parentheses)
+ test_str = "Great live unplugged song"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Great live unplugged song"
+ assert version == ""
+ test_str = "I Do (featuring Sonny of P.O.D.) (Album Version)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "I Do"
+ assert version == "Album Version"
+ test_str = "Get Up Stand Up (Phunk Investigation instrumental club mix)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Get Up Stand Up"
+ assert version == "Phunk Investigation instrumental club mix"
+ # Complex case: non-version part + version part with 'mix' keyword
+ test_str = "Lovin' You More (That Big Track) (Mosquito Chillout mix)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Lovin' You More (That Big Track)"
+ assert version == "Mosquito Chillout mix"
+
+
+def test_with_handling_in_titles() -> None:
+ """Test 'with' handling - preserved in title, stripped as featuring credit."""
+ # 'with you' (preserved as title word)
+ test_str = "CCF (I'm Gonna Stay with You)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "CCF (I'm Gonna Stay with You)"
+ assert version == ""
+ # 'with someone' (preserved as title word)
+ test_str = "Ever Fallen in Love (With Someone You Shouldn't've)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Ever Fallen in Love (With Someone You Shouldn't've)"
+ assert version == ""
+ # 'with u' (preserved as title word)
+ test_str = "Dance (With U)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Dance (With U)"
+ assert version == ""
+ # 'with the' (preserved as title word)
+ test_str = "Girl (With the Patent Leather Face)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Girl (With the Patent Leather Face)"
+ assert version == ""
+ # 'with you' - different phrasing (preserved as title word)
+ test_str = "Rockin' Around (With You)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Rockin' Around (With You)"
+ assert version == ""
+ # 'with no' (preserved as title word)
+ test_str = "Ain't Gonna Bump No More (With No Big Fat Woman)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Ain't Gonna Bump No More (With No Big Fat Woman)"
+ assert version == ""
+ # 'with that' - not in WITH_TITLE_WORDS but not stripped because it doesn't start with "with "
+ test_str = "The Catastrophe (Good Luck with That Man)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "The Catastrophe (Good Luck with That Man)"
+ assert version == ""
+ # 'with [artist name]' - should still be stripped (not a title word)
+ test_str = "Great Song (with John Smith)"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Great Song"
+ assert version == ""
+ # 'with [artist name]' in brackets - should still be stripped
+ test_str = "Great Song [with Jane Doe]"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Great Song"
+ assert version == ""
+ # Title word preserved + version extracted from dash notation
+ test_str = "CCF (I'm Gonna Stay with You) - Live Version"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "CCF (I'm Gonna Stay with You)"
+ assert version == "Live Version"
+ # Title word preserved + version extracted from brackets
+ test_str = "Dance (With U) [Remix]"
+ title, version = util.parse_title_and_version(test_str)
+ assert title == "Dance (With U)"
+ assert version == "Remix"
async def test_uri_parsing() -> None: