readcursor -> cursor

This commit is contained in:
dave 2020-10-05 22:41:01 -07:00
parent f3d888be35
commit bfcb528ddf
1 changed files with 109 additions and 109 deletions

View File

@ -9,9 +9,9 @@ logging = logging.getLogger("database")
keys_in_table = ["title", "album", "artist", "type", "size"] keys_in_table = ["title", "album", "artist", "type", "size"]
def dict_factory(cursor, row): def dict_factory(c, row):
d = {} d = {}
for idx, col in enumerate(cursor.description): for idx, col in enumerate(c.description):
d[col[0]] = row[idx] d[col[0]] = row[idx]
return d return d
@ -28,7 +28,7 @@ def hash_password(unicode_string):
return sha512(unicode_string.encode('UTF-8')).hexdigest() return sha512(unicode_string.encode('UTF-8')).hexdigest()
def readcursor(func): def cursor(func):
""" """
Provides a cursor to the wrapped method as the first arg. Provides a cursor to the wrapped method as the first arg.
""" """
@ -37,8 +37,8 @@ def readcursor(func):
if len(args) >= 2 and isinstance(args[1], sqlite3.Cursor): if len(args) >= 2 and isinstance(args[1], sqlite3.Cursor):
return func(*args, **kwargs) return func(*args, **kwargs)
else: else:
with closing(self.db.cursor()) as cursor: with closing(self.db.cursor()) as c:
return func(self, cursor, *args[1:], **kwargs) return func(self, c, *args[1:], **kwargs)
return wrapped return wrapped
@ -135,31 +135,31 @@ class PysonicDatabase(object):
'value' TEXT);""", 'value' TEXT);""",
"""INSERT INTO meta VALUES ('db_version', '1');"""] """INSERT INTO meta VALUES ('db_version', '1');"""]
with closing(self.db.cursor()) as cursor: with closing(self.db.cursor()) as c:
cursor.execute("SELECT * FROM sqlite_master WHERE type='table' AND name='meta'") c.execute("SELECT * FROM sqlite_master WHERE type='table' AND name='meta'")
# Initialize DB # Initialize DB
if len(cursor.fetchall()) == 0: if len(c.fetchall()) == 0:
logging.warning("Initializing database") logging.warning("Initializing database")
for query in queries: for query in queries:
cursor.execute(query) c.execute(query)
cursor.execute("COMMIT") c.execute("COMMIT")
else: else:
# Migrate if old db exists # Migrate if old db exists
# cursor.execute("""UPDATE meta SET value=? WHERE key="db_version";""", (str(version), )) # c.execute("""UPDATE meta SET value=? WHERE key="db_version";""", (str(version), ))
# logging.warning("db schema is version {}".format(version)) # logging.warning("db schema is version {}".format(version))
pass pass
@readcursor @cursor
def get_stats(self, cursor): def get_stats(self, c):
songs = cursor.execute("SELECT COUNT(*) as cnt FROM songs").fetchone()['cnt'] songs = c.execute("SELECT COUNT(*) as cnt FROM songs").fetchone()['cnt']
artists = cursor.execute("SELECT COUNT(*) as cnt FROM artists").fetchone()['cnt'] artists = c.execute("SELECT COUNT(*) as cnt FROM artists").fetchone()['cnt']
albums = cursor.execute("SELECT COUNT(*) as cnt FROM albums").fetchone()['cnt'] albums = c.execute("SELECT COUNT(*) as cnt FROM albums").fetchone()['cnt']
return dict(songs=songs, artists=artists, albums=albums) return dict(songs=songs, artists=artists, albums=albums)
# Music related # Music related
@readcursor @cursor
def add_root(self, cursor, path, name="Library"): def add_root(self, c, path, name="Library"):
""" """
Add a new library root. Returns the root ID or raises on collision Add a new library root. Returns the root ID or raises on collision
:param path: normalized absolute path to add to the library :param path: normalized absolute path to add to the library
@ -169,14 +169,14 @@ class PysonicDatabase(object):
""" """
assert path.startswith("/") assert path.startswith("/")
try: try:
cursor.execute("INSERT INTO libraries ('name', 'path') VALUES (?, ?)", (name, path, )) c.execute("INSERT INTO libraries ('name', 'path') VALUES (?, ?)", (name, path, ))
cursor.execute("COMMIT") c.execute("COMMIT")
return cursor.lastrowid return c.lastrowid
except sqlite3.IntegrityError: except sqlite3.IntegrityError:
raise DuplicateRootException("Root '{}' already exists".format(path)) raise DuplicateRootException("Root '{}' already exists".format(path))
@readcursor @cursor
def get_libraries(self, cursor, id=None): def get_libraries(self, c, id=None):
libs = [] libs = []
q = "SELECT * FROM libraries" q = "SELECT * FROM libraries"
params = [] params = []
@ -186,13 +186,13 @@ class PysonicDatabase(object):
params.append(id) params.append(id)
if conditions: if conditions:
q += " WHERE " + " AND ".join(conditions) q += " WHERE " + " AND ".join(conditions)
cursor.execute(q, params) c.execute(q, params)
for row in cursor: for row in c:
libs.append(row) libs.append(row)
return libs return libs
@readcursor @cursor
def get_artists(self, cursor, id=None, dirid=None, sortby="name", order=None, name_contains=None): def get_artists(self, c, id=None, dirid=None, sortby="name", order=None, name_contains=None):
assert order in ["asc", "desc", None] assert order in ["asc", "desc", None]
artists = [] artists = []
q = "SELECT * FROM artists" q = "SELECT * FROM artists"
@ -211,13 +211,13 @@ class PysonicDatabase(object):
q += " WHERE " + " AND ".join(conditions) q += " WHERE " + " AND ".join(conditions)
if sortby: if sortby:
q += " ORDER BY {} {}".format(sortby, order.upper() if order else "ASC") q += " ORDER BY {} {}".format(sortby, order.upper() if order else "ASC")
cursor.execute(q, params) c.execute(q, params)
for row in cursor: for row in c:
artists.append(row) artists.append(row)
return artists return artists
@readcursor @cursor
def get_albums(self, cursor, id=None, artist=None, sortby="name", order=None, limit=None, name_contains=None): def get_albums(self, c, id=None, artist=None, sortby="name", order=None, limit=None, name_contains=None):
""" """
:param limit: int or tuple of int, int. translates directly to sql logic. :param limit: int or tuple of int, int. translates directly to sql logic.
""" """
@ -264,13 +264,13 @@ class PysonicDatabase(object):
q += " LIMIT {}".format(limit) if isinstance(limit, int) \ q += " LIMIT {}".format(limit) if isinstance(limit, int) \
else " LIMIT {}, {}".format(*limit) else " LIMIT {}, {}".format(*limit)
cursor.execute(q, params) c.execute(q, params)
for row in cursor: for row in c:
albums.append(row) albums.append(row)
return albums return albums
@readcursor @cursor
def get_songs(self, cursor, id=None, genre=None, sortby="title", order=None, limit=None, title_contains=None): def get_songs(self, c, id=None, genre=None, sortby="title", order=None, limit=None, title_contains=None):
# TODO make this query massively uglier by joining albums and artists so that artistid etc can be a filter # TODO make this query massively uglier by joining albums and artists so that artistid etc can be a filter
# or maybe lookup those IDs in the library layer? # or maybe lookup those IDs in the library layer?
if order: if order:
@ -326,13 +326,13 @@ class PysonicDatabase(object):
if limit: if limit:
q += " LIMIT {}".format(limit) # TODO support limit pagination q += " LIMIT {}".format(limit) # TODO support limit pagination
cursor.execute(q, params) c.execute(q, params)
for row in cursor: for row in c:
songs.append(row) songs.append(row)
return songs return songs
@readcursor @cursor
def get_genres(self, cursor, genre_id=None): def get_genres(self, c, genre_id=None):
genres = [] genres = []
q = "SELECT * FROM genres" q = "SELECT * FROM genres"
params = [] params = []
@ -342,19 +342,19 @@ class PysonicDatabase(object):
params.append(genre_id) params.append(genre_id)
if conditions: if conditions:
q += " WHERE " + " AND ".join(conditions) q += " WHERE " + " AND ".join(conditions)
cursor.execute(q, params) c.execute(q, params)
for row in cursor: for row in c:
genres.append(row) genres.append(row)
return genres return genres
@readcursor @cursor
def get_cover(self, cursor, coverid): def get_cover(self, c, coverid):
cover = None cover = None
for cover in cursor.execute("SELECT * FROM covers WHERE id = ?", (coverid, )): for cover in c.execute("SELECT * FROM covers WHERE id = ?", (coverid, )):
return cover return cover
@readcursor @cursor
def get_subsonic_musicdir(self, cursor, dirid): def get_subsonic_musicdir(self, c, dirid):
""" """
The world is a harsh place. The world is a harsh place.
Again, this bullshit exists only to serve subsonic clients. Given a directory ID it returns a dict containing: Again, this bullshit exists only to serve subsonic clients. Given a directory ID it returns a dict containing:
@ -367,7 +367,7 @@ class PysonicDatabase(object):
""" """
# find directory # find directory
dirinfo = None dirinfo = None
for dirinfo in cursor.execute("SELECT * FROM dirs WHERE id = ?", (dirid, )): for dirinfo in c.execute("SELECT * FROM dirs WHERE id = ?", (dirid, )):
pass pass
assert dirinfo assert dirinfo
@ -375,7 +375,7 @@ class PysonicDatabase(object):
# see if it matches the artists or albums table # see if it matches the artists or albums table
artist = None artist = None
for artist in cursor.execute("SELECT * FROM artists WHERE dir = ?", (dirid, )): for artist in c.execute("SELECT * FROM artists WHERE dir = ?", (dirid, )):
pass pass
# if artist: # if artist:
@ -383,7 +383,7 @@ class PysonicDatabase(object):
if artist: if artist:
ret = ("artist", dirinfo, artist) ret = ("artist", dirinfo, artist)
children = [] children = []
for album in cursor.execute("SELECT * FROM albums WHERE artistid = ?", (artist["id"], )): for album in c.execute("SELECT * FROM albums WHERE artistid = ?", (artist["id"], )):
children.append(("album", album)) children.append(("album", album))
ret[2]['children'] = children ret[2]['children'] = children
return ret return ret
@ -391,45 +391,45 @@ class PysonicDatabase(object):
# else if album: # else if album:
# get child tracks # get child tracks
album = None album = None
for album in cursor.execute("SELECT * FROM albums WHERE dir = ?", (dirid, )): for album in c.execute("SELECT * FROM albums WHERE dir = ?", (dirid, )):
pass pass
if album: if album:
ret = ("album", dirinfo, album) ret = ("album", dirinfo, album)
artist_info = cursor.execute("SELECT * FROM artists WHERE id = ?", (album["artistid"], )).fetchall()[0] artist_info = c.execute("SELECT * FROM artists WHERE id = ?", (album["artistid"], )).fetchall()[0]
children = [] children = []
for song in cursor.execute("SELECT * FROM songs WHERE albumid = ? ORDER BY track, title ASC;", (album["id"], )): for song in c.execute("SELECT * FROM songs WHERE albumid = ? ORDER BY track, title ASC;", (album["id"], )):
song["_artist"] = artist_info song["_artist"] = artist_info
children.append(("song", song)) children.append(("song", song))
ret[2]['children'] = children ret[2]['children'] = children
return ret return ret
# Playlist related # Playlist related
@readcursor @cursor
def add_playlist(self, cursor, ownerid, name, song_ids, public=False): def add_playlist(self, c, ownerid, name, song_ids, public=False):
""" """
Create a playlist Create a playlist
""" """
now = time() now = time()
cursor.execute("INSERT INTO playlists (ownerid, name, public, created, changed) VALUES (?, ?, ?, ?, ?)", c.execute("INSERT INTO playlists (ownerid, name, public, created, changed) VALUES (?, ?, ?, ?, ?)",
(ownerid, name, public, now, now)) (ownerid, name, public, now, now))
plid = cursor.lastrowid plid = c.lastrowid
for song_id in song_ids: for song_id in song_ids:
self.add_to_playlist(cursor, plid, song_id) self.add_to_playlist(c, plid, song_id)
cursor.execute("COMMIT") c.execute("COMMIT")
@readcursor @cursor
def add_to_playlist(self, cursor, playlist_id, song_id): def add_to_playlist(self, c, playlist_id, song_id):
# TODO deal with order column # TODO deal with order column
cursor.execute("INSERT INTO playlist_entries (playlistid, songid) VALUES (?, ?)", (playlist_id, song_id)) c.execute("INSERT INTO playlist_entries (playlistid, songid) VALUES (?, ?)", (playlist_id, song_id))
@readcursor @cursor
def get_playlist(self, cursor, playlist_id): def get_playlist(self, c, playlist_id):
return cursor.execute("SELECT * FROM playlists WHERE id=?", (playlist_id, )).fetchone() return c.execute("SELECT * FROM playlists WHERE id=?", (playlist_id, )).fetchone()
@readcursor @cursor
def get_playlist_songs(self, cursor, playlist_id): def get_playlist_songs(self, c, playlist_id):
songs = [] songs = []
q = """ q = """
SELECT SELECT
@ -451,65 +451,65 @@ class PysonicDatabase(object):
WHERE pe.playlistid = ? WHERE pe.playlistid = ?
ORDER BY pe.'order' ASC; ORDER BY pe.'order' ASC;
""" """
for row in cursor.execute(q, (playlist_id, )): for row in c.execute(q, (playlist_id, )):
songs.append(row) songs.append(row)
return songs return songs
@readcursor @cursor
def get_playlists(self, cursor, user_id): def get_playlists(self, c, user_id):
playlists = [] playlists = []
for row in cursor.execute("SELECT * FROM playlists WHERE ownerid=? or public=1", (user_id, )): for row in c.execute("SELECT * FROM playlists WHERE ownerid=? or public=1", (user_id, )):
playlists.append(row) playlists.append(row)
return playlists return playlists
@readcursor @cursor
def remove_index_from_playlist(self, cursor, playlist_id, index): def remove_index_from_playlist(self, c, playlist_id, index):
cursor.execute("DELETE FROM playlist_entries WHERE playlistid=? LIMIT ?, 1", (playlist_id, index, )) c.execute("DELETE FROM playlist_entries WHERE playlistid=? LIMIT ?, 1", (playlist_id, index, ))
cursor.execute("COMMIT") c.execute("COMMIT")
@readcursor @cursor
def empty_playlist(self, cursor, playlist_id): def empty_playlist(self, c, playlist_id):
#TODO combine with # TODO combine with #TODO combine with ??
cursor.execute("DELETE FROM playlist_entries WHERE playlistid=?", (playlist_id, )) c.execute("DELETE FROM playlist_entries WHERE playlistid=?", (playlist_id, ))
cursor.execute("COMMIT") c.execute("COMMIT")
@readcursor @cursor
def delete_playlist(self, cursor, playlist_id): def delete_playlist(self, c, playlist_id):
cursor.execute("DELETE FROM playlists WHERE id=?", (playlist_id, )) c.execute("DELETE FROM playlists WHERE id=?", (playlist_id, ))
cursor.execute("COMMIT") c.execute("COMMIT")
@readcursor @cursor
def update_album_played(self, cursor, album_id, last_played=None): def update_album_played(self, c, album_id, last_played=None):
cursor.execute("UPDATE albums SET played=? WHERE id=?", (last_played, album_id, )) c.execute("UPDATE albums SET played=? WHERE id=?", (last_played, album_id, ))
cursor.execute("COMMIT") c.execute("COMMIT")
@readcursor @cursor
def increment_album_plays(self, cursor, album_id): def increment_album_plays(self, c, album_id):
cursor.execute("UPDATE albums SET plays = plays + 1 WHERE id=?", (album_id, )) c.execute("UPDATE albums SET plays = plays + 1 WHERE id=?", (album_id, ))
cursor.execute("COMMIT") c.execute("COMMIT")
@readcursor @cursor
def increment_track_plays(self, cursor, track_id): def increment_track_plays(self, c, track_id):
cursor.execute("UPDATE songs SET plays = plays + 1 WHERE id=?", (track_id, )) c.execute("UPDATE songs SET plays = plays + 1 WHERE id=?", (track_id, ))
cursor.execute("COMMIT") c.execute("COMMIT")
# User related # User related
@readcursor @cursor
def add_user(self, cursor, username, password, is_admin=False): def add_user(self, c, username, password, is_admin=False):
cursor.execute("INSERT INTO users (username, password, admin) VALUES (?, ?, ?)", c.execute("INSERT INTO users (username, password, admin) VALUES (?, ?, ?)",
(username, hash_password(password), is_admin)) (username, hash_password(password), is_admin))
cursor.execute("COMMIT") c.execute("COMMIT")
@readcursor @cursor
def update_user(self, cursor, username, password, is_admin=False): def update_user(self, c, username, password, is_admin=False):
cursor.execute("UPDATE users SET password=?, admin=? WHERE username=?;", c.execute("UPDATE users SET password=?, admin=? WHERE username=?;",
(hash_password(password), is_admin, username)) (hash_password(password), is_admin, username))
cursor.execute("COMMIT") c.execute("COMMIT")
@readcursor @cursor
def get_user(self, cursor, user): def get_user(self, c, user):
try: try:
column = "id" if type(user) is int else "username" column = "id" if type(user) is int else "username"
return cursor.execute("SELECT * FROM users WHERE {}=?;".format(column), (user, )).fetchall()[0] return c.execute("SELECT * FROM users WHERE {}=?;".format(column), (user, )).fetchall()[0]
except IndexError: except IndexError:
raise NotFoundError("User doesn't exist") raise NotFoundError("User doesn't exist")