1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 08:56:17 +00:00

Code style

This commit is contained in:
Alban Féron 2021-11-28 17:15:05 +01:00
parent c3f911b3f4
commit 799bfa3dde
No known key found for this signature in database
GPG Key ID: 8CE0313646D16165
22 changed files with 262 additions and 257 deletions

View File

@ -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":

View File

@ -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
)
],
),
},
)

View File

@ -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)

View File

@ -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())
],
),
},
)

View File

@ -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]}
)

View File

@ -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

View File

@ -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():

View File

@ -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:

View File

@ -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)

View File

@ -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:

View File

@ -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

View File

@ -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,
},
)

View File

@ -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

View File

@ -18,4 +18,4 @@ def ping():
@api_routing("/getLicense")
def license():
return request.formatter("license", dict(valid=True))
return request.formatter("license", {"valid": True})

View File

@ -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

View File

@ -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):

View File

@ -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"))

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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,
)