Refactor file: taglib.py and utils/parsers.py

Add dataclass and pathlib imports in taglib.py

Add clean_filename, ParseData, and extract_artist_title functions in
taglib.py

Modify get_tags function in taglib.py to use extract_artist_title
function

Modify LyricsProvider class in lyrics.py to add timeout parameter in
session.get

Remove parse_artist_from_filename and parse_title_from_filename
functions in utils/parsers.py

Add split_artists function in utils/parsers.py

Remove parse_artist_from_filename and parse_title_from_filename
functions in utils/parsers.py

Add remove_prod function in utils/parsers.py

Refactor code and improve code readability
This commit is contained in:
mungai-njoroge 2023-11-22 15:44:31 +03:00
parent 52173d4c7e
commit 38650a1a7e
3 changed files with 55 additions and 40 deletions

View File

@ -1,5 +1,8 @@
from dataclasses import dataclass
import os import os
from io import BytesIO from io import BytesIO
from pathlib import Path
import re
import pendulum import pendulum
from PIL import Image, UnidentifiedImageError from PIL import Image, UnidentifiedImageError
@ -7,7 +10,7 @@ from tinytag import TinyTag
from app.settings import Defaults, Paths from app.settings import Defaults, Paths
from app.utils.hashing import create_hash from app.utils.hashing import create_hash
from app.utils.parsers import parse_artist_from_filename, parse_title_from_filename from app.utils.parsers import split_artists
from app.utils.wintools import win_replace_slash from app.utils.wintools import win_replace_slash
@ -85,6 +88,45 @@ def parse_date(date_str: str | None) -> int | None:
return None return None
def clean_filename(filename: str):
if "official" in filename.lower():
return re.sub(r"\s*\([^)]*official[^)]*\)", "", filename, flags=re.IGNORECASE)
return filename
@dataclass
class ParseData:
artist: str
title: str
def __post_init__(self):
self.artist = split_artists(self.artist)
def extract_artist_title(filename: str):
path = Path(filename).with_suffix("")
path = clean_filename(str(path))
split_result = path.split(" - ")
split_result = [x.strip() for x in split_result]
if len(split_result) == 1:
return ParseData("", split_result[0])
if len(split_result) > 2:
try:
int(split_result[0])
return ParseData(split_result[1], " - ".join(split_result[2:]))
except ValueError:
pass
artist = split_result[0]
title = split_result[1]
return ParseData(artist, title)
def get_tags(filepath: str): def get_tags(filepath: str):
""" """
Returns the tags for a given audio file. Returns the tags for a given audio file.
@ -112,22 +154,28 @@ def get_tags(filepath: str):
if no_artist and not no_albumartist: if no_artist and not no_albumartist:
tags.artist = tags.albumartist tags.artist = tags.albumartist
parse_data = None
to_filename = ["title", "album"] to_filename = ["title", "album"]
for tag in to_filename: for tag in to_filename:
p = getattr(tags, tag) p = getattr(tags, tag)
if p == "" or p is None: if p == "" or p is None:
maybe = parse_title_from_filename(filename) parse_data = extract_artist_title(filename)
setattr(tags, tag, maybe) title = parse_data.title
setattr(tags, tag, title)
parse = ["artist", "albumartist"] parse = ["artist", "albumartist"]
for tag in parse: for tag in parse:
p = getattr(tags, tag) p = getattr(tags, tag)
if p == "" or p is None: if p == "" or p is None:
maybe = parse_artist_from_filename(filename) if not parse_data:
parse_data = extract_artist_title(filename)
if maybe: artist = parse_data.artist
setattr(tags, tag, ", ".join(maybe))
if artist:
setattr(tags, tag, ", ".join(artist))
else: else:
setattr(tags, tag, "Unknown") setattr(tags, tag, "Unknown")

View File

@ -75,7 +75,7 @@ class LyricsProvider(LRCProvider):
return None return None
try: try:
response = self.session.get(url, params=query) response = self.session.get(url, params=query, timeout=10)
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
return None return None

View File

@ -18,39 +18,6 @@ def split_artists(src: str):
return [a for a in artists if a] return [a for a in artists if a]
def parse_artist_from_filename(title: str):
"""
Extracts artist names from a song title using regex.
"""
regex = r"^(.+?)\s*[-–—]\s*(?:.+?)$"
match = re.search(regex, title, re.IGNORECASE)
if not match:
return []
artists = match.group(1)
artists = split_artists(artists)
return artists
def parse_title_from_filename(title: str):
"""
Extracts track title from a song title using regex.
"""
regex = r"^(?:.+?)\s*[-–—]\s*(.+?)$"
match = re.search(regex, title, re.IGNORECASE)
if not match:
return title
res = match.group(1)
# remove text in brackets starting with "official" case-insensitive
res = re.sub(r"\s*\([^)]*official[^)]*\)", "", res, flags=re.IGNORECASE)
return res.strip()
def remove_prod(title: str) -> str: def remove_prod(title: str) -> str:
""" """
Removes the producer string in a track title using regex. Removes the producer string in a track title using regex.