mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-04 20:43:04 +00:00
rewrite album and artist stores using in-mem hashmap stores
This commit is contained in:
+66
-48
@@ -1,9 +1,13 @@
|
||||
from itertools import groupby
|
||||
import json
|
||||
from pprint import pprint
|
||||
import random
|
||||
from typing import Iterable
|
||||
|
||||
from app.db.sqlite.albumcolors import SQLiteAlbumMethods as aldb
|
||||
from app.lib.tagger import create_albums
|
||||
from app.models import Album, Track
|
||||
from app.store.artists import ArtistStore
|
||||
from app.utils.customlist import CustomList
|
||||
from app.utils.remove_duplicates import remove_duplicates
|
||||
|
||||
@@ -14,8 +18,19 @@ from app.utils.progressbar import tqdm
|
||||
ALBUM_LOAD_KEY = ""
|
||||
|
||||
|
||||
class AlbumMapEntry:
|
||||
def __init__(self, album: Album) -> None:
|
||||
self.album = album
|
||||
self.trackhashes: set[str] = set()
|
||||
|
||||
@property
|
||||
def basetitle(self):
|
||||
return self.album.base_title
|
||||
|
||||
|
||||
class AlbumStore:
|
||||
albums: list[Album] = CustomList()
|
||||
albummap: dict[str, AlbumMapEntry] = {}
|
||||
|
||||
@staticmethod
|
||||
def create_album(track: Track):
|
||||
@@ -36,43 +51,28 @@ class AlbumStore:
|
||||
global ALBUM_LOAD_KEY
|
||||
ALBUM_LOAD_KEY = instance_key
|
||||
|
||||
cls.albums = CustomList()
|
||||
|
||||
print("Loading albums... ", end="")
|
||||
tracks = remove_duplicates(TrackStore.tracks)
|
||||
|
||||
cls.albummap = {
|
||||
album.albumhash: AlbumMapEntry(album=album) for album in create_albums()
|
||||
}
|
||||
tracks = remove_duplicates(TrackStore.get_flat_list())
|
||||
tracks = sorted(tracks, key=lambda t: t.albumhash)
|
||||
grouped = groupby(tracks, lambda t: t.albumhash)
|
||||
|
||||
for albumhash, tracks in grouped:
|
||||
tracks = list(tracks)
|
||||
sample = tracks[0]
|
||||
cls.albummap[albumhash].trackhashes = {t.trackhash for t in tracks}
|
||||
|
||||
if sample is None:
|
||||
continue
|
||||
# db_albums: list[tuple] = aldb.get_all_albums()
|
||||
|
||||
count = len(list(tracks))
|
||||
duration = sum(t.duration for t in tracks)
|
||||
created_date = min(t.created_date for t in tracks)
|
||||
# for album in db_albums:
|
||||
# albumhash = album[1]
|
||||
# colors = json.loads(album[2])
|
||||
|
||||
album = AlbumStore.create_album(sample)
|
||||
|
||||
album.get_date_from_tracks(tracks)
|
||||
album.set_count(count)
|
||||
album.set_duration(duration)
|
||||
album.set_created_date(created_date)
|
||||
|
||||
cls.albums.append(album)
|
||||
|
||||
db_albums: list[tuple] = aldb.get_all_albums()
|
||||
|
||||
for album in db_albums:
|
||||
albumhash = album[1]
|
||||
colors = json.loads(album[2])
|
||||
|
||||
for _al in cls.albums:
|
||||
if _al.albumhash == albumhash:
|
||||
_al.set_colors(colors)
|
||||
break
|
||||
# for _al in cls.albums:
|
||||
# if _al.albumhash == albumhash:
|
||||
# _al.set_colors(colors)
|
||||
# break
|
||||
|
||||
print("Done!")
|
||||
|
||||
@@ -98,9 +98,7 @@ class AlbumStore:
|
||||
Returns N albums by the given albumartist, excluding the specified album.
|
||||
"""
|
||||
|
||||
albums = [
|
||||
album for album in cls.albums if artisthash in album.albumartists_hashes
|
||||
]
|
||||
albums = [album for album in cls.albums if artisthash in album.artisthashes]
|
||||
|
||||
albums = [
|
||||
album
|
||||
@@ -126,25 +124,11 @@ class AlbumStore:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_albums_by_hashes(cls, albumhashes: list[str]) -> list[Album]:
|
||||
def get_albums_by_hashes(cls, albumhashes: Iterable[str]) -> list[Album]:
|
||||
"""
|
||||
Returns albums by their hashes.
|
||||
"""
|
||||
albums_str = "-".join(albumhashes)
|
||||
albums = [a for a in cls.albums if a.albumhash in albums_str]
|
||||
|
||||
# sort albums by the order of the hashes
|
||||
albums.sort(key=lambda x: albumhashes.index(x.albumhash))
|
||||
return albums
|
||||
|
||||
@classmethod
|
||||
def get_albums_by_artisthash(cls, artisthash: str) -> list[Album]:
|
||||
"""
|
||||
Returns all albums by the given artist.
|
||||
"""
|
||||
return [
|
||||
album for album in cls.albums if artisthash in album.albumartists_hashes
|
||||
]
|
||||
return [cls.albummap[albumhash].album for albumhash in albumhashes]
|
||||
|
||||
@classmethod
|
||||
def count_albums_by_artisthash(cls, artisthash: str):
|
||||
@@ -174,3 +158,37 @@ class AlbumStore:
|
||||
Removes an album from the store.
|
||||
"""
|
||||
cls.albums = CustomList(a for a in cls.albums if a.albumhash != albumhash)
|
||||
|
||||
@classmethod
|
||||
def get_albums_by_artisthash(cls, hash: str):
|
||||
"""
|
||||
Returns all albums by the given artist hash.
|
||||
"""
|
||||
artist = ArtistStore.artistmap.get(hash)
|
||||
|
||||
if not artist:
|
||||
return []
|
||||
|
||||
return [cls.albummap[albumhash].album for albumhash in artist.albumhashes]
|
||||
|
||||
@classmethod
|
||||
def get_albums_by_artisthashes(cls, hashes: Iterable[str]):
|
||||
"""
|
||||
Returns all albums by the given artist hashes.
|
||||
"""
|
||||
albums = []
|
||||
for hash in hashes:
|
||||
albums.extend(cls.get_albums_by_artisthash(hash))
|
||||
|
||||
return albums
|
||||
|
||||
@classmethod
|
||||
def get_album_tracks(cls, albumhash: str) -> list[Track]:
|
||||
"""
|
||||
Returns all tracks for the given album hash.
|
||||
"""
|
||||
album = cls.albummap.get(albumhash)
|
||||
if not album:
|
||||
return []
|
||||
|
||||
return TrackStore.get_tracks_by_trackhashes(album.trackhashes)
|
||||
|
||||
+46
-16
@@ -1,19 +1,30 @@
|
||||
import json
|
||||
from typing import Iterable
|
||||
|
||||
from app.db.sqlite.artistcolors import SQLiteArtistMethods as ardb
|
||||
from app.lib.tagger import create_artists
|
||||
from app.models import Artist
|
||||
from app.utils.bisection import use_bisection
|
||||
from app.utils.customlist import CustomList
|
||||
from app.utils.progressbar import tqdm
|
||||
from .tracks import TrackStore
|
||||
|
||||
from .albums import AlbumStore
|
||||
# from .albums import AlbumStore
|
||||
from .tracks import TrackStore
|
||||
|
||||
ARTIST_LOAD_KEY = ""
|
||||
|
||||
|
||||
class ArtistMapEntry:
|
||||
def __init__(self, artist: Artist) -> None:
|
||||
self.artist = artist
|
||||
self.albumhashes: set[str] = set()
|
||||
self.trackhashes: set[str] = set()
|
||||
|
||||
|
||||
class ArtistStore:
|
||||
artists: list[Artist] = CustomList()
|
||||
artistmap: dict[str, ArtistMapEntry] = {}
|
||||
|
||||
@classmethod
|
||||
def load_artists(cls, instance_key: str):
|
||||
@@ -24,15 +35,27 @@ class ArtistStore:
|
||||
ARTIST_LOAD_KEY = instance_key
|
||||
|
||||
print("Loading artists... ", end="")
|
||||
cls.artists.clear()
|
||||
cls.artistmap.clear()
|
||||
|
||||
cls.artists.extend(get_all_artists(TrackStore.tracks, AlbumStore.albums))
|
||||
print("Done!")
|
||||
for artist in ardb.get_all_artists():
|
||||
cls.artistmap = {
|
||||
artist.artisthash: ArtistMapEntry(artist=artist)
|
||||
for artist in create_artists()
|
||||
}
|
||||
|
||||
for track in TrackStore.get_flat_list():
|
||||
if instance_key != ARTIST_LOAD_KEY:
|
||||
return
|
||||
|
||||
cls.map_artist_color(artist)
|
||||
for hash in track.artisthashes:
|
||||
cls.artistmap[hash].trackhashes.add(track.trackhash)
|
||||
cls.artistmap[hash].albumhashes.add(track.albumhash)
|
||||
|
||||
print("Done!")
|
||||
# for artist in ardb.get_all_artists():
|
||||
# if instance_key != ARTIST_LOAD_KEY:
|
||||
# return
|
||||
|
||||
# cls.map_artist_color(artist)
|
||||
|
||||
@classmethod
|
||||
def map_artist_color(cls, artist_tuple: tuple):
|
||||
@@ -65,24 +88,20 @@ class ArtistStore:
|
||||
cls.artists.append(artist)
|
||||
|
||||
@classmethod
|
||||
def get_artist_by_hash(cls, artisthash: str) -> Artist:
|
||||
def get_artist_by_hash(cls, artisthash: str):
|
||||
"""
|
||||
Returns an artist by its hash.P
|
||||
"""
|
||||
artists = sorted(cls.artists, key=lambda x: x.artisthash)
|
||||
try:
|
||||
artist = use_bisection(artists, "artisthash", [artisthash])[0]
|
||||
return artist
|
||||
except IndexError:
|
||||
return None
|
||||
entry = cls.artistmap.get(artisthash, None)
|
||||
if entry is not None:
|
||||
return entry.artist
|
||||
|
||||
@classmethod
|
||||
def get_artists_by_hashes(cls, artisthashes: list[str]) -> list[Artist]:
|
||||
def get_artists_by_hashes(cls, artisthashes: Iterable[str]):
|
||||
"""
|
||||
Returns artists by their hashes.
|
||||
"""
|
||||
artists = sorted(cls.artists, key=lambda x: x.artisthash)
|
||||
artists = use_bisection(artists, "artisthash", artisthashes)
|
||||
artists = [cls.get_artist_by_hash(hash) for hash in artisthashes]
|
||||
return [a for a in artists if a is not None]
|
||||
|
||||
@classmethod
|
||||
@@ -113,3 +132,14 @@ class ArtistStore:
|
||||
Removes an artist from the store.
|
||||
"""
|
||||
cls.artists = CustomList(a for a in cls.artists if a.artisthash != artisthash)
|
||||
|
||||
@classmethod
|
||||
def get_artist_tracks(cls, artisthash: str):
|
||||
"""
|
||||
Returns all tracks by the given artist hash.
|
||||
"""
|
||||
entry = cls.artistmap.get(artisthash)
|
||||
if entry is not None:
|
||||
return TrackStore.get_tracks_by_trackhashes(entry.trackhashes)
|
||||
|
||||
return []
|
||||
|
||||
+5
-4
@@ -1,8 +1,7 @@
|
||||
# from tqdm import tqdm
|
||||
|
||||
import itertools
|
||||
import sys
|
||||
from typing import Callable
|
||||
from typing import Callable, Iterable
|
||||
from flask_jwt_extended import current_user
|
||||
from app.db.libdata import TrackTable
|
||||
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||
@@ -243,7 +242,7 @@ class TrackStore:
|
||||
# ================================================
|
||||
|
||||
@classmethod
|
||||
def get_tracks_by_trackhashes(cls, trackhashes: list[str]) -> list[Track]:
|
||||
def get_tracks_by_trackhashes(cls, trackhashes: Iterable[str]) -> list[Track]:
|
||||
"""
|
||||
Returns a list of tracks by their hashes.
|
||||
"""
|
||||
@@ -259,7 +258,9 @@ class TrackStore:
|
||||
tracks.append(track)
|
||||
|
||||
# sort the tracks in the order of the given trackhashes
|
||||
tracks.sort(key=lambda t: trackhashes.index(t.trackhash))
|
||||
if type(trackhashes) == list:
|
||||
tracks.sort(key=lambda t: trackhashes.index(t.trackhash))
|
||||
|
||||
return tracks
|
||||
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user