mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 08:56:17 +00:00
Porting supysonic.api.albums_songs
This commit is contained in:
parent
c5246c74bb
commit
2b472b4d97
@ -11,8 +11,7 @@ import binascii
|
|||||||
import uuid
|
import uuid
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
from pony.orm import ObjectNotFound, TransactionIntegrityError
|
from peewee import IntegrityError
|
||||||
from pony.orm import commit
|
|
||||||
|
|
||||||
from ..db import ClientPrefs, Folder
|
from ..db import ClientPrefs, Folder
|
||||||
from ..managers.user import UserManager
|
from ..managers.user import UserManager
|
||||||
@ -82,15 +81,12 @@ def get_client_prefs():
|
|||||||
client = request.values["c"]
|
client = request.values["c"]
|
||||||
try:
|
try:
|
||||||
request.client = ClientPrefs[request.user, client]
|
request.client = ClientPrefs[request.user, client]
|
||||||
except ObjectNotFound:
|
except ClientPrefs.DoesNotExist:
|
||||||
try:
|
try:
|
||||||
request.client = ClientPrefs(user=request.user, client_name=client)
|
request.client = ClientPrefs.create(user=request.user, client_name=client)
|
||||||
commit()
|
except IntegrityError:
|
||||||
except TransactionIntegrityError:
|
|
||||||
# We might have hit a race condition here, another request already created
|
# We might have hit a race condition here, another request already created
|
||||||
# the ClientPrefs. Issue #220
|
# the ClientPrefs. Issue #220
|
||||||
# Reload the user or Pony will complain about different transactions
|
|
||||||
request.user = UserManager.get(request.user.id)
|
|
||||||
request.client = ClientPrefs[request.user, client]
|
request.client = ClientPrefs[request.user, client]
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,19 +7,21 @@
|
|||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from flask import request
|
from flask import request
|
||||||
from pony.orm import select, desc, avg, max, min, count, between, distinct
|
from peewee import fn, JOIN
|
||||||
|
|
||||||
from ..db import (
|
from ..db import (
|
||||||
Folder,
|
Folder,
|
||||||
|
Artist,
|
||||||
Album,
|
Album,
|
||||||
Track,
|
Track,
|
||||||
StarredFolder,
|
StarredFolder,
|
||||||
StarredArtist,
|
StarredArtist,
|
||||||
StarredAlbum,
|
StarredAlbum,
|
||||||
StarredTrack,
|
StarredTrack,
|
||||||
|
RatingFolder,
|
||||||
User,
|
User,
|
||||||
)
|
)
|
||||||
from ..db import now
|
from ..db import now, random
|
||||||
|
|
||||||
from . import api_routing, get_root_folder
|
from . import api_routing, get_root_folder
|
||||||
from .exceptions import GenericError
|
from .exceptions import GenericError
|
||||||
@ -39,20 +41,20 @@ def rand_songs():
|
|||||||
|
|
||||||
query = Track.select()
|
query = Track.select()
|
||||||
if fromYear:
|
if fromYear:
|
||||||
query = query.filter(lambda t: t.year >= fromYear)
|
query = query.where(Track.year >= fromYear)
|
||||||
if toYear:
|
if toYear:
|
||||||
query = query.filter(lambda t: t.year <= toYear)
|
query = query.where(Track.year <= toYear)
|
||||||
if genre:
|
if genre:
|
||||||
query = query.filter(lambda t: t.genre == genre)
|
query = query.where(Track.genre == genre)
|
||||||
if root:
|
if root:
|
||||||
query = query.filter(lambda t: t.root_folder == root)
|
query = query.where(Track.root_folder == root)
|
||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"randomSongs",
|
"randomSongs",
|
||||||
{
|
{
|
||||||
"song": [
|
"song": [
|
||||||
t.as_subsonic_child(request.user, request.client)
|
t.as_subsonic_child(request.user, request.client)
|
||||||
for t in query.without_distinct().random(size)
|
for t in query.order_by(random()).limit(size)
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -67,58 +69,52 @@ def album_list():
|
|||||||
offset = int(offset) if offset else 0
|
offset = int(offset) if offset else 0
|
||||||
root = get_root_folder(mfid)
|
root = get_root_folder(mfid)
|
||||||
|
|
||||||
query = select(t.folder for t in Track)
|
query = Track.select(Track.folder).join(Folder).group_by(Track.folder)
|
||||||
if root is not None:
|
if root is not None:
|
||||||
query = select(t.folder for t in Track if t.root_folder == root)
|
query = query.where(Track.root_folder == root)
|
||||||
|
|
||||||
if ltype == "random":
|
if ltype == "random":
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"albumList",
|
"albumList",
|
||||||
{
|
{
|
||||||
"album": [
|
"album": [
|
||||||
a.as_subsonic_child(request.user)
|
t.folder.as_subsonic_child(request.user)
|
||||||
for a in distinct(query.random(size))
|
for t in query.order_by(random()).limit(size)
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
elif ltype == "newest":
|
elif ltype == "newest":
|
||||||
query = query.sort_by(desc(Folder.created)).distinct()
|
query = query.order_by(Folder.created.desc()).distinct()
|
||||||
elif ltype == "highest":
|
elif ltype == "highest":
|
||||||
query = query.sort_by(lambda f: desc(avg(f.ratings.rating)))
|
query = query.join(RatingFolder, JOIN.LEFT_OUTER).order_by(
|
||||||
|
fn.avg(RatingFolder.rating).desc()
|
||||||
|
)
|
||||||
elif ltype == "frequent":
|
elif ltype == "frequent":
|
||||||
query = query.sort_by(lambda f: desc(avg(f.tracks.play_count)))
|
query = query.order_by(fn.avg(Track.play_count).desc())
|
||||||
elif ltype == "recent":
|
elif ltype == "recent":
|
||||||
query = select(
|
query = query.where(Track.last_play.is_null(False)).order_by(
|
||||||
t.folder for t in Track if max(t.folder.tracks.last_play) is not None
|
fn.max(Track.last_play).desc()
|
||||||
)
|
)
|
||||||
if root is not None:
|
|
||||||
query = query.where(lambda t: t.root_folder == root)
|
|
||||||
query = query.sort_by(lambda f: desc(max(f.tracks.last_play)))
|
|
||||||
elif ltype == "starred":
|
elif ltype == "starred":
|
||||||
query = select(
|
query = query.join(StarredFolder).where(StarredFolder.user == request.user)
|
||||||
s.starred
|
|
||||||
for s in StarredFolder
|
|
||||||
if s.user.id == request.user.id and count(s.starred.tracks) > 0
|
|
||||||
)
|
|
||||||
if root is not None:
|
|
||||||
query = query.filter(lambda f: f.path.startswith(root.path))
|
|
||||||
elif ltype == "alphabeticalByName":
|
elif ltype == "alphabeticalByName":
|
||||||
query = query.sort_by(Folder.name).distinct()
|
query = query.order_by(Folder.name).distinct()
|
||||||
elif ltype == "alphabeticalByArtist":
|
elif ltype == "alphabeticalByArtist":
|
||||||
query = query.sort_by(lambda f: f.parent.name + f.name)
|
parent = Folder.alias()
|
||||||
|
query = query.join(parent).order_by(parent.name, Folder.name)
|
||||||
elif ltype == "byYear":
|
elif ltype == "byYear":
|
||||||
startyear = int(request.values["fromYear"])
|
startyear = int(request.values["fromYear"])
|
||||||
endyear = int(request.values["toYear"])
|
endyear = int(request.values["toYear"])
|
||||||
query = query.where(
|
query = query.where(
|
||||||
lambda t: between(t.year, min(startyear, endyear), max(startyear, endyear))
|
Track.year.between(min(startyear, endyear), max(startyear, endyear))
|
||||||
)
|
)
|
||||||
|
order = fn.min(Track.year)
|
||||||
if endyear < startyear:
|
if endyear < startyear:
|
||||||
query = query.sort_by(lambda f: desc(min(f.tracks.year)))
|
order = order.desc()
|
||||||
else:
|
query = query.order_by(order)
|
||||||
query = query.sort_by(lambda f: min(f.tracks.year))
|
|
||||||
elif ltype == "byGenre":
|
elif ltype == "byGenre":
|
||||||
genre = request.values["genre"]
|
genre = request.values["genre"]
|
||||||
query = query.where(lambda t: t.genre == genre)
|
query = query.where(Track.genre == genre)
|
||||||
else:
|
else:
|
||||||
raise GenericError("Unknown search type")
|
raise GenericError("Unknown search type")
|
||||||
|
|
||||||
@ -126,7 +122,8 @@ def album_list():
|
|||||||
"albumList",
|
"albumList",
|
||||||
{
|
{
|
||||||
"album": [
|
"album": [
|
||||||
f.as_subsonic_child(request.user) for f in query.limit(size, offset)
|
t.folder.as_subsonic_child(request.user)
|
||||||
|
for t in query.limit(size).offset(offset)
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -141,46 +138,49 @@ def album_list_id3():
|
|||||||
offset = int(offset) if offset else 0
|
offset = int(offset) if offset else 0
|
||||||
root = get_root_folder(mfid)
|
root = get_root_folder(mfid)
|
||||||
|
|
||||||
query = Album.select()
|
query = Album.select().join(Track).group_by(Album)
|
||||||
if root is not None:
|
if root is not None:
|
||||||
query = query.where(lambda a: root in a.tracks.root_folder)
|
query = query.where(Track.root_folder == root)
|
||||||
|
|
||||||
if ltype == "random":
|
if ltype == "random":
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"albumList2",
|
"albumList2",
|
||||||
{"album": [a.as_subsonic_album(request.user) for a in query.random(size)]},
|
{
|
||||||
|
"album": [
|
||||||
|
a.as_subsonic_album(request.user)
|
||||||
|
for a in query.order_by(random()).limit(size)
|
||||||
|
]
|
||||||
|
},
|
||||||
)
|
)
|
||||||
elif ltype == "newest":
|
elif ltype == "newest":
|
||||||
query = query.order_by(lambda a: desc(min(a.tracks.created)))
|
query = query.order_by(fn.min(Track.created).desc())
|
||||||
elif ltype == "frequent":
|
elif ltype == "frequent":
|
||||||
query = query.order_by(lambda a: desc(avg(a.tracks.play_count)))
|
query = query.order_by(fn.avg(Track.play_count).desc())
|
||||||
elif ltype == "recent":
|
elif ltype == "recent":
|
||||||
query = query.where(lambda a: max(a.tracks.last_play) is not None).order_by(
|
query = query.where(Track.last_play.is_null(False)).order_by(
|
||||||
lambda a: desc(max(a.tracks.last_play))
|
fn.max(Track.last_play).desc()
|
||||||
)
|
)
|
||||||
elif ltype == "starred":
|
elif ltype == "starred":
|
||||||
query = select(s.starred for s in StarredAlbum if s.user.id == request.user.id)
|
query = (
|
||||||
if root is not None:
|
query.switch().join(StarredAlbum).where(StarredAlbum.user == request.user)
|
||||||
query = query.filter(lambda a: root in a.tracks.root_folder)
|
)
|
||||||
elif ltype == "alphabeticalByName":
|
elif ltype == "alphabeticalByName":
|
||||||
query = query.order_by(Album.name)
|
query = query.order_by(Album.name)
|
||||||
elif ltype == "alphabeticalByArtist":
|
elif ltype == "alphabeticalByArtist":
|
||||||
query = query.order_by(lambda a: a.artist.name + a.name)
|
query = query.switch().join(Artist).order_by(Artist.name, Album.name)
|
||||||
elif ltype == "byYear":
|
elif ltype == "byYear":
|
||||||
startyear = int(request.values["fromYear"])
|
startyear = int(request.values["fromYear"])
|
||||||
endyear = int(request.values["toYear"])
|
endyear = int(request.values["toYear"])
|
||||||
query = query.where(
|
query = query.having(
|
||||||
lambda a: between(
|
fn.min(Track.year).between(min(startyear, endyear), max(startyear, endyear))
|
||||||
min(a.tracks.year), min(startyear, endyear), max(startyear, endyear)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
order = fn.min(Track.year)
|
||||||
if endyear < startyear:
|
if endyear < startyear:
|
||||||
query = query.order_by(lambda a: desc(min(a.tracks.year)))
|
order = order.desc()
|
||||||
else:
|
query = query.order_by(order)
|
||||||
query = query.order_by(lambda a: min(a.tracks.year))
|
|
||||||
elif ltype == "byGenre":
|
elif ltype == "byGenre":
|
||||||
genre = request.values["genre"]
|
genre = request.values["genre"]
|
||||||
query = query.where(lambda a: genre in a.tracks.genre)
|
query = query.where(Track.genre == genre)
|
||||||
else:
|
else:
|
||||||
raise GenericError("Unknown search type")
|
raise GenericError("Unknown search type")
|
||||||
|
|
||||||
@ -188,7 +188,8 @@ def album_list_id3():
|
|||||||
"albumList2",
|
"albumList2",
|
||||||
{
|
{
|
||||||
"album": [
|
"album": [
|
||||||
f.as_subsonic_album(request.user) for f in query.limit(size, offset)
|
a.as_subsonic_album(request.user)
|
||||||
|
for a in query.limit(size).offset(offset)
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -203,9 +204,9 @@ def songs_by_genre():
|
|||||||
offset = int(offset) if offset else 0
|
offset = int(offset) if offset else 0
|
||||||
root = get_root_folder(mfid)
|
root = get_root_folder(mfid)
|
||||||
|
|
||||||
query = select(t for t in Track if t.genre == genre)
|
query = Track.select().where(Track.genre == genre)
|
||||||
if root is not None:
|
if root is not None:
|
||||||
query = query.where(lambda t: t.root_folder == root)
|
query = query.where(Track.root_folder == root)
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"songsByGenre",
|
"songsByGenre",
|
||||||
{
|
{
|
||||||
@ -219,9 +220,9 @@ def songs_by_genre():
|
|||||||
|
|
||||||
@api_routing("/getNowPlaying")
|
@api_routing("/getNowPlaying")
|
||||||
def now_playing():
|
def now_playing():
|
||||||
query = User.select(
|
query = User.select().where(
|
||||||
lambda u: u.last_play is not None
|
User.last_play.is_null(False),
|
||||||
and u.last_play_date + timedelta(minutes=3) > now()
|
User.last_play_date > now() - timedelta(minutes=3),
|
||||||
)
|
)
|
||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
@ -245,16 +246,26 @@ def get_starred():
|
|||||||
mfid = request.values.get("musicFolderId")
|
mfid = request.values.get("musicFolderId")
|
||||||
root = get_root_folder(mfid)
|
root = get_root_folder(mfid)
|
||||||
|
|
||||||
folders = select(s.starred for s in StarredFolder if s.user.id == request.user.id)
|
folders = (
|
||||||
|
StarredFolder.select(StarredFolder.starred)
|
||||||
|
.join(Folder)
|
||||||
|
.join(Track, on=Track.folder)
|
||||||
|
.where(StarredFolder.user == request.user)
|
||||||
|
.group_by(Folder)
|
||||||
|
)
|
||||||
if root is not None:
|
if root is not None:
|
||||||
folders = folders.filter(lambda f: f.path.startswith(root.path))
|
folders = folders.where(Folder.path.startswith(root.path))
|
||||||
|
|
||||||
arq = folders.filter(lambda f: count(f.tracks) == 0)
|
arq = folders.having(fn.count(Track.id) == 0)
|
||||||
alq = folders.filter(lambda f: count(f.tracks) > 0)
|
alq = folders.having(fn.count(Track.id) > 0)
|
||||||
trq = select(s.starred for s in StarredTrack if s.user.id == request.user.id)
|
trq = (
|
||||||
|
StarredTrack.select(StarredTrack.starred)
|
||||||
|
.join(Track)
|
||||||
|
.where(StarredTrack.user == request.user)
|
||||||
|
)
|
||||||
|
|
||||||
if root is not None:
|
if root is not None:
|
||||||
trq = trq.filter(lambda t: t.root_folder == root)
|
trq = trq.where(Track.root_folder == root)
|
||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"starred",
|
"starred",
|
||||||
@ -271,14 +282,26 @@ def get_starred_id3():
|
|||||||
mfid = request.values.get("musicFolderId")
|
mfid = request.values.get("musicFolderId")
|
||||||
root = get_root_folder(mfid)
|
root = get_root_folder(mfid)
|
||||||
|
|
||||||
arq = select(s.starred for s in StarredArtist if s.user.id == request.user.id)
|
arq = (
|
||||||
alq = select(s.starred for s in StarredAlbum if s.user.id == request.user.id)
|
StarredArtist.select(StarredArtist.starred)
|
||||||
trq = select(s.starred for s in StarredTrack if s.user.id == request.user.id)
|
.join(Artist)
|
||||||
|
.where(StarredArtist.user == request.user)
|
||||||
|
)
|
||||||
|
alq = (
|
||||||
|
StarredAlbum.select(StarredAlbum.starred)
|
||||||
|
.join(Album)
|
||||||
|
.where(StarredAlbum.user == request.user)
|
||||||
|
)
|
||||||
|
trq = (
|
||||||
|
StarredTrack.select(StarredTrack.starred)
|
||||||
|
.join(Track)
|
||||||
|
.where(StarredTrack.user == request.user)
|
||||||
|
)
|
||||||
|
|
||||||
if root is not None:
|
if root is not None:
|
||||||
arq = arq.filter(lambda a: root in a.tracks.root_folder)
|
arq = arq.join(Track).where(Track.root_folder == root)
|
||||||
alq = alq.filter(lambda a: root in a.tracks.root_folder)
|
alq = alq.join(Track).where(Track.root_folder == root)
|
||||||
trq = trq.filter(lambda t: t.root_folder == root)
|
trq = trq.where(Track.root_folder == root)
|
||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"starred2",
|
"starred2",
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
|
# Copyright (C) 2013-2022 Alban 'spl0k' Féron
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from flask import current_app, request
|
from flask import current_app, request
|
||||||
from pony.orm import delete
|
|
||||||
from pony.orm import ObjectNotFound
|
|
||||||
|
|
||||||
from ..db import Track, Album, Artist, Folder
|
from ..db import Track, Album, Artist, Folder
|
||||||
from ..db import StarredTrack, StarredAlbum, StarredArtist, StarredFolder
|
from ..db import StarredTrack, StarredAlbum, StarredArtist, StarredFolder
|
||||||
|
@ -9,7 +9,6 @@ import re
|
|||||||
import string
|
import string
|
||||||
|
|
||||||
from flask import current_app, request
|
from flask import current_app, request
|
||||||
from pony.orm import select, count
|
|
||||||
|
|
||||||
from ..db import Folder, Artist, Album, Track
|
from ..db import Folder, Artist, Album, Track
|
||||||
|
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2018-2019 Alban 'spl0k' Féron
|
# Copyright (C) 2018-2022 Alban 'spl0k' Féron
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
from pony.orm import rollback
|
from peewee import DoesNotExist
|
||||||
from pony.orm import ObjectNotFound
|
|
||||||
from werkzeug.exceptions import BadRequestKeyError
|
from werkzeug.exceptions import BadRequestKeyError
|
||||||
|
|
||||||
from . import api
|
from . import api
|
||||||
@ -15,25 +14,21 @@ from .exceptions import GenericError, MissingParameter, NotFound, ServerError
|
|||||||
|
|
||||||
@api.errorhandler(ValueError)
|
@api.errorhandler(ValueError)
|
||||||
def value_error(e):
|
def value_error(e):
|
||||||
rollback()
|
|
||||||
return GenericError("{0.__class__.__name__}: {0}".format(e))
|
return GenericError("{0.__class__.__name__}: {0}".format(e))
|
||||||
|
|
||||||
|
|
||||||
@api.errorhandler(BadRequestKeyError)
|
@api.errorhandler(BadRequestKeyError)
|
||||||
def key_error(e):
|
def key_error(e):
|
||||||
rollback()
|
|
||||||
return MissingParameter()
|
return MissingParameter()
|
||||||
|
|
||||||
|
|
||||||
@api.errorhandler(ObjectNotFound)
|
@api.errorhandler(DoesNotExist)
|
||||||
def object_not_found(e):
|
def object_not_found(e):
|
||||||
rollback()
|
return NotFound(e.__class__.__name__[: -len("DoesNotExist")])
|
||||||
return NotFound(e.entity.__name__)
|
|
||||||
|
|
||||||
|
|
||||||
@api.errorhandler(500)
|
@api.errorhandler(500)
|
||||||
def generic_error(e): # pragma: nocover
|
def generic_error(e): # pragma: nocover
|
||||||
rollback()
|
|
||||||
return ServerError("{0.__class__.__name__}: {0}".format(e))
|
return ServerError("{0.__class__.__name__}: {0}".format(e))
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2019 Alban 'spl0k' Féron
|
# Copyright (C) 2019-2022 Alban 'spl0k' Féron
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from flask import current_app, request
|
from flask import current_app, request
|
||||||
from pony.orm import ObjectNotFound
|
|
||||||
|
|
||||||
from ..daemon import DaemonClient
|
from ..daemon import DaemonClient
|
||||||
from ..daemon.exceptions import DaemonUnavailableError
|
from ..daemon.exceptions import DaemonUnavailableError
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2013-2020 Alban 'spl0k' Féron
|
# Copyright (C) 2013-2022 Alban 'spl0k' Féron
|
||||||
# 2018-2019 Carey 'pR0Ps' Metcalfe
|
# 2018-2019 Carey 'pR0Ps' Metcalfe
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
@ -20,7 +20,6 @@ import zlib
|
|||||||
from flask import request, Response, send_file
|
from flask import request, Response, send_file
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from pony.orm import ObjectNotFound
|
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
from zipstream import ZipStream
|
from zipstream import ZipStream
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import request
|
from flask import request
|
||||||
from pony.orm import select
|
|
||||||
|
|
||||||
from ..db import Folder, Track, Artist, Album
|
from ..db import Folder, Track, Artist, Album
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ from peewee import (
|
|||||||
IntegerField,
|
IntegerField,
|
||||||
TextField,
|
TextField,
|
||||||
)
|
)
|
||||||
from peewee import CompositeKey, DatabaseProxy
|
from peewee import CompositeKey, DatabaseProxy, MySQLDatabase
|
||||||
from peewee import fn
|
from peewee import fn
|
||||||
from playhouse.db_url import parseresult_to_dict, schemes
|
from playhouse.db_url import parseresult_to_dict, schemes
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
@ -38,11 +38,18 @@ def now():
|
|||||||
return datetime.now().replace(microsecond=0)
|
return datetime.now().replace(microsecond=0)
|
||||||
|
|
||||||
|
|
||||||
|
def random():
|
||||||
|
if isinstance(db.obj, MySQLDatabase):
|
||||||
|
return fn.rand()
|
||||||
|
return fn.random()
|
||||||
|
|
||||||
|
|
||||||
def PrimaryKeyField(**kwargs):
|
def PrimaryKeyField(**kwargs):
|
||||||
return BinaryUUIDField(primary_key=True, default=uuid4, **kwargs)
|
return BinaryUUIDField(primary_key=True, default=uuid4, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
db = DatabaseProxy()
|
db = DatabaseProxy()
|
||||||
|
db.Model._meta.legacy_table_names = False
|
||||||
|
|
||||||
|
|
||||||
class Meta(db.Model):
|
class Meta(db.Model):
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
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
|
||||||
@ -21,41 +19,40 @@ class AlbumSongsTestCase(ApiTestBase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
with db_session:
|
folder = Folder.create(name="Root", root=True, path="tests/assets")
|
||||||
folder = Folder(name="Root", root=True, path="tests/assets")
|
empty = Folder.create(name="Root", root=True, path="/tmp")
|
||||||
empty = Folder(name="Root", root=True, path="/tmp")
|
artist = Artist.create(name="Artist")
|
||||||
artist = Artist(name="Artist")
|
album = Album.create(name="Album", artist=artist)
|
||||||
album = Album(name="Album", artist=artist)
|
|
||||||
|
|
||||||
Track(
|
Track.create(
|
||||||
title="Track 1",
|
title="Track 1",
|
||||||
album=album,
|
album=album,
|
||||||
artist=artist,
|
artist=artist,
|
||||||
disc=1,
|
disc=1,
|
||||||
number=1,
|
number=1,
|
||||||
year=123,
|
year=123,
|
||||||
path="tests/assets/folder/1",
|
path="tests/assets/folder/1",
|
||||||
folder=folder,
|
folder=folder,
|
||||||
root_folder=folder,
|
root_folder=folder,
|
||||||
duration=2,
|
duration=2,
|
||||||
bitrate=320,
|
bitrate=320,
|
||||||
last_modification=0,
|
last_modification=0,
|
||||||
)
|
)
|
||||||
Track(
|
Track.create(
|
||||||
title="Track 2",
|
title="Track 2",
|
||||||
album=album,
|
album=album,
|
||||||
artist=artist,
|
artist=artist,
|
||||||
disc=1,
|
disc=1,
|
||||||
number=1,
|
number=1,
|
||||||
year=124,
|
year=124,
|
||||||
genre="Lampshade",
|
genre="Lampshade",
|
||||||
path="tests/assets/folder/2",
|
path="tests/assets/folder/2",
|
||||||
folder=folder,
|
folder=folder,
|
||||||
root_folder=folder,
|
root_folder=folder,
|
||||||
duration=2,
|
duration=2,
|
||||||
bitrate=320,
|
bitrate=320,
|
||||||
last_modification=0,
|
last_modification=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_album_list(self):
|
def test_get_album_list(self):
|
||||||
self._make_request("getAlbumList", error=10)
|
self._make_request("getAlbumList", error=10)
|
||||||
@ -140,8 +137,7 @@ class AlbumSongsTestCase(ApiTestBase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(len(child), 0)
|
self.assertEqual(len(child), 0)
|
||||||
|
|
||||||
with db_session:
|
Folder[1].delete_instance()
|
||||||
Folder[1].delete()
|
|
||||||
rv, child = self._make_request(
|
rv, child = self._make_request(
|
||||||
"getAlbumList", {"type": "random"}, tag="albumList"
|
"getAlbumList", {"type": "random"}, tag="albumList"
|
||||||
)
|
)
|
||||||
@ -231,9 +227,8 @@ class AlbumSongsTestCase(ApiTestBase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(len(child), 0)
|
self.assertEqual(len(child), 0)
|
||||||
|
|
||||||
with db_session:
|
Track.delete().execute()
|
||||||
Track.select().delete()
|
Album.delete().execute()
|
||||||
Album.get().delete()
|
|
||||||
rv, child = self._make_request(
|
rv, child = self._make_request(
|
||||||
"getAlbumList2", {"type": "random"}, tag="albumList2"
|
"getAlbumList2", {"type": "random"}, tag="albumList2"
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from supysonic.db import init_database, release_database
|
from supysonic.db import release_database
|
||||||
from supysonic.config import DefaultConfig
|
from supysonic.config import DefaultConfig
|
||||||
from supysonic.managers.user import UserManager
|
from supysonic.managers.user import UserManager
|
||||||
from supysonic.web import create_application
|
from supysonic.web import create_application
|
||||||
@ -93,9 +93,6 @@ class TestBase(unittest.TestCase):
|
|||||||
self.config.BASE["database_uri"] = "sqlite:///" + self.__db[1]
|
self.config.BASE["database_uri"] = "sqlite:///" + self.__db[1]
|
||||||
self.config.WEBAPP["cache_dir"] = self.__dir
|
self.config.WEBAPP["cache_dir"] = self.__dir
|
||||||
|
|
||||||
init_database(self.config.BASE["database_uri"])
|
|
||||||
release_database()
|
|
||||||
|
|
||||||
self.__app = create_application(self.config)
|
self.__app = create_application(self.config)
|
||||||
self.client = self.__app.test_client()
|
self.client = self.__app.test_client()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user