mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 08:56:17 +00:00
Code style
This commit is contained in:
parent
c3f911b3f4
commit
799bfa3dde
@ -36,7 +36,7 @@ def api_routing(endpoint):
|
||||
@api.before_request
|
||||
def set_formatter():
|
||||
"""Return a function to create the response."""
|
||||
f, callback = map(request.values.get, ["f", "callback"])
|
||||
f, callback = map(request.values.get, ("f", "callback"))
|
||||
if f == "jsonp":
|
||||
request.formatter = JSONPFormatter(callback)
|
||||
elif f == "json":
|
||||
|
@ -29,7 +29,7 @@ from .exceptions import GenericError, NotFound
|
||||
def rand_songs():
|
||||
size = request.values.get("size", "10")
|
||||
genre, fromYear, toYear, musicFolderId = map(
|
||||
request.values.get, ["genre", "fromYear", "toYear", "musicFolderId"]
|
||||
request.values.get, ("genre", "fromYear", "toYear", "musicFolderId")
|
||||
)
|
||||
|
||||
size = int(size) if size else 10
|
||||
@ -57,12 +57,12 @@ def rand_songs():
|
||||
|
||||
return request.formatter(
|
||||
"randomSongs",
|
||||
dict(
|
||||
song=[
|
||||
{
|
||||
"song": [
|
||||
t.as_subsonic_child(request.user, request.client)
|
||||
for t in query.without_distinct().random(size)
|
||||
]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -70,7 +70,7 @@ def rand_songs():
|
||||
def album_list():
|
||||
ltype = request.values["type"]
|
||||
|
||||
size, offset = map(request.values.get, ["size", "offset"])
|
||||
size, offset = map(request.values.get, ("size", "offset"))
|
||||
size = int(size) if size else 10
|
||||
offset = int(offset) if offset else 0
|
||||
|
||||
@ -78,12 +78,12 @@ def album_list():
|
||||
if ltype == "random":
|
||||
return request.formatter(
|
||||
"albumList",
|
||||
dict(
|
||||
album=[
|
||||
{
|
||||
"album": [
|
||||
a.as_subsonic_child(request.user)
|
||||
for a in distinct(query.random(size))
|
||||
]
|
||||
),
|
||||
},
|
||||
)
|
||||
elif ltype == "newest":
|
||||
query = query.sort_by(desc(Folder.created)).distinct()
|
||||
@ -123,9 +123,11 @@ def album_list():
|
||||
|
||||
return request.formatter(
|
||||
"albumList",
|
||||
dict(
|
||||
album=[f.as_subsonic_child(request.user) for f in query.limit(size, offset)]
|
||||
),
|
||||
{
|
||||
"album": [
|
||||
f.as_subsonic_child(request.user) for f in query.limit(size, offset)
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -133,7 +135,7 @@ def album_list():
|
||||
def album_list_id3():
|
||||
ltype = request.values["type"]
|
||||
|
||||
size, offset = map(request.values.get, ["size", "offset"])
|
||||
size, offset = map(request.values.get, ("size", "offset"))
|
||||
size = int(size) if size else 10
|
||||
offset = int(offset) if offset else 0
|
||||
|
||||
@ -141,7 +143,7 @@ def album_list_id3():
|
||||
if ltype == "random":
|
||||
return request.formatter(
|
||||
"albumList2",
|
||||
dict(album=[a.as_subsonic_album(request.user) for a in query.random(size)]),
|
||||
{"album": [a.as_subsonic_album(request.user) for a in query.random(size)]},
|
||||
)
|
||||
elif ltype == "newest":
|
||||
query = query.order_by(lambda a: desc(min(a.tracks.created)))
|
||||
@ -177,9 +179,11 @@ def album_list_id3():
|
||||
|
||||
return request.formatter(
|
||||
"albumList2",
|
||||
dict(
|
||||
album=[f.as_subsonic_album(request.user) for f in query.limit(size, offset)]
|
||||
),
|
||||
{
|
||||
"album": [
|
||||
f.as_subsonic_album(request.user) for f in query.limit(size, offset)
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -187,14 +191,14 @@ def album_list_id3():
|
||||
def songs_by_genre():
|
||||
genre = request.values["genre"]
|
||||
|
||||
count, offset = map(request.values.get, ["count", "offset"])
|
||||
count, offset = map(request.values.get, ("count", "offset"))
|
||||
count = int(count) if count else 10
|
||||
offset = int(offset) if offset else 0
|
||||
|
||||
query = select(t for t in Track if t.genre == genre).limit(count, offset)
|
||||
return request.formatter(
|
||||
"songsByGenre",
|
||||
dict(song=[t.as_subsonic_child(request.user, request.client) for t in query]),
|
||||
{"song": [t.as_subsonic_child(request.user, request.client) for t in query]},
|
||||
)
|
||||
|
||||
|
||||
@ -207,17 +211,17 @@ def now_playing():
|
||||
|
||||
return request.formatter(
|
||||
"nowPlaying",
|
||||
dict(
|
||||
entry=[
|
||||
dict(
|
||||
u.last_play.as_subsonic_child(request.user, request.client),
|
||||
username=u.name,
|
||||
minutesAgo=(now() - u.last_play_date).seconds / 60,
|
||||
playerId=0,
|
||||
)
|
||||
{
|
||||
"entry": [
|
||||
{
|
||||
**u.last_play.as_subsonic_child(request.user, request.client),
|
||||
"username": u.name,
|
||||
"minutesAgo": (now() - u.last_play_date).seconds / 60,
|
||||
"playerId": 0,
|
||||
}
|
||||
for u in query
|
||||
]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -227,22 +231,22 @@ def get_starred():
|
||||
|
||||
return request.formatter(
|
||||
"starred",
|
||||
dict(
|
||||
artist=[
|
||||
{
|
||||
"artist": [
|
||||
sf.as_subsonic_artist(request.user)
|
||||
for sf in folders.filter(lambda f: count(f.tracks) == 0)
|
||||
],
|
||||
album=[
|
||||
"album": [
|
||||
sf.as_subsonic_child(request.user)
|
||||
for sf in folders.filter(lambda f: count(f.tracks) > 0)
|
||||
],
|
||||
song=[
|
||||
"song": [
|
||||
st.as_subsonic_child(request.user, request.client)
|
||||
for st in select(
|
||||
s.starred for s in StarredTrack if s.user.id == request.user.id
|
||||
)
|
||||
],
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -250,24 +254,24 @@ def get_starred():
|
||||
def get_starred_id3():
|
||||
return request.formatter(
|
||||
"starred2",
|
||||
dict(
|
||||
artist=[
|
||||
{
|
||||
"artist": [
|
||||
sa.as_subsonic_artist(request.user)
|
||||
for sa in select(
|
||||
s.starred for s in StarredArtist if s.user.id == request.user.id
|
||||
)
|
||||
],
|
||||
album=[
|
||||
"album": [
|
||||
sa.as_subsonic_album(request.user)
|
||||
for sa in select(
|
||||
s.starred for s in StarredAlbum if s.user.id == request.user.id
|
||||
)
|
||||
],
|
||||
song=[
|
||||
"song": [
|
||||
st.as_subsonic_child(request.user, request.client)
|
||||
for st in select(
|
||||
s.starred for s in StarredTrack if s.user.id == request.user.id
|
||||
)
|
||||
],
|
||||
),
|
||||
},
|
||||
)
|
||||
|
@ -54,7 +54,7 @@ def unstar_single(cls, starcls, eid):
|
||||
|
||||
|
||||
def handle_star_request(func):
|
||||
id, albumId, artistId = map(request.values.getlist, ["id", "albumId", "artistId"])
|
||||
id, albumId, artistId = map(request.values.getlist, ("id", "albumId", "artistId"))
|
||||
|
||||
if not id and not albumId and not artistId:
|
||||
raise MissingParameter("id, albumId or artistId")
|
||||
@ -174,7 +174,7 @@ def rate():
|
||||
@api_routing("/scrobble")
|
||||
def scrobble():
|
||||
res = get_entity(Track)
|
||||
t, submission = map(request.values.get, ["time", "submission"])
|
||||
t, submission = map(request.values.get, ("time", "submission"))
|
||||
t = int(t) / 1000 if t else int(time.time())
|
||||
|
||||
lfm = LastFm(current_app.config["LASTFM"], request.user)
|
||||
|
@ -20,12 +20,12 @@ from . import get_entity, get_entity_id, api_routing
|
||||
def list_folders():
|
||||
return request.formatter(
|
||||
"musicFolders",
|
||||
dict(
|
||||
musicFolder=[
|
||||
dict(id=str(f.id), name=f.name)
|
||||
{
|
||||
"musicFolder": [
|
||||
{"id": str(f.id), "name": f.name}
|
||||
for f in Folder.select(lambda f: f.root).order_by(Folder.name)
|
||||
]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -66,13 +66,14 @@ def list_indexes():
|
||||
|
||||
folders = [folder]
|
||||
|
||||
last_modif = max(map(lambda f: f.last_scan, folders))
|
||||
last_modif = max(f.last_scan for f in folders)
|
||||
if ifModifiedSince is not None and last_modif < ifModifiedSince:
|
||||
return request.formatter(
|
||||
"indexes",
|
||||
dict(
|
||||
lastModified=last_modif * 1000, ignoredArticles=ignored_articles_str()
|
||||
),
|
||||
{
|
||||
"lastModified": last_modif * 1000,
|
||||
"ignoredArticles": ignored_articles_str(),
|
||||
},
|
||||
)
|
||||
|
||||
# The XSD lies, we don't return artists but a directory structure
|
||||
@ -82,7 +83,7 @@ def list_indexes():
|
||||
artists += f.children.select()[:]
|
||||
children += f.tracks.select()[:]
|
||||
|
||||
indexes = dict()
|
||||
indexes = {}
|
||||
pattern = build_ignored_articles_pattern()
|
||||
for artist in artists:
|
||||
name = artist.name
|
||||
@ -101,24 +102,24 @@ def list_indexes():
|
||||
|
||||
return request.formatter(
|
||||
"indexes",
|
||||
dict(
|
||||
lastModified=last_modif * 1000,
|
||||
ignoredArticles=ignored_articles_str(),
|
||||
index=[
|
||||
dict(
|
||||
name=k,
|
||||
artist=[
|
||||
{
|
||||
"lastModified": last_modif * 1000,
|
||||
"ignoredArticles": ignored_articles_str(),
|
||||
"index": [
|
||||
{
|
||||
"name": k,
|
||||
"artist": [
|
||||
a.as_subsonic_artist(request.user)
|
||||
for a, _ in sorted(v, key=lambda t: t[1].lower())
|
||||
],
|
||||
)
|
||||
}
|
||||
for k, v in sorted(indexes.items())
|
||||
],
|
||||
child=[
|
||||
"child": [
|
||||
c.as_subsonic_child(request.user, request.client)
|
||||
for c in sorted(children, key=lambda t: t.sort_key())
|
||||
],
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -134,21 +135,21 @@ def show_directory():
|
||||
def list_genres():
|
||||
return request.formatter(
|
||||
"genres",
|
||||
dict(
|
||||
genre=[
|
||||
dict(value=genre, songCount=sc, albumCount=ac)
|
||||
{
|
||||
"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
|
||||
)
|
||||
]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@api_routing("/getArtists")
|
||||
def list_artists():
|
||||
# According to the API page, there are no parameters?
|
||||
indexes = dict()
|
||||
indexes = {}
|
||||
pattern = build_ignored_articles_pattern()
|
||||
for artist in Artist.select():
|
||||
name = artist.name or "?"
|
||||
@ -167,19 +168,19 @@ def list_artists():
|
||||
|
||||
return request.formatter(
|
||||
"artists",
|
||||
dict(
|
||||
ignoredArticles=ignored_articles_str(),
|
||||
index=[
|
||||
dict(
|
||||
name=k,
|
||||
artist=[
|
||||
{
|
||||
"ignoredArticles": ignored_articles_str(),
|
||||
"index": [
|
||||
{
|
||||
"name": k,
|
||||
"artist": [
|
||||
a.as_subsonic_artist(request.user)
|
||||
for a, _ in sorted(v, key=lambda t: t[1].lower())
|
||||
],
|
||||
)
|
||||
}
|
||||
for k, v in sorted(indexes.items())
|
||||
],
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ def get_chat():
|
||||
query = query.filter(lambda m: m.time > since)
|
||||
|
||||
return request.formatter(
|
||||
"chatMessages", dict(chatMessage=[msg.responsize() for msg in query])
|
||||
"chatMessages", {"chatMessage": [msg.responsize() for msg in query]}
|
||||
)
|
||||
|
||||
|
||||
|
@ -114,11 +114,12 @@ class AggregateException(SubsonicAPIException):
|
||||
|
||||
codes = {exc.api_code for exc in self.exceptions}
|
||||
errors = [
|
||||
dict(code=exc.api_code, message=exc.message) for exc in self.exceptions
|
||||
{"code": exc.api_code, "message": exc.message} for exc in self.exceptions
|
||||
]
|
||||
|
||||
rv = request.formatter(
|
||||
"error", dict(code=list(codes)[0] if len(codes) == 1 else 0, error=errors)
|
||||
"error",
|
||||
{"code": next(iter(codes)) if len(codes) == 1 else 0, "error": errors},
|
||||
)
|
||||
# rv.status_code = self.code
|
||||
return rv
|
||||
|
@ -16,7 +16,7 @@ class BaseFormatter:
|
||||
raise NotImplementedError()
|
||||
|
||||
def make_error(self, code, message):
|
||||
return self.make_response("error", dict(code=code, message=message))
|
||||
return self.make_response("error", {"code": code, "message": message})
|
||||
|
||||
def make_empty(self):
|
||||
return self.make_response(None, None)
|
||||
@ -78,7 +78,7 @@ class JSONPFormatter(JSONBaseFormatter):
|
||||
def make_response(self, elem, data):
|
||||
if not self.__callback:
|
||||
return jsonify(
|
||||
self._subsonicify("error", dict(code=10, message="Missing callback"))
|
||||
self._subsonicify("error", {"code": 10, "message": "Missing callback"})
|
||||
)
|
||||
|
||||
rv = self._subsonicify(elem, data)
|
||||
@ -100,7 +100,7 @@ class XMLFormatter(BaseFormatter):
|
||||
"""
|
||||
if not isinstance(dictionary, dict):
|
||||
raise TypeError("Expecting a dict")
|
||||
if not all(map(lambda x: isinstance(x, str), dictionary)):
|
||||
if not all(isinstance(x, str) for x in dictionary):
|
||||
raise TypeError("Dictionary keys must be strings")
|
||||
|
||||
for name, value in dictionary.items():
|
||||
|
@ -79,12 +79,12 @@ def jukebox_control():
|
||||
except DaemonUnavailableError:
|
||||
raise GenericError("Jukebox unavaliable")
|
||||
|
||||
rv = dict(
|
||||
currentIndex=status.index,
|
||||
playing=status.playing,
|
||||
gain=status.gain,
|
||||
position=status.position,
|
||||
)
|
||||
rv = {
|
||||
"currentIndex": status.index,
|
||||
"playing": status.playing,
|
||||
"gain": status.gain,
|
||||
"position": status.position,
|
||||
}
|
||||
if action == "get":
|
||||
playlist = []
|
||||
for path in status.playlist:
|
||||
|
@ -73,7 +73,7 @@ def stream_media():
|
||||
raise UnsupportedParameter("size")
|
||||
|
||||
maxBitRate, request_format, estimateContentLength = map(
|
||||
request.values.get, ["maxBitRate", "format", "estimateContentLength"]
|
||||
request.values.get, ("maxBitRate", "format", "estimateContentLength")
|
||||
)
|
||||
if request_format:
|
||||
request_format = request_format.lower()
|
||||
@ -378,7 +378,7 @@ def cover_art():
|
||||
def lyrics_response_for_track(track, lyrics):
|
||||
return request.formatter(
|
||||
"lyrics",
|
||||
dict(artist=track.album.artist.name, title=track.title, value=lyrics),
|
||||
{"artist": track.album.artist.name, "title": track.title, "value": lyrics},
|
||||
)
|
||||
|
||||
|
||||
@ -419,7 +419,7 @@ def lyrics():
|
||||
).hexdigest()
|
||||
cache_key = "lyrics-{}".format(unique)
|
||||
|
||||
lyrics = dict()
|
||||
lyrics = {}
|
||||
try:
|
||||
lyrics = json.loads(
|
||||
zlib.decompress(current_app.cache.get_value(cache_key)).decode("utf-8")
|
||||
@ -434,11 +434,11 @@ def lyrics():
|
||||
root = ElementTree.fromstring(r.content)
|
||||
|
||||
ns = {"cl": "http://api.chartlyrics.com/"}
|
||||
lyrics = dict(
|
||||
artist=root.find("cl:LyricArtist", namespaces=ns).text,
|
||||
title=root.find("cl:LyricSong", namespaces=ns).text,
|
||||
value=root.find("cl:Lyric", namespaces=ns).text,
|
||||
)
|
||||
lyrics = {
|
||||
"artist": root.find("cl:LyricArtist", namespaces=ns).text,
|
||||
"title": root.find("cl:LyricSong", namespaces=ns).text,
|
||||
"value": root.find("cl:Lyric", namespaces=ns).text,
|
||||
}
|
||||
|
||||
current_app.cache.set(
|
||||
cache_key, zlib.compress(json.dumps(lyrics).encode("utf-8"), 9)
|
||||
|
@ -36,7 +36,7 @@ def list_playlists():
|
||||
|
||||
return request.formatter(
|
||||
"playlists",
|
||||
dict(playlist=[p.as_subsonic_playlist(request.user) for p in query]),
|
||||
{"playlist": [p.as_subsonic_playlist(request.user) for p in query]},
|
||||
)
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ def show_playlist():
|
||||
|
||||
@api_routing("/createPlaylist")
|
||||
def create_playlist():
|
||||
playlist_id, name = map(request.values.get, ["playlistId", "name"])
|
||||
playlist_id, name = map(request.values.get, ("playlistId", "name"))
|
||||
# songId actually doesn't seem to be required
|
||||
songs = request.values.getlist("songId")
|
||||
playlist_id = uuid.UUID(playlist_id) if playlist_id else None
|
||||
@ -99,9 +99,9 @@ def update_playlist():
|
||||
raise Forbidden()
|
||||
|
||||
playlist = res
|
||||
name, comment, public = map(request.values.get, ["name", "comment", "public"])
|
||||
name, comment, public = map(request.values.get, ("name", "comment", "public"))
|
||||
to_add, to_remove = map(
|
||||
request.values.getlist, ["songIdToAdd", "songIndexToRemove"]
|
||||
request.values.getlist, ("songIdToAdd", "songIndexToRemove")
|
||||
)
|
||||
|
||||
if name:
|
||||
|
@ -18,7 +18,7 @@ def get_radio_stations():
|
||||
query = RadioStation.select().sort_by(RadioStation.name)
|
||||
return request.formatter(
|
||||
"internetRadioStations",
|
||||
dict(internetRadioStation=[p.as_subsonic_station() for p in query]),
|
||||
{"internetRadioStation": [p.as_subsonic_station() for p in query]},
|
||||
)
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ def create_radio_station():
|
||||
raise Forbidden()
|
||||
|
||||
stream_url, name, homepage_url = map(
|
||||
request.values.get, ["streamUrl", "name", "homepageUrl"]
|
||||
request.values.get, ("streamUrl", "name", "homepageUrl")
|
||||
)
|
||||
|
||||
if stream_url and name:
|
||||
@ -47,7 +47,7 @@ def update_radio_station():
|
||||
res = get_entity(RadioStation)
|
||||
|
||||
stream_url, name, homepage_url = map(
|
||||
request.values.get, ["streamUrl", "name", "homepageUrl"]
|
||||
request.values.get, ("streamUrl", "name", "homepageUrl")
|
||||
)
|
||||
if stream_url and name:
|
||||
res.stream_url = stream_url
|
||||
|
@ -28,10 +28,10 @@ def startScan():
|
||||
raise ServerError(str(e))
|
||||
return request.formatter(
|
||||
"scanStatus",
|
||||
dict(
|
||||
scanning="true" if scanned is not None else "false",
|
||||
count=scanned if scanned is not None else 0,
|
||||
),
|
||||
{
|
||||
"scanning": scanned is not None,
|
||||
"count": scanned or 0,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -46,8 +46,8 @@ def getScanStatus():
|
||||
raise ServerError(str(e))
|
||||
return request.formatter(
|
||||
"scanStatus",
|
||||
dict(
|
||||
scanning="true" if scanned is not None else "false",
|
||||
count=scanned if scanned is not None else 0,
|
||||
),
|
||||
{
|
||||
"scanning": scanned is not None,
|
||||
"count": scanned or 0,
|
||||
},
|
||||
)
|
||||
|
@ -20,7 +20,7 @@ from .exceptions import MissingParameter
|
||||
def old_search():
|
||||
artist, album, title, anyf, count, offset, newer_than = map(
|
||||
request.values.get,
|
||||
["artist", "album", "title", "any", "count", "offset", "newerThan"],
|
||||
("artist", "album", "title", "any", "count", "offset", "newerThan"),
|
||||
)
|
||||
|
||||
count = int(count) if count else 20
|
||||
@ -54,32 +54,32 @@ def old_search():
|
||||
|
||||
return request.formatter(
|
||||
"searchResult",
|
||||
dict(
|
||||
totalHits=folders.count() + tracks.count(),
|
||||
offset=offset,
|
||||
match=[
|
||||
{
|
||||
"totalHits": folders.count() + tracks.count(),
|
||||
"offset": offset,
|
||||
"match": [
|
||||
r.as_subsonic_child(request.user)
|
||||
if isinstance(r, Folder)
|
||||
else r.as_subsonic_child(request.user, request.client)
|
||||
for r in res
|
||||
],
|
||||
),
|
||||
},
|
||||
)
|
||||
else:
|
||||
raise MissingParameter("search")
|
||||
|
||||
return request.formatter(
|
||||
"searchResult",
|
||||
dict(
|
||||
totalHits=query.count(),
|
||||
offset=offset,
|
||||
match=[
|
||||
{
|
||||
"totalHits": query.count(),
|
||||
"offset": offset,
|
||||
"match": [
|
||||
r.as_subsonic_child(request.user)
|
||||
if isinstance(r, Folder)
|
||||
else r.as_subsonic_child(request.user, request.client)
|
||||
for r in query[offset : offset + count]
|
||||
],
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -95,14 +95,14 @@ def new_search():
|
||||
song_offset,
|
||||
) = map(
|
||||
request.values.get,
|
||||
[
|
||||
(
|
||||
"artistCount",
|
||||
"artistOffset",
|
||||
"albumCount",
|
||||
"albumOffset",
|
||||
"songCount",
|
||||
"songOffset",
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
artist_count = int(artist_count) if artist_count else 20
|
||||
@ -147,14 +147,14 @@ def search_id3():
|
||||
song_offset,
|
||||
) = map(
|
||||
request.values.get,
|
||||
[
|
||||
(
|
||||
"artistCount",
|
||||
"artistOffset",
|
||||
"albumCount",
|
||||
"albumOffset",
|
||||
"songCount",
|
||||
"songOffset",
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
artist_count = int(artist_count) if artist_count else 20
|
||||
|
@ -18,4 +18,4 @@ def ping():
|
||||
|
||||
@api_routing("/getLicense")
|
||||
def license():
|
||||
return request.formatter("license", dict(valid=True))
|
||||
return request.formatter("license", {"valid": True})
|
||||
|
@ -43,7 +43,7 @@ def user_info():
|
||||
@admin_only
|
||||
def users_info():
|
||||
return request.formatter(
|
||||
"users", dict(user=[u.as_subsonic_user() for u in User.select()])
|
||||
"users", {"user": [u.as_subsonic_user() for u in User.select()]}
|
||||
)
|
||||
|
||||
|
||||
@ -107,7 +107,7 @@ def user_edit():
|
||||
UserManager.change_password2(user, password)
|
||||
|
||||
email, admin, jukebox = map(
|
||||
request.values.get, ["email", "adminRole", "jukeboxRole"]
|
||||
request.values.get, ("email", "adminRole", "jukeboxRole")
|
||||
)
|
||||
if email is not None:
|
||||
user.mail = email
|
||||
|
220
supysonic/db.py
220
supysonic/db.py
@ -92,13 +92,13 @@ class Folder(PathMixin, db.Entity):
|
||||
ratings = Set(lambda: RatingFolder)
|
||||
|
||||
def as_subsonic_child(self, user):
|
||||
info = dict(
|
||||
id=str(self.id),
|
||||
isDir=True,
|
||||
title=self.name,
|
||||
album=self.name,
|
||||
created=self.created.isoformat(),
|
||||
)
|
||||
info = {
|
||||
"id": str(self.id),
|
||||
"isDir": True,
|
||||
"title": self.name,
|
||||
"album": self.name,
|
||||
"created": self.created.isoformat(),
|
||||
}
|
||||
if not self.root:
|
||||
info["parent"] = str(self.parent.id)
|
||||
info["artist"] = self.parent.name
|
||||
@ -129,7 +129,7 @@ class Folder(PathMixin, db.Entity):
|
||||
return info
|
||||
|
||||
def as_subsonic_artist(self, user): # "Artist" type in XSD
|
||||
info = dict(id=str(self.id), name=self.name)
|
||||
info = {"id": str(self.id), "name": self.name}
|
||||
|
||||
try:
|
||||
starred = StarredFolder[user.id, self.id]
|
||||
@ -140,10 +140,10 @@ class Folder(PathMixin, db.Entity):
|
||||
return info
|
||||
|
||||
def as_subsonic_directory(self, user, client): # "Directory" type in XSD
|
||||
info = dict(
|
||||
id=str(self.id),
|
||||
name=self.name,
|
||||
child=[
|
||||
info = {
|
||||
"id": str(self.id),
|
||||
"name": self.name,
|
||||
"child": [
|
||||
f.as_subsonic_child(user)
|
||||
for f in self.children.order_by(lambda c: c.name.lower())
|
||||
]
|
||||
@ -151,7 +151,7 @@ class Folder(PathMixin, db.Entity):
|
||||
t.as_subsonic_child(user, client)
|
||||
for t in sorted(self.tracks, key=lambda t: t.sort_key())
|
||||
],
|
||||
)
|
||||
}
|
||||
if not self.root:
|
||||
info["parent"] = str(self.parent.id)
|
||||
|
||||
@ -183,12 +183,12 @@ class Artist(db.Entity):
|
||||
stars = Set(lambda: StarredArtist)
|
||||
|
||||
def as_subsonic_artist(self, user):
|
||||
info = dict(
|
||||
id=str(self.id),
|
||||
name=self.name,
|
||||
info = {
|
||||
"id": str(self.id),
|
||||
"name": self.name,
|
||||
# coverArt
|
||||
albumCount=self.albums.count(),
|
||||
)
|
||||
"albumCount": self.albums.count(),
|
||||
}
|
||||
|
||||
try:
|
||||
starred = StarredArtist[user.id, self.id]
|
||||
@ -217,15 +217,15 @@ class Album(db.Entity):
|
||||
stars = Set(lambda: StarredAlbum)
|
||||
|
||||
def as_subsonic_album(self, user): # "AlbumID3" type in XSD
|
||||
info = dict(
|
||||
id=str(self.id),
|
||||
name=self.name,
|
||||
artist=self.artist.name,
|
||||
artistId=str(self.artist.id),
|
||||
songCount=self.tracks.count(),
|
||||
duration=sum(self.tracks.duration),
|
||||
created=min(self.tracks.created).isoformat(),
|
||||
)
|
||||
info = {
|
||||
"id": str(self.id),
|
||||
"name": self.name,
|
||||
"artist": self.artist.name,
|
||||
"artistId": str(self.artist.id),
|
||||
"songCount": self.tracks.count(),
|
||||
"duration": sum(self.tracks.duration),
|
||||
"created": min(self.tracks.created).isoformat(),
|
||||
}
|
||||
|
||||
track_with_cover = self.tracks.select(
|
||||
lambda t: t.folder.cover_art is not None
|
||||
@ -253,8 +253,8 @@ class Album(db.Entity):
|
||||
return info
|
||||
|
||||
def sort_key(self):
|
||||
year = min(map(lambda t: t.year if t.year else 9999, self.tracks))
|
||||
return "%i%s" % (year, self.name.lower())
|
||||
year = min(t.year if t.year else 9999 for t in self.tracks)
|
||||
return f"{year}{self.name.lower()}"
|
||||
|
||||
@classmethod
|
||||
def prune(cls):
|
||||
@ -297,27 +297,27 @@ class Track(PathMixin, db.Entity):
|
||||
ratings = Set(lambda: RatingTrack)
|
||||
|
||||
def as_subsonic_child(self, user, prefs):
|
||||
info = dict(
|
||||
id=str(self.id),
|
||||
parent=str(self.folder.id),
|
||||
isDir=False,
|
||||
title=self.title,
|
||||
album=self.album.name,
|
||||
artist=self.artist.name,
|
||||
track=self.number,
|
||||
size=os.path.getsize(self.path) if os.path.isfile(self.path) else -1,
|
||||
contentType=self.mimetype,
|
||||
suffix=self.suffix(),
|
||||
duration=self.duration,
|
||||
bitRate=self.bitrate,
|
||||
path=self.path[len(self.root_folder.path) + 1 :],
|
||||
isVideo=False,
|
||||
discNumber=self.disc,
|
||||
created=self.created.isoformat(),
|
||||
albumId=str(self.album.id),
|
||||
artistId=str(self.artist.id),
|
||||
type="music",
|
||||
)
|
||||
info = {
|
||||
"id": str(self.id),
|
||||
"parent": str(self.folder.id),
|
||||
"isDir": False,
|
||||
"title": self.title,
|
||||
"album": self.album.name,
|
||||
"artist": self.artist.name,
|
||||
"track": self.number,
|
||||
"size": os.path.getsize(self.path) if os.path.isfile(self.path) else -1,
|
||||
"contentType": self.mimetype,
|
||||
"suffix": self.suffix(),
|
||||
"duration": self.duration,
|
||||
"bitRate": self.bitrate,
|
||||
"path": self.path[len(self.root_folder.path) + 1 :],
|
||||
"isVideo": False,
|
||||
"discNumber": self.disc,
|
||||
"created": self.created.isoformat(),
|
||||
"albumId": str(self.album.id),
|
||||
"artistId": str(self.artist.id),
|
||||
"type": "music",
|
||||
}
|
||||
|
||||
if self.year:
|
||||
info["year"] = self.year
|
||||
@ -362,22 +362,16 @@ class Track(PathMixin, db.Entity):
|
||||
return mimetypes.guess_type(self.path, False)[0] or "application/octet-stream"
|
||||
|
||||
def duration_str(self):
|
||||
ret = "%02i:%02i" % ((self.duration % 3600) / 60, self.duration % 60)
|
||||
ret = "{:02}:{:02}".format((self.duration % 3600) / 60, self.duration % 60)
|
||||
if self.duration >= 3600:
|
||||
ret = "%02i:%s" % (self.duration / 3600, ret)
|
||||
ret = "{:02}:{}".format(self.duration / 3600, ret)
|
||||
return ret
|
||||
|
||||
def suffix(self):
|
||||
return os.path.splitext(self.path)[1][1:].lower()
|
||||
|
||||
def sort_key(self):
|
||||
return (
|
||||
self.album.artist.name
|
||||
+ self.album.name
|
||||
+ ("%02i" % self.disc)
|
||||
+ ("%02i" % self.number)
|
||||
+ self.title
|
||||
).lower()
|
||||
return f"{self.album.artist.name}{self.album.name}{self.disc:02}{self.number:02}{self.title}".lower()
|
||||
|
||||
|
||||
class User(db.Entity):
|
||||
@ -412,22 +406,22 @@ class User(db.Entity):
|
||||
track_ratings = Set(lambda: RatingTrack, lazy=True)
|
||||
|
||||
def as_subsonic_user(self):
|
||||
return dict(
|
||||
username=self.name,
|
||||
email=self.mail,
|
||||
scrobblingEnabled=self.lastfm_session is not None and self.lastfm_status,
|
||||
adminRole=self.admin,
|
||||
settingsRole=True,
|
||||
downloadRole=True,
|
||||
uploadRole=False,
|
||||
playlistRole=True,
|
||||
coverArtRole=False,
|
||||
commentRole=False,
|
||||
podcastRole=False,
|
||||
streamRole=True,
|
||||
jukeboxRole=self.admin or self.jukebox,
|
||||
shareRole=False,
|
||||
)
|
||||
return {
|
||||
"username": self.name,
|
||||
"email": self.mail,
|
||||
"scrobblingEnabled": self.lastfm_session is not None and self.lastfm_status,
|
||||
"adminRole": self.admin,
|
||||
"settingsRole": True,
|
||||
"downloadRole": True,
|
||||
"uploadRole": False,
|
||||
"playlistRole": True,
|
||||
"coverArtRole": False,
|
||||
"commentRole": False,
|
||||
"podcastRole": False,
|
||||
"streamRole": True,
|
||||
"jukeboxRole": self.admin or self.jukebox,
|
||||
"shareRole": False,
|
||||
}
|
||||
|
||||
|
||||
class ClientPrefs(db.Entity):
|
||||
@ -507,9 +501,11 @@ class ChatMessage(db.Entity):
|
||||
message = Required(str, 512)
|
||||
|
||||
def responsize(self):
|
||||
return dict(
|
||||
username=self.user.name, time=self.time * 1000, message=self.message
|
||||
)
|
||||
return {
|
||||
"username": self.user.name,
|
||||
"time": self.time * 1000,
|
||||
"message": self.message,
|
||||
}
|
||||
|
||||
|
||||
class Playlist(db.Entity):
|
||||
@ -525,17 +521,17 @@ class Playlist(db.Entity):
|
||||
|
||||
def as_subsonic_playlist(self, user):
|
||||
tracks = self.get_tracks()
|
||||
info = dict(
|
||||
id=str(self.id),
|
||||
name=self.name
|
||||
info = {
|
||||
"id": str(self.id),
|
||||
"name": self.name
|
||||
if self.user.id == user.id
|
||||
else "[{}] {}".format(self.user.name, self.name),
|
||||
owner=self.user.name,
|
||||
public=self.public,
|
||||
songCount=len(tracks),
|
||||
duration=sum(map(lambda t: t.duration, tracks)),
|
||||
created=self.created.isoformat(),
|
||||
)
|
||||
"owner": self.user.name,
|
||||
"public": self.public,
|
||||
"songCount": len(tracks),
|
||||
"duration": sum(t.duration for t in tracks),
|
||||
"created": self.created.isoformat(),
|
||||
}
|
||||
if self.comment:
|
||||
info["comment"] = self.comment
|
||||
return info
|
||||
@ -556,7 +552,7 @@ class Playlist(db.Entity):
|
||||
should_fix = True
|
||||
|
||||
if should_fix:
|
||||
self.tracks = ",".join(map(lambda t: str(t.id), tracks))
|
||||
self.tracks = ",".join(str(t.id) for t in tracks)
|
||||
db.commit()
|
||||
|
||||
return tracks
|
||||
@ -597,12 +593,12 @@ class RadioStation(db.Entity):
|
||||
created = Required(datetime, precision=0, default=now)
|
||||
|
||||
def as_subsonic_station(self):
|
||||
info = dict(
|
||||
id=str(self.id),
|
||||
streamUrl=self.stream_url,
|
||||
name=self.name,
|
||||
homePageUrl=self.homepage_url,
|
||||
)
|
||||
info = {
|
||||
"id": str(self.id),
|
||||
"streamUrl": self.stream_url,
|
||||
"name": self.name,
|
||||
"homePageUrl": self.homepage_url,
|
||||
}
|
||||
return info
|
||||
|
||||
|
||||
@ -622,28 +618,28 @@ def parse_uri(database_uri):
|
||||
elif path[0] == "/":
|
||||
path = path[1:]
|
||||
|
||||
return dict(provider="sqlite", filename=path, create_db=True, **args)
|
||||
return {"provider": "sqlite", "filename": path, "create_db": True, **args}
|
||||
elif uri.scheme in ("postgres", "postgresql"):
|
||||
return dict(
|
||||
provider="postgres",
|
||||
user=uri.username,
|
||||
password=uri.password,
|
||||
host=uri.hostname,
|
||||
dbname=uri.path[1:],
|
||||
**args
|
||||
)
|
||||
return {
|
||||
"provider": "postgres",
|
||||
"user": uri.username,
|
||||
"password": uri.password,
|
||||
"host": uri.hostname,
|
||||
"dbname": uri.path[1:],
|
||||
**args,
|
||||
}
|
||||
elif uri.scheme == "mysql":
|
||||
args.setdefault("charset", "utf8mb4")
|
||||
args.setdefault("binary_prefix", True)
|
||||
return dict(
|
||||
provider="mysql",
|
||||
user=uri.username,
|
||||
passwd=uri.password,
|
||||
host=uri.hostname,
|
||||
db=uri.path[1:],
|
||||
**args
|
||||
)
|
||||
return dict()
|
||||
return {
|
||||
"provider": "mysql",
|
||||
"user": uri.username,
|
||||
"passwd": uri.password,
|
||||
"host": uri.hostname,
|
||||
"db": uri.path[1:],
|
||||
**args,
|
||||
}
|
||||
return {}
|
||||
|
||||
|
||||
def execute_sql_resource_script(respath):
|
||||
|
@ -43,7 +43,7 @@ def add_folder_form():
|
||||
@admin_only
|
||||
def add_folder_post():
|
||||
error = False
|
||||
(name, path) = map(request.form.get, ["name", "path"])
|
||||
name, path = map(request.form.get, ("name", "path"))
|
||||
if name in (None, ""):
|
||||
flash("The name is required.")
|
||||
error = True
|
||||
@ -59,7 +59,7 @@ def add_folder_post():
|
||||
flash(str(e), "error")
|
||||
return render_template("addfolder.html")
|
||||
|
||||
flash("Folder '%s' created. You should now run a scan" % name)
|
||||
flash(f"Folder '{name}' created. You should now run a scan")
|
||||
return redirect(url_for("frontend.folder_index"))
|
||||
|
||||
|
||||
|
@ -73,7 +73,7 @@ def user_profile(uid, user):
|
||||
@frontend.route("/user/<uid>", methods=["POST"])
|
||||
@me_or_uuid
|
||||
def update_clients(uid, user):
|
||||
clients_opts = dict()
|
||||
clients_opts = {}
|
||||
for key, value in request.form.items():
|
||||
if "_" not in key:
|
||||
continue
|
||||
@ -85,7 +85,7 @@ def update_clients(uid, user):
|
||||
continue
|
||||
|
||||
if client not in clients_opts:
|
||||
clients_opts[client] = dict([(opt, value)])
|
||||
clients_opts[client] = {opt: value}
|
||||
else:
|
||||
clients_opts[client][opt] = value
|
||||
logger.debug(clients_opts)
|
||||
@ -157,9 +157,9 @@ def change_username_post(uid):
|
||||
if user.name != username or user.admin != admin:
|
||||
user.name = username
|
||||
user.admin = admin
|
||||
flash("User '%s' updated." % username)
|
||||
flash(f"User '{username}' updated.")
|
||||
else:
|
||||
flash("No changes for '%s'." % username)
|
||||
flash(f"No changes for '{username}'.")
|
||||
|
||||
return redirect(url_for("frontend.user_profile", uid=uid))
|
||||
|
||||
@ -195,7 +195,7 @@ def change_password_post(uid, user):
|
||||
flash("The current password is required")
|
||||
error = True
|
||||
|
||||
new, confirm = map(request.form.get, ["new", "confirm"])
|
||||
new, confirm = map(request.form.get, ("new", "confirm"))
|
||||
|
||||
if not new:
|
||||
flash("The new password is required")
|
||||
@ -231,7 +231,7 @@ def add_user_post():
|
||||
error = False
|
||||
args = request.form.copy()
|
||||
(name, passwd, passwd_confirm) = map(
|
||||
args.pop, ["user", "passwd", "passwd_confirm"], [None] * 3
|
||||
args.pop, ("user", "passwd", "passwd_confirm"), (None,) * 3
|
||||
)
|
||||
if not name:
|
||||
flash("The name is required.")
|
||||
@ -246,7 +246,7 @@ def add_user_post():
|
||||
if not error:
|
||||
try:
|
||||
UserManager.add(name, passwd, **args)
|
||||
flash("User '%s' successfully added" % name)
|
||||
flash(f"User '{name}' successfully added")
|
||||
return redirect(url_for("frontend.user_index"))
|
||||
except ValueError as e:
|
||||
flash(str(e), "error")
|
||||
@ -302,7 +302,7 @@ def login():
|
||||
if request.method == "GET":
|
||||
return render_template("login.html")
|
||||
|
||||
name, password = map(request.form.get, ["user", "password"])
|
||||
name, password = map(request.form.get, ("user", "password"))
|
||||
error = False
|
||||
if not name:
|
||||
flash("Missing user name")
|
||||
|
@ -30,7 +30,7 @@ class LastFm:
|
||||
if not res:
|
||||
return False, "Error connecting to LastFM"
|
||||
elif "error" in res:
|
||||
return False, "Error %i: %s" % (res["error"], res["message"])
|
||||
return False, f"Error {res['error']}: {res['message']}"
|
||||
else:
|
||||
self.__user.lastfm_session = res["session"]["key"]
|
||||
self.__user.lastfm_status = True
|
||||
@ -107,6 +107,6 @@ class LastFm:
|
||||
if "error" in json:
|
||||
if json["error"] in (9, "9"):
|
||||
self.__user.lastfm_status = False
|
||||
logger.warning("LastFM error %i: %s" % (json["error"], json["message"]))
|
||||
logger.warning("LastFM error %i: %s", json["error"], json["message"])
|
||||
|
||||
return json
|
||||
|
@ -400,9 +400,12 @@ class Scanner(Thread):
|
||||
|
||||
created = datetime.fromtimestamp(os.path.getmtime(path))
|
||||
children.append(
|
||||
dict(
|
||||
root=False, name=os.path.basename(path), path=path, created=created
|
||||
)
|
||||
{
|
||||
"root": False,
|
||||
"name": os.path.basename(path),
|
||||
"path": path,
|
||||
"created": created,
|
||||
}
|
||||
)
|
||||
path = os.path.dirname(path)
|
||||
|
||||
|
@ -31,9 +31,9 @@ class SupysonicWatcherEventHandler(PatternMatchingEventHandler):
|
||||
def __init__(self, extensions):
|
||||
patterns = None
|
||||
if extensions:
|
||||
patterns = list(map(lambda e: "*." + e.lower(), extensions.split())) + list(
|
||||
map(lambda e: "*" + e, covers.EXTENSIONS)
|
||||
)
|
||||
patterns = ["*." + e.lower() for e in extensions.split()] + [
|
||||
"*" + e for e in covers.EXTENSIONS
|
||||
]
|
||||
super().__init__(patterns=patterns, ignore_directories=True)
|
||||
|
||||
def dispatch(self, event):
|
||||
@ -132,7 +132,7 @@ class ScannerProcessingQueue(Thread):
|
||||
self.__timeout = delay
|
||||
self.__cond = Condition()
|
||||
self.__timer = None
|
||||
self.__queue = dict()
|
||||
self.__queue = {}
|
||||
self.__running = True
|
||||
|
||||
def run(self):
|
||||
|
@ -172,7 +172,7 @@ class PlaylistTestCase(ApiTestBase):
|
||||
"createPlaylist",
|
||||
{
|
||||
"name": "songs",
|
||||
"songId": list(map(lambda s: songs[s], ["Three", "One", "Two"])),
|
||||
"songId": [songs[s] for s in ("Three", "One", "Two")],
|
||||
},
|
||||
skip_post=True,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user