add serializer functions for track and album objects

This commit is contained in:
mungai-njoroge 2023-06-24 16:47:54 +03:00
parent 88be80b25d
commit dbfa395207
7 changed files with 169 additions and 43 deletions

View File

@ -6,14 +6,16 @@ from dataclasses import asdict
from flask import Blueprint, request
from app.models import FavType, Track
from app.serializers.track import track_serializer
from app.store.albums import AlbumStore
from app.store.tracks import TrackStore
from app.db.sqlite.albums import SQLiteAlbumMethods as adb
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from app.models import FavType, Track
from app.utils.hashing import create_hash
from app.utils.remove_duplicates import remove_duplicates
from app.store.tracks import TrackStore
from app.store.albums import AlbumStore
from app.utils.hashing import create_hash
from app.serializers.album import serialize_for_card
from app.utils.remove_duplicates import remove_duplicates
get_albums_by_albumartist = adb.get_albums_by_albumartist
check_is_fav = favdb.check_is_favorite
@ -79,7 +81,10 @@ def get_album_tracks_and_info():
album.is_favorite = check_is_fav(albumhash, FavType.album)
return {"tracks": tracks, "info": album}
return {
"tracks": [track_serializer(t, retain_disc=True) for t in tracks],
"info": album,
}
@api.route("/album/<albumhash>/tracks", methods=["GET"])
@ -92,9 +97,10 @@ def get_album_tracks(albumhash: str):
for t in tracks:
track = str(t["track"]).zfill(3)
t["pos"] = int(f"{t['disc']}{track}")
t["_pos"] = int(f"{t['disc']}{track}")
tracks = sorted(tracks, key=lambda t: t["pos"])
tracks = sorted(tracks, key=lambda t: t["_pos"])
tracks = [track_serializer(t, _remove={"_pos"}) for t in tracks]
return {"tracks": tracks}
@ -122,7 +128,14 @@ def get_artist_albums():
for a in albumartists
]
albums = [a for a in albums if len(a["albums"]) > 0]
albums = [
{
"artisthash": a["artisthash"],
"albums": [serialize_for_card(a_) for a_ in (a["albums"])],
}
for a in albums
if len(a["albums"]) > 0
]
return {"data": albums}

View File

@ -7,6 +7,8 @@ from flask import Blueprint, request
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from app.models import Album, FavType, Track
from app.serializers.album import serialize_for_card_many
from app.serializers.track import serialize_tracks
from app.utils.remove_duplicates import remove_duplicates
from app.store.albums import AlbumStore
@ -22,7 +24,7 @@ class CacheEntry:
"""
def __init__(
self, artisthash: str, albumhashes: set[str], tracks: list[Track]
self, artisthash: str, albumhashes: set[str], tracks: list[Track]
) -> None:
self.albums: list[Album] = []
self.tracks: list[Track] = []
@ -208,7 +210,7 @@ def get_artist(artisthash: str):
artist.is_favorite = favdb.check_is_favorite(artisthash, FavType.artist)
return {"artist": artist, "tracks": tracks[:limit]}
return {"artist": artist, "tracks": serialize_tracks(tracks[:limit])}
@api.route("/artist/<artisthash>/albums", methods=["GET"])
@ -265,11 +267,11 @@ def get_artist_albums(artisthash: str):
return {
"artistname": artist.name,
"albums": albums[:limit],
"singles": singles[:limit],
"eps": eps[:limit],
"appearances": appearances[:limit],
"compilations": compilations[:limit]
"albums": serialize_for_card_many(albums[:limit]),
"singles": serialize_for_card_many(singles[:limit]),
"eps": serialize_for_card_many(eps[:limit]),
"appearances": serialize_for_card_many(appearances[:limit]),
"compilations": serialize_for_card_many(compilations[:limit]),
}
@ -280,7 +282,8 @@ def get_all_artist_tracks(artisthash: str):
"""
tracks = TrackStore.get_tracks_by_artist(artisthash)
return {"tracks": tracks}
return {"tracks": serialize_tracks(tracks)}
#
# @api.route("/artist/<artisthash>/similar", methods=["GET"])

View File

@ -2,13 +2,17 @@ from flask import Blueprint, request
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from app.models import FavType
from app.serializers.album import serialize_for_card_many
from app.serializers.track import serialize_tracks
from app.utils.bisection import UseBisection
from app.store.artists import ArtistStore
from app.store.albums import AlbumStore
from app.store.tracks import TrackStore
from app.serializers.favorites_serializer import recent_fav_track_serializer, recent_fav_album_serializer, \
recent_fav_artist_serializer
from app.serializers.favorites_serializer import (
recent_fav_album_serializer,
recent_fav_artist_serializer,
)
api = Blueprint("favorite", __name__, url_prefix="/")
@ -80,7 +84,7 @@ def get_favorite_albums():
if limit == 0:
limit = len(albums)
return {"albums": fav_albums[:limit]}
return {"albums": serialize_for_card_many(fav_albums[:limit])}
@api.route("/tracks/favorite")
@ -103,7 +107,7 @@ def get_favorite_tracks():
if limit == 0:
limit = len(tracks)
return {"tracks": tracks[:limit]}
return {"tracks": serialize_tracks(tracks[:limit])}
@api.route("/artists/favorite")
@ -194,20 +198,18 @@ def get_all_favorites():
if fav[2] == FavType.album:
try:
album = [a for a in albums if a.albumhash == fav[1]][0]
recents.append({
"type": "album",
"item": recent_fav_album_serializer(album)
})
recents.append(
{"type": "album", "item": recent_fav_album_serializer(album)}
)
except IndexError:
continue
if fav[2] == FavType.artist:
try:
artist = [a for a in artists if a.artisthash == fav[1]][0]
recents.append({
"type": "artist",
"item": recent_fav_artist_serializer(artist)
})
recents.append(
{"type": "artist", "item": recent_fav_artist_serializer(artist)}
)
except IndexError:
continue

View File

@ -1,5 +1,6 @@
import dataclasses
from dataclasses import dataclass
import datetime
from .track import Track
from .artist import Artist
@ -47,21 +48,28 @@ class Album:
if len(featured) > 0:
original_lower = "-".join([a.name.lower() for a in self.albumartists])
self.albumartists.extend([Artist(a) for a in featured if a.lower() not in original_lower])
self.albumartists.extend(
[Artist(a) for a in featured if a.lower() not in original_lower]
)
from ..store.tracks import TrackStore
TrackStore.append_track_artists(self.albumhash, featured, self.title)
if get_flag(ParserFlags.CLEAN_ALBUM_TITLE):
get_versions = not get_flag(ParserFlags.MERGE_ALBUM_VERSIONS)
self.title, self.versions = get_base_title_and_versions(self.title, get_versions=get_versions)
self.title, self.versions = get_base_title_and_versions(
self.title, get_versions=get_versions
)
self.base_title = self.title
if "super_deluxe" in self.versions:
self.versions.remove("deluxe")
else:
self.base_title = get_base_title_and_versions(self.title, get_versions=False)[0]
self.base_title = get_base_title_and_versions(
self.title, get_versions=False
)[0]
self.albumartists_hashes = "-".join(a.artisthash for a in self.albumartists)
@ -108,8 +116,17 @@ class Album:
return True
substrings = [
"the essential", "best of", "greatest hits", "#1 hits", "number ones", "super hits",
"ultimate collection", "anthology", "great hits", "biggest hits", "the hits"
"the essential",
"best of",
"greatest hits",
"#1 hits",
"number ones",
"super hits",
"ultimate collection",
"anthology",
"great hits",
"biggest hits",
"the hits",
]
for substring in substrings:
@ -147,16 +164,26 @@ class Album:
return
if (
len(tracks) == 1
and create_hash(tracks[0].title) == create_hash(self.title) # if they have the same title
# and tracks[0].track == 1
# and tracks[0].disc == 1
# TODO: Review -> Are the above commented checks necessary?
len(tracks) == 1
and create_hash(tracks[0].title)
== create_hash(self.title) # if they have the same title
# and tracks[0].track == 1
# and tracks[0].disc == 1
# TODO: Review -> Are the above commented checks necessary?
):
self.is_single = True
def get_date_from_tracks(self, tracks: list[Track]):
for track in tracks:
if track.date != "Unknown":
self.date = track.date
break
"""
Gets the date of the album its tracks.
Args:
tracks (list[Track]): The tracks of the album.
"""
dates = {t.date for t in tracks if t.date}
if len(dates) == 0:
self.date = 0
return
self.date = datetime.datetime.fromtimestamp(min(dates)).year

28
app/serializers/album.py Normal file
View File

@ -0,0 +1,28 @@
from dataclasses import asdict
from app.models.album import Album
def album_serializer(album: Album, to_remove: set[str]) -> dict:
album_dict = asdict(album)
to_remove.update(key for key in album_dict.keys() if key.startswith("is_"))
for key in to_remove:
album_dict.pop(key, None)
return album_dict
def serialize_for_card(album: Album):
props_to_remove = {
"duration",
"count",
"albumartist_hashes",
"og_title",
"base_title",
}
return album_serializer(album, props_to_remove)
def serialize_for_card_many(albums: list[Album]):
return [serialize_for_card(a) for a in albums]

25
app/serializers/artist.py Normal file
View File

@ -0,0 +1,25 @@
# from dataclasses import asdict
# def album_serializer(album: Artist, to_remove: set[str]) -> ArtistMinimal:
# album_dict = asdict(album)
# to_remove.update(key for key in album_dict.keys() if key.startswith("is_"))
# for key in to_remove:
# album_dict.pop(key, None)
# return album_dict
# Traceback (most recent call last):
# File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
# self.run()
# File "/usr/lib/python3.10/threading.py", line 953, in run
# self._target(*self._args, **self._kwargs)
# File "/usr/lib/python3.10/multiprocessing/pool.py", line 579, in _handle_results
# task = get()
# File "/usr/lib/python3.10/multiprocessing/connection.py", line 251, in recv
# return _ForkingPickler.loads(buf.getbuffer())
# File "/home/cwilvx/.cache/pypoetry/virtualenvs/swing_music_player-xIXBgWdk-py3.10/lib/python3.10/site-packages/requests/exceptions.py", line 41, in __init__
# CompatJSONDecodeError.__init__(self, *args)
# TypeError: JSONDecodeError.__init__() missing 2 required positional arguments: 'doc' and 'pos'

28
app/serializers/track.py Normal file
View File

@ -0,0 +1,28 @@
from dataclasses import asdict
from app.models.track import Track
def track_serializer(track: Track, _remove: set = {}, retain_disc=False) -> dict:
album_dict = asdict(track)
to_remove = {
"date",
"genre",
"last_mod",
"og_title",
"og_album",
}.union(_remove)
if not retain_disc:
to_remove.union("disc", "track")
to_remove.update(key for key in album_dict.keys() if key.startswith("is_"))
for key in to_remove:
album_dict.pop(key, None)
return album_dict
def serialize_tracks(
tracks: list[Track], _remove: set = {}, retain_disc=False
) -> list[dict]:
return [track_serializer(t, _remove, retain_disc) for t in tracks]