syng/syng/result.py

116 lines
3.4 KiB
Python

"""Module for search results."""
from __future__ import annotations
from dataclasses import dataclass
import os.path
from typing import Optional
@dataclass
class Result:
"""This models a search result.
:param ident: The identifier of the entry in the source
:type ident: str
:param source: The name of the source of the entry
:type source: str
:param title: The title of the song
:type title: str
:param artist: The artist of the song
:type artist: str
:param album: The name of the album or compilation, this particular
version is from.
:type album: str
"""
ident: str
source: str
title: str
artist: Optional[str]
album: Optional[str]
duration: Optional[str] = None
@classmethod
def from_filename(cls, filename: str, source: str) -> Result:
"""
Infer most attributes from the filename.
The filename must be in this form::
{artist} - {title} - {album}.ext
If parsing failes, the filename will be used as the title and the
artist and album will be set to "Unknown".
:param filename: The filename to parse
:type filename: str
:param source: The name of the source
:type source: str
:return: see above
:rtype: Optional[Result]
"""
basename = os.path.splitext(filename)[0]
try:
splitfile = os.path.basename(basename).split(" - ")
ident = filename
artist = splitfile[0].strip()
title = splitfile[1].strip()
album = splitfile[2].strip()
return cls(ident=ident, source=source, title=title, artist=artist, album=album)
except IndexError:
return cls(ident=filename, source=source, title=basename, artist=None, album=None)
@classmethod
def from_dict(cls, values: dict[str, str]) -> Result:
"""
Create a Result object from a dictionary.
The dictionary must have the following keys:
- ident (str)
- source (str)
- title (str)
- artist (str)
- album (str)
- duration (int, optional)
:param values: The dictionary with the values
:type values: dict[str, str]
:return: The Result object
:rtype: Result
"""
return cls(
ident=values["ident"],
source=values["source"],
title=values["title"],
artist=values["artist"],
album=values["album"],
duration=values.get("duration", None),
)
def to_dict(self) -> dict[str, str]:
"""
Convert the Result object to a dictionary.
The dictionary will have the following keys:
- ident (str)
- source (str)
- title (str)
- album (str, if available)
- artist (str, if available)
- duration (str, if available)
:return: The dictionary with the values
:rtype: dict[str, str]
"""
output: dict[str, str] = {
"ident": self.ident,
"source": self.source,
"title": self.title,
}
if self.album is not None:
output["album"] = self.album
if self.artist is not None:
output["artist"] = self.artist
if self.duration is not None:
output["duration"] = self.duration
return output