1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-11-10 04:02:17 +00:00

Porting supysonic.api.browse

This commit is contained in:
Alban Féron 2022-12-18 18:03:51 +01:00
parent 7401b4dec9
commit 95f77cc170
No known key found for this signature in database
GPG Key ID: 8CE0313646D16165
4 changed files with 112 additions and 117 deletions

View File

@ -96,8 +96,7 @@ def get_entity(cls, param="id"):
eid = int(eid)
else:
eid = uuid.UUID(eid)
entity = cls[eid]
return entity
return cls[eid]
def get_entity_id(cls, eid):
@ -107,12 +106,12 @@ def get_entity_id(cls, eid):
raise GenericError("Invalid ID")
try:
return int(eid)
except ValueError:
raise GenericError("Invalid ID")
except ValueError as e:
raise GenericError("Invalid ID") from e
try:
return uuid.UUID(eid)
except (AttributeError, ValueError):
raise GenericError("Invalid ID")
except (AttributeError, ValueError) as e:
raise GenericError("Invalid ID") from e
def get_root_folder(id):
@ -121,14 +120,13 @@ def get_root_folder(id):
try:
fid = int(id)
except ValueError:
raise ValueError("Invalid folder ID")
except ValueError as e:
raise ValueError("Invalid folder ID") from e
folder = Folder.get(id=fid, root=True)
if folder is None:
raise NotFound("Folder")
return folder
try:
return Folder.get(id=fid, root=True)
except Folder.DoesNotExist as e:
raise NotFound("Folder") from e
from .errors import *

View File

@ -9,6 +9,7 @@ import re
import string
from flask import current_app, request
from peewee import fn
from ..db import Folder, Artist, Album, Track
@ -22,7 +23,7 @@ def list_folders():
{
"musicFolder": [
{"id": str(f.id), "name": f.name}
for f in Folder.select(lambda f: f.root).order_by(Folder.name)
for f in Folder.select().where(Folder.root).order_by(Folder.name)
]
},
)
@ -77,7 +78,7 @@ def list_indexes():
ifModifiedSince = int(ifModifiedSince) / 1000
if musicFolderId is None:
folders = Folder.select(lambda f: f.root)[:]
folders = Folder.select().where(Folder.root)[:]
else:
folders = [get_root_folder(musicFolderId)]
@ -95,8 +96,8 @@ def list_indexes():
artists = []
children = []
for f in folders:
artists += f.children.select()[:]
children += f.tracks.select()[:]
artists += f.children[:]
children += f.tracks[:]
indexes = build_indexes(artists)
return request.formatter(
@ -137,9 +138,11 @@ def list_genres():
{
"genre": [
{"value": genre, "songCount": sc, "albumCount": ac}
for genre, sc, ac in select(
(t.genre, count(), count(t.album)) for t in Track if t.genre
for genre, sc, ac in Track.select(
Track.genre, fn.count(), fn.count(Track.album.distinct())
)
.group_by(Track.genre)
.tuples()
]
},
)
@ -152,7 +155,7 @@ def list_artists():
query = Artist.select()
if mfid is not None:
folder = get_root_folder(mfid)
query = Artist.select(lambda a: folder in a.tracks.root_folder)
query = Artist.select().join(Track).where(Track.root_folder == folder)
indexes = build_indexes(query)
return request.formatter(

View File

@ -150,7 +150,7 @@ class Folder(PathMixin, db.Model):
"name": self.name,
"child": [
f.as_subsonic_child(user)
for f in self.children.order_by(lambda c: c.name.lower())
for f in self.children.order_by(fn.lower(Folder.name))
]
+ [
t.as_subsonic_child(user, client)

View File

@ -9,8 +9,6 @@ import time
import unittest
import uuid
from pony.orm import db_session
from supysonic.db import Folder, Artist, Album, Track
from .apitestbase import ApiTestBase
@ -20,51 +18,52 @@ class BrowseTestCase(ApiTestBase):
def setUp(self):
super().setUp()
with db_session:
self.empty_root = Folder(root=True, name="Empty root", path="/tmp")
self.root = Folder(root=True, name="Root folder", path="tests/assets")
self.empty_root = Folder.create(root=True, name="Empty root", path="/tmp")
self.root = Folder.create(root=True, name="Root folder", path="tests/assets")
for letter in "ABC":
folder = Folder(
name=letter + "rtist",
path="tests/assets/{}rtist".format(letter),
parent=self.root,
for letter in "ABC":
folder = Folder.create(
name=letter + "rtist",
path="tests/assets/{}rtist".format(letter),
root=False,
parent=self.root,
)
artist = Artist.create(name=letter + "rtist")
for lether in "AB":
afolder = Folder.create(
name=letter + lether + "lbum",
path="tests/assets/{0}rtist/{0}{1}lbum".format(letter, lether),
root=False,
parent=folder,
)
artist = Artist(name=letter + "rtist")
album = Album.create(name=letter + lether + "lbum", artist=artist)
for lether in "AB":
afolder = Folder(
name=letter + lether + "lbum",
path="tests/assets/{0}rtist/{0}{1}lbum".format(letter, lether),
parent=folder,
for num, song in enumerate(["One", "Two", "Three"]):
Track.create(
disc=1,
number=num,
title=song,
duration=2,
album=album,
artist=artist,
genre="Music!",
bitrate=320,
path="tests/assets/{0}rtist/{0}{1}lbum/{2}".format(
letter, lether, song
),
last_modification=0,
root_folder=self.root,
folder=afolder,
)
album = Album(name=letter + lether + "lbum", artist=artist)
for num, song in enumerate(["One", "Two", "Three"]):
Track(
disc=1,
number=num,
title=song,
duration=2,
album=album,
artist=artist,
genre="Music!",
bitrate=320,
path="tests/assets/{0}rtist/{0}{1}lbum/{2}".format(
letter, lether, song
),
last_modification=0,
root_folder=self.root,
folder=afolder,
)
self.assertEqual(Folder.select().count(), 11)
self.assertEqual(Folder.select(lambda f: f.root).count(), 2)
self.assertEqual(Artist.select().count(), 3)
self.assertEqual(Album.select().count(), 6)
self.assertEqual(Track.select().count(), 18)
self.assertEqual(Folder.select().count(), 11)
self.assertEqual(Folder.select().where(Folder.root).count(), 2)
self.assertEqual(Artist.select().count(), 3)
self.assertEqual(Album.select().count(), 6)
self.assertEqual(Track.select().count(), 18)
def test_get_music_folders(self):
rv, child = self._make_request("getMusicFolders", tag="musicFolders")
@ -86,8 +85,7 @@ class BrowseTestCase(ApiTestBase):
)
self.assertEqual(len(child), 0)
with db_session:
fid = Folder.get(name="Empty root").id
fid = Folder.get(name="Empty root").id
rv, child = self._make_request(
"getIndexes", {"musicFolderId": str(fid)}, tag="indexes"
)
@ -106,27 +104,26 @@ class BrowseTestCase(ApiTestBase):
self._make_request("getMusicDirectory", {"id": 1234567890}, error=70)
# should test with folders with both children folders and tracks. this code would break in that case
with db_session:
for f in Folder.select():
rv, child = self._make_request(
"getMusicDirectory", {"id": str(f.id)}, tag="directory"
)
self.assertEqual(child.get("id"), str(f.id))
self.assertEqual(child.get("name"), f.name)
self.assertEqual(len(child), f.children.count() + f.tracks.count())
for dbc, xmlc in zip(
sorted(f.children, key=lambda c: c.name),
sorted(child, key=lambda c: c.get("title")),
):
self.assertEqual(dbc.name, xmlc.get("title"))
self.assertEqual(xmlc.get("artist"), f.name)
self.assertEqual(xmlc.get("parent"), str(f.id))
for t, xmlc in zip(
sorted(f.tracks, key=lambda t: t.title),
sorted(child, key=lambda c: c.get("title")),
):
self.assertEqual(t.title, xmlc.get("title"))
self.assertEqual(xmlc.get("parent"), str(f.id))
for f in Folder.select():
rv, child = self._make_request(
"getMusicDirectory", {"id": str(f.id)}, tag="directory"
)
self.assertEqual(child.get("id"), str(f.id))
self.assertEqual(child.get("name"), f.name)
self.assertEqual(len(child), f.children.count() + f.tracks.count())
for dbc, xmlc in zip(
sorted(f.children, key=lambda c: c.name),
sorted(child, key=lambda c: c.get("title")),
):
self.assertEqual(dbc.name, xmlc.get("title"))
self.assertEqual(xmlc.get("artist"), f.name)
self.assertEqual(xmlc.get("parent"), str(f.id))
for t, xmlc in zip(
sorted(f.tracks, key=lambda t: t.title),
sorted(child, key=lambda c: c.get("title")),
):
self.assertEqual(t.title, xmlc.get("title"))
self.assertEqual(xmlc.get("parent"), str(f.id))
def test_get_artists(self):
# same as getIndexes standard case
@ -158,51 +155,48 @@ class BrowseTestCase(ApiTestBase):
self._make_request("getArtist", {"id": "artist"}, error=0)
self._make_request("getArtist", {"id": str(uuid.uuid4())}, error=70)
with db_session:
for ar in Artist.select():
rv, child = self._make_request(
"getArtist", {"id": str(ar.id)}, tag="artist"
)
self.assertEqual(child.get("id"), str(ar.id))
self.assertEqual(child.get("albumCount"), str(len(child)))
self.assertEqual(len(child), ar.albums.count())
for dal, xal in zip(
sorted(ar.albums, key=lambda a: a.name),
sorted(child, key=lambda c: c.get("name")),
):
self.assertEqual(dal.name, xal.get("name"))
self.assertEqual(
xal.get("artist"), ar.name
) # could break with a better dataset
self.assertEqual(xal.get("artistId"), str(ar.id)) # see above
for ar in Artist.select():
rv, child = self._make_request(
"getArtist", {"id": str(ar.id)}, tag="artist"
)
self.assertEqual(child.get("id"), str(ar.id))
self.assertEqual(child.get("albumCount"), str(len(child)))
self.assertEqual(len(child), ar.albums.count())
for dal, xal in zip(
sorted(ar.albums, key=lambda a: a.name),
sorted(child, key=lambda c: c.get("name")),
):
self.assertEqual(dal.name, xal.get("name"))
self.assertEqual(
xal.get("artist"), ar.name
) # could break with a better dataset
self.assertEqual(xal.get("artistId"), str(ar.id)) # see above
def test_get_album(self):
self._make_request("getAlbum", error=10)
self._make_request("getAlbum", {"id": "nastynasty"}, error=0)
self._make_request("getAlbum", {"id": str(uuid.uuid4())}, error=70)
with db_session:
a = Album.select().first()
rv, child = self._make_request("getAlbum", {"id": str(a.id)}, tag="album")
self.assertEqual(child.get("id"), str(a.id))
self.assertEqual(child.get("songCount"), str(len(child)))
a = Album.select().first()
rv, child = self._make_request("getAlbum", {"id": str(a.id)}, tag="album")
self.assertEqual(child.get("id"), str(a.id))
self.assertEqual(child.get("songCount"), str(len(child)))
self.assertEqual(len(child), a.tracks.count())
for dal, xal in zip(
sorted(a.tracks, key=lambda t: t.title),
sorted(child, key=lambda c: c.get("title")),
):
self.assertEqual(dal.title, xal.get("title"))
self.assertEqual(xal.get("album"), a.name)
self.assertEqual(xal.get("albumId"), str(a.id))
self.assertEqual(len(child), a.tracks.count())
for dal, xal in zip(
sorted(a.tracks, key=lambda t: t.title),
sorted(child, key=lambda c: c.get("title")),
):
self.assertEqual(dal.title, xal.get("title"))
self.assertEqual(xal.get("album"), a.name)
self.assertEqual(xal.get("albumId"), str(a.id))
def test_get_song(self):
self._make_request("getSong", error=10)
self._make_request("getSong", {"id": "nastynasty"}, error=0)
self._make_request("getSong", {"id": str(uuid.uuid4())}, error=70)
with db_session:
s = Track.select().first()
s = Track.select().first()
self._make_request("getSong", {"id": str(s.id)}, tag="song")
def test_get_videos(self):