mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 17:06:17 +00:00
Porting supysonic.api.browse
This commit is contained in:
parent
7401b4dec9
commit
95f77cc170
@ -96,8 +96,7 @@ def get_entity(cls, param="id"):
|
|||||||
eid = int(eid)
|
eid = int(eid)
|
||||||
else:
|
else:
|
||||||
eid = uuid.UUID(eid)
|
eid = uuid.UUID(eid)
|
||||||
entity = cls[eid]
|
return cls[eid]
|
||||||
return entity
|
|
||||||
|
|
||||||
|
|
||||||
def get_entity_id(cls, eid):
|
def get_entity_id(cls, eid):
|
||||||
@ -107,12 +106,12 @@ def get_entity_id(cls, eid):
|
|||||||
raise GenericError("Invalid ID")
|
raise GenericError("Invalid ID")
|
||||||
try:
|
try:
|
||||||
return int(eid)
|
return int(eid)
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
raise GenericError("Invalid ID")
|
raise GenericError("Invalid ID") from e
|
||||||
try:
|
try:
|
||||||
return uuid.UUID(eid)
|
return uuid.UUID(eid)
|
||||||
except (AttributeError, ValueError):
|
except (AttributeError, ValueError) as e:
|
||||||
raise GenericError("Invalid ID")
|
raise GenericError("Invalid ID") from e
|
||||||
|
|
||||||
|
|
||||||
def get_root_folder(id):
|
def get_root_folder(id):
|
||||||
@ -121,14 +120,13 @@ def get_root_folder(id):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
fid = int(id)
|
fid = int(id)
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
raise ValueError("Invalid folder ID")
|
raise ValueError("Invalid folder ID") from e
|
||||||
|
|
||||||
folder = Folder.get(id=fid, root=True)
|
try:
|
||||||
if folder is None:
|
return Folder.get(id=fid, root=True)
|
||||||
raise NotFound("Folder")
|
except Folder.DoesNotExist as e:
|
||||||
|
raise NotFound("Folder") from e
|
||||||
return folder
|
|
||||||
|
|
||||||
|
|
||||||
from .errors import *
|
from .errors import *
|
||||||
|
@ -9,6 +9,7 @@ import re
|
|||||||
import string
|
import string
|
||||||
|
|
||||||
from flask import current_app, request
|
from flask import current_app, request
|
||||||
|
from peewee import fn
|
||||||
|
|
||||||
from ..db import Folder, Artist, Album, Track
|
from ..db import Folder, Artist, Album, Track
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ def list_folders():
|
|||||||
{
|
{
|
||||||
"musicFolder": [
|
"musicFolder": [
|
||||||
{"id": str(f.id), "name": f.name}
|
{"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
|
ifModifiedSince = int(ifModifiedSince) / 1000
|
||||||
|
|
||||||
if musicFolderId is None:
|
if musicFolderId is None:
|
||||||
folders = Folder.select(lambda f: f.root)[:]
|
folders = Folder.select().where(Folder.root)[:]
|
||||||
else:
|
else:
|
||||||
folders = [get_root_folder(musicFolderId)]
|
folders = [get_root_folder(musicFolderId)]
|
||||||
|
|
||||||
@ -95,8 +96,8 @@ def list_indexes():
|
|||||||
artists = []
|
artists = []
|
||||||
children = []
|
children = []
|
||||||
for f in folders:
|
for f in folders:
|
||||||
artists += f.children.select()[:]
|
artists += f.children[:]
|
||||||
children += f.tracks.select()[:]
|
children += f.tracks[:]
|
||||||
|
|
||||||
indexes = build_indexes(artists)
|
indexes = build_indexes(artists)
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
@ -137,9 +138,11 @@ def list_genres():
|
|||||||
{
|
{
|
||||||
"genre": [
|
"genre": [
|
||||||
{"value": genre, "songCount": sc, "albumCount": ac}
|
{"value": genre, "songCount": sc, "albumCount": ac}
|
||||||
for genre, sc, ac in select(
|
for genre, sc, ac in Track.select(
|
||||||
(t.genre, count(), count(t.album)) for t in Track if t.genre
|
Track.genre, fn.count(), fn.count(Track.album.distinct())
|
||||||
)
|
)
|
||||||
|
.group_by(Track.genre)
|
||||||
|
.tuples()
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -152,7 +155,7 @@ def list_artists():
|
|||||||
query = Artist.select()
|
query = Artist.select()
|
||||||
if mfid is not None:
|
if mfid is not None:
|
||||||
folder = get_root_folder(mfid)
|
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)
|
indexes = build_indexes(query)
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
|
@ -150,7 +150,7 @@ class Folder(PathMixin, db.Model):
|
|||||||
"name": self.name,
|
"name": self.name,
|
||||||
"child": [
|
"child": [
|
||||||
f.as_subsonic_child(user)
|
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)
|
t.as_subsonic_child(user, client)
|
||||||
|
@ -9,8 +9,6 @@ import time
|
|||||||
import unittest
|
import unittest
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from pony.orm import db_session
|
|
||||||
|
|
||||||
from supysonic.db import Folder, Artist, Album, Track
|
from supysonic.db import Folder, Artist, Album, Track
|
||||||
|
|
||||||
from .apitestbase import ApiTestBase
|
from .apitestbase import ApiTestBase
|
||||||
@ -20,51 +18,52 @@ class BrowseTestCase(ApiTestBase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
with db_session:
|
self.empty_root = Folder.create(root=True, name="Empty root", path="/tmp")
|
||||||
self.empty_root = Folder(root=True, name="Empty root", path="/tmp")
|
self.root = Folder.create(root=True, name="Root folder", path="tests/assets")
|
||||||
self.root = Folder(root=True, name="Root folder", path="tests/assets")
|
|
||||||
|
|
||||||
for letter in "ABC":
|
for letter in "ABC":
|
||||||
folder = Folder(
|
folder = Folder.create(
|
||||||
name=letter + "rtist",
|
name=letter + "rtist",
|
||||||
path="tests/assets/{}rtist".format(letter),
|
path="tests/assets/{}rtist".format(letter),
|
||||||
parent=self.root,
|
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":
|
for num, song in enumerate(["One", "Two", "Three"]):
|
||||||
afolder = Folder(
|
Track.create(
|
||||||
name=letter + lether + "lbum",
|
disc=1,
|
||||||
path="tests/assets/{0}rtist/{0}{1}lbum".format(letter, lether),
|
number=num,
|
||||||
parent=folder,
|
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)
|
self.assertEqual(Folder.select().count(), 11)
|
||||||
|
self.assertEqual(Folder.select().where(Folder.root).count(), 2)
|
||||||
for num, song in enumerate(["One", "Two", "Three"]):
|
self.assertEqual(Artist.select().count(), 3)
|
||||||
Track(
|
self.assertEqual(Album.select().count(), 6)
|
||||||
disc=1,
|
self.assertEqual(Track.select().count(), 18)
|
||||||
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)
|
|
||||||
|
|
||||||
def test_get_music_folders(self):
|
def test_get_music_folders(self):
|
||||||
rv, child = self._make_request("getMusicFolders", tag="musicFolders")
|
rv, child = self._make_request("getMusicFolders", tag="musicFolders")
|
||||||
@ -86,8 +85,7 @@ class BrowseTestCase(ApiTestBase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(len(child), 0)
|
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(
|
rv, child = self._make_request(
|
||||||
"getIndexes", {"musicFolderId": str(fid)}, tag="indexes"
|
"getIndexes", {"musicFolderId": str(fid)}, tag="indexes"
|
||||||
)
|
)
|
||||||
@ -106,27 +104,26 @@ class BrowseTestCase(ApiTestBase):
|
|||||||
self._make_request("getMusicDirectory", {"id": 1234567890}, error=70)
|
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
|
# 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():
|
||||||
for f in Folder.select():
|
rv, child = self._make_request(
|
||||||
rv, child = self._make_request(
|
"getMusicDirectory", {"id": str(f.id)}, tag="directory"
|
||||||
"getMusicDirectory", {"id": str(f.id)}, tag="directory"
|
)
|
||||||
)
|
self.assertEqual(child.get("id"), str(f.id))
|
||||||
self.assertEqual(child.get("id"), str(f.id))
|
self.assertEqual(child.get("name"), f.name)
|
||||||
self.assertEqual(child.get("name"), f.name)
|
self.assertEqual(len(child), f.children.count() + f.tracks.count())
|
||||||
self.assertEqual(len(child), f.children.count() + f.tracks.count())
|
for dbc, xmlc in zip(
|
||||||
for dbc, xmlc in zip(
|
sorted(f.children, key=lambda c: c.name),
|
||||||
sorted(f.children, key=lambda c: c.name),
|
sorted(child, key=lambda c: c.get("title")),
|
||||||
sorted(child, key=lambda c: c.get("title")),
|
):
|
||||||
):
|
self.assertEqual(dbc.name, xmlc.get("title"))
|
||||||
self.assertEqual(dbc.name, xmlc.get("title"))
|
self.assertEqual(xmlc.get("artist"), f.name)
|
||||||
self.assertEqual(xmlc.get("artist"), f.name)
|
self.assertEqual(xmlc.get("parent"), str(f.id))
|
||||||
self.assertEqual(xmlc.get("parent"), str(f.id))
|
for t, xmlc in zip(
|
||||||
for t, xmlc in zip(
|
sorted(f.tracks, key=lambda t: t.title),
|
||||||
sorted(f.tracks, key=lambda t: t.title),
|
sorted(child, key=lambda c: c.get("title")),
|
||||||
sorted(child, key=lambda c: c.get("title")),
|
):
|
||||||
):
|
self.assertEqual(t.title, xmlc.get("title"))
|
||||||
self.assertEqual(t.title, xmlc.get("title"))
|
self.assertEqual(xmlc.get("parent"), str(f.id))
|
||||||
self.assertEqual(xmlc.get("parent"), str(f.id))
|
|
||||||
|
|
||||||
def test_get_artists(self):
|
def test_get_artists(self):
|
||||||
# same as getIndexes standard case
|
# 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": "artist"}, error=0)
|
||||||
self._make_request("getArtist", {"id": str(uuid.uuid4())}, error=70)
|
self._make_request("getArtist", {"id": str(uuid.uuid4())}, error=70)
|
||||||
|
|
||||||
with db_session:
|
for ar in Artist.select():
|
||||||
for ar in Artist.select():
|
rv, child = self._make_request(
|
||||||
rv, child = self._make_request(
|
"getArtist", {"id": str(ar.id)}, tag="artist"
|
||||||
"getArtist", {"id": str(ar.id)}, tag="artist"
|
)
|
||||||
)
|
self.assertEqual(child.get("id"), str(ar.id))
|
||||||
self.assertEqual(child.get("id"), str(ar.id))
|
self.assertEqual(child.get("albumCount"), str(len(child)))
|
||||||
self.assertEqual(child.get("albumCount"), str(len(child)))
|
self.assertEqual(len(child), ar.albums.count())
|
||||||
self.assertEqual(len(child), ar.albums.count())
|
for dal, xal in zip(
|
||||||
for dal, xal in zip(
|
sorted(ar.albums, key=lambda a: a.name),
|
||||||
sorted(ar.albums, key=lambda a: a.name),
|
sorted(child, key=lambda c: c.get("name")),
|
||||||
sorted(child, key=lambda c: c.get("name")),
|
):
|
||||||
):
|
self.assertEqual(dal.name, xal.get("name"))
|
||||||
self.assertEqual(dal.name, xal.get("name"))
|
self.assertEqual(
|
||||||
self.assertEqual(
|
xal.get("artist"), ar.name
|
||||||
xal.get("artist"), ar.name
|
) # could break with a better dataset
|
||||||
) # could break with a better dataset
|
self.assertEqual(xal.get("artistId"), str(ar.id)) # see above
|
||||||
self.assertEqual(xal.get("artistId"), str(ar.id)) # see above
|
|
||||||
|
|
||||||
def test_get_album(self):
|
def test_get_album(self):
|
||||||
self._make_request("getAlbum", error=10)
|
self._make_request("getAlbum", error=10)
|
||||||
self._make_request("getAlbum", {"id": "nastynasty"}, error=0)
|
self._make_request("getAlbum", {"id": "nastynasty"}, error=0)
|
||||||
self._make_request("getAlbum", {"id": str(uuid.uuid4())}, error=70)
|
self._make_request("getAlbum", {"id": str(uuid.uuid4())}, error=70)
|
||||||
|
|
||||||
with db_session:
|
a = Album.select().first()
|
||||||
a = Album.select().first()
|
rv, child = self._make_request("getAlbum", {"id": str(a.id)}, tag="album")
|
||||||
rv, child = self._make_request("getAlbum", {"id": str(a.id)}, tag="album")
|
self.assertEqual(child.get("id"), str(a.id))
|
||||||
self.assertEqual(child.get("id"), str(a.id))
|
self.assertEqual(child.get("songCount"), str(len(child)))
|
||||||
self.assertEqual(child.get("songCount"), str(len(child)))
|
|
||||||
|
|
||||||
self.assertEqual(len(child), a.tracks.count())
|
self.assertEqual(len(child), a.tracks.count())
|
||||||
for dal, xal in zip(
|
for dal, xal in zip(
|
||||||
sorted(a.tracks, key=lambda t: t.title),
|
sorted(a.tracks, key=lambda t: t.title),
|
||||||
sorted(child, key=lambda c: c.get("title")),
|
sorted(child, key=lambda c: c.get("title")),
|
||||||
):
|
):
|
||||||
self.assertEqual(dal.title, xal.get("title"))
|
self.assertEqual(dal.title, xal.get("title"))
|
||||||
self.assertEqual(xal.get("album"), a.name)
|
self.assertEqual(xal.get("album"), a.name)
|
||||||
self.assertEqual(xal.get("albumId"), str(a.id))
|
self.assertEqual(xal.get("albumId"), str(a.id))
|
||||||
|
|
||||||
def test_get_song(self):
|
def test_get_song(self):
|
||||||
self._make_request("getSong", error=10)
|
self._make_request("getSong", error=10)
|
||||||
self._make_request("getSong", {"id": "nastynasty"}, error=0)
|
self._make_request("getSong", {"id": "nastynasty"}, error=0)
|
||||||
self._make_request("getSong", {"id": str(uuid.uuid4())}, error=70)
|
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")
|
self._make_request("getSong", {"id": str(s.id)}, tag="song")
|
||||||
|
|
||||||
def test_get_videos(self):
|
def test_get_videos(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user