db: Convert the PlaylistStateTable into a table.Table

This gives us access to the new functions and built-in caching. I also
change the PlaylistState object to cache its values rather than querying
the database for everything.

Implements: Issue #11 (Cache database items fields)
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2021-10-09 10:14:30 -04:00
parent ca3a88557f
commit 84ad195716
18 changed files with 118 additions and 99 deletions

View File

@ -25,8 +25,12 @@ def make_fake_track(trackno, length, title, path, lib="/a/b/c", art="Test Artist
length, title, pathlib.Path(path))
def reset():
mods = [ state ]
for mod in mods: mod.Table.reset()
mods = [ artist, album, disc, genre, decade, year,
library, track, user, state ]
library, track, user ]
for mod in mods: mod.Table.drop()
for mod in mods: mod.Table.do_create()

View File

@ -27,7 +27,7 @@ class Album(objects.Tag):
@GObject.Property
def playlist_state(self):
return state.PlaylistState(self.get_column("plstateid"))
return state.Table.get(self.get_column("plstateid"))
def discs(self):
cursor = execute(f"SELECT discid FROM discs "
@ -56,7 +56,7 @@ class AlbumTable(objects.Table):
plstate = state.Table.insert(random=False, loop=False)
return execute("INSERT INTO albums (artistid, plstateid, name, sort) "
"VALUES (?, ?, ?, ?)",
[ int(artist), int(plstate), name, name.casefold() ])
[ int(artist), plstate.rowid, name, name.casefold() ])
def do_delete(self, album):
state.Table.delete(album.playlist_state)

View File

@ -22,7 +22,7 @@ class Artist(objects.Tag):
@GObject.Property
def playlist_state(self):
return state.PlaylistState(self.get_column("plstateid"))
return state.Table.get(self.get_column("plstateid"))
def albums(self):
cursor = execute(f"SELECT albumid FROM albums "
@ -48,7 +48,7 @@ class ArtistTable(objects.Table):
plstate = state.Table.insert(random=False, loop=False)
return execute("INSERT INTO artists (plstateid, name, sort) "
"VALUES (?, ?, ?)",
[ int(plstate), name, sort.casefold() ])
[ plstate.rowid, name, sort.casefold() ])
def do_delete(self, artist):
state.Table.delete(artist.playlist_state)

View File

@ -30,7 +30,7 @@ class Decade(objects.Row):
@GObject.Property
def playlist_state(self):
return state.PlaylistState(self.get_column("plstateid"))
return state.Table.get(self.get_column("plstateid"))
class DecadeTable(objects.Table):
@ -47,7 +47,7 @@ class DecadeTable(objects.Table):
def do_insert(self, decade):
plstate = state.Table.insert(random=False, loop=False)
return execute("INSERT INTO decades (plstateid,decade) "
"VALUES (?, ?)", [ int(plstate), decade ])
"VALUES (?, ?)", [ plstate.rowid, decade ])
def do_delete(self, decade):
state.Table.delete(decade.playlist_state)

View File

@ -32,7 +32,7 @@ class Disc(objects.Row):
@GObject.Property
def playlist_state(self):
return state.PlaylistState(self.get_column("plstateid"))
return state.Table.get(self.get_column("plstateid"))
@GObject.Property
def subtitle(self):
@ -59,7 +59,7 @@ class DiscTable(objects.Table):
plstate = state.Table.insert(random=False, loop=False)
return execute("INSERT INTO discs (albumid, plstateid, number, subtitle) "
"VALUES (?, ?, ?, ?)",
[ int(album), int(plstate), number, subtitle ])
[ int(album), plstate.rowid, number, subtitle ])
def do_delete(self, disc):
state.Table.delete(disc.playlist_state)

View File

@ -27,7 +27,7 @@ class Genre(objects.Tag):
@GObject.Property
def playlist_state(self):
return state.PlaylistState(self.get_column("plstateid"))
return state.Table.get(self.get_column("plstateid"))
class GenreTable(objects.Table):
@ -47,7 +47,7 @@ class GenreTable(objects.Table):
plstate = state.Table.insert(random=False, loop=False)
return execute("INSERT INTO genres (plstateid, name, sort) "
"VALUES (?, ?, ?)",
[ int(plstate), name, name.casefold() ])
[ plstate.rowid, name, name.casefold() ])
def do_delete(self, genre):
state.Table.delete(genre.playlist_state)

View File

@ -28,7 +28,7 @@ class Library(objects.Row):
@GObject.Property
def playlist_state(self):
return state.PlaylistState(self.get_column("plstateid"))
return state.Table.get(self.get_column("plstateid"))
@GObject.Property
def path(self):
@ -62,7 +62,7 @@ class LibraryTable(objects.Table):
plstate = state.Table.insert(random=False, loop=False)
return execute("INSERT INTO libraries (plstateid, path) "
"VALUES (?, ?)",
[ int(plstate), str(path) ])
[ plstate.rowid, str(path) ])
def do_delete(self, library):
for t in library.tracks():

View File

@ -5,76 +5,71 @@
# | plstateid | random | loop | current | sort |
# +-----------+--------+------+---------+------+
from gi.repository import GObject
from .sql import execute
from . import objects
from . import sql
from . import table
class PlaylistState(objects.Row):
def do_get_column(self, column):
return execute(f"SELECT {column} FROM playlist_states "
"WHERE plstateid=?", [ self.rowid ])
class PlaylistState(GObject.GObject):
def __init__(self, row):
GObject.GObject.__init__(self)
self._plstateid = row["plstateid"]
self._random = row["random"]
self._loop = row["loop"]
self._current = row["current"]
self._sort = row["sort"]
@GObject.Property
def rowid(self): return self._plstateid
@GObject.Property(type=bool,default=False)
def random(self):
return bool(self.get_column("random"))
def random(self): return self._random
@random.setter
def random(self, newval):
execute("UPDATE playlist_states SET random=? WHERE plstateid=?",
[ newval, self.rowid ])
def random(self, newval): self._random = self.update("random", newval)
@GObject.Property(type=bool,default=False)
def loop(self):
return bool(self.get_column("loop"))
def loop(self): return self._loop
@loop.setter
def loop(self, newval):
execute("UPDATE playlist_states SET loop=? WHERE plstateid=?",
[ newval, self.rowid ])
def loop(self, newval): self._loop = self.update("loop", newval)
@GObject.Property(type=int)
def current(self):
return self.get_column("current")
def current(self): return self._current
@current.setter
def current(self, newval):
execute("UPDATE playlist_states SET current=? WHERE plstateid=?",
[ newval, self.rowid ])
def current(self, newval): self._current = self.update("current", newval)
@GObject.Property(type=str)
def sort(self):
return self.get_column("sort")
def sort(self): return self._sort
@sort.setter
def sort(self, newval):
execute("UPDATE playlist_states SET sort=? WHERE plstateid=?",
[ newval, self.rowid ])
def sort(self, newval): self._sort = self.update("sort", newval)
def update(self, column, newval):
sql.execute(f"UPDATE playlist_states SET {column}=? WHERE plstateid=?",
[ newval, self.rowid ])
sql.commit()
return newval
class PlaylistStateTable(objects.Table):
class PlaylistStateTable(table.Table):
def __init__(self):
objects.Table.__init__(self, "playlist_states", PlaylistState)
table.Table.__init__(self, "playlist_states")
def do_create(self):
execute("CREATE TABLE IF NOT EXISTS playlist_states "
"(plstateid INTEGER PRIMARY KEY, "
" random INTEGER DEFAULT 0, "
" loop INTEGER DEFAULT 0, "
" current INTEGER DEFAULT -1, "
" sort TEXT)")
sql.execute("CREATE TABLE IF NOT EXISTS playlist_states "
"(plstateid INTEGER PRIMARY KEY, "
" random INTEGER DEFAULT 0, "
" loop INTEGER DEFAULT 0, "
" current INTEGER DEFAULT -1, "
" sort TEXT)")
def do_insert(self, random, loop):
return execute("INSERT INTO playlist_states (random, loop, sort) "
"VALUES (?, ?, ?)", (random, loop, ""))
def do_factory(self, row):
return PlaylistState(row)
def do_delete(self, state):
return execute("DELETE FROM playlist_states WHERE plstateid=?", [ int(state) ])
def do_get(self, rowid):
return execute("SELECT plstateid FROM playlist_states "
"WHERE plstateid=?", [ rowid ])
def insert(self, random=False, loop=False):
return super().insert(random, loop)
def do_insert(self, random=False, loop=False, sort=""):
return sql.execute("INSERT INTO playlist_states (random, loop, sort) "
"VALUES (?, ?, ?)", (random, loop, sort))
Table = PlaylistStateTable()

View File

@ -41,7 +41,7 @@ class TestAlbumTable(unittest.TestCase):
db.album.Table.delete(album)
self.assertIsNone(db.album.Table.lookup(artist, "Test Album"))
self.assertIsNone(db.state.Table.get(int(state)))
self.assertIsNone(db.state.Table.get(state.rowid))
def test_album_table_get(self):
artist = db.artist.Table.insert("Test Artist", "Test Sort")

View File

@ -41,7 +41,7 @@ class TestArtistTable(unittest.TestCase):
db.artist.Table.delete(artist)
self.assertIsNone(db.artist.Table.lookup("Test Artist"))
self.assertIsNone(db.state.Table.get(int(state)))
self.assertIsNone(db.state.Table.get(state.rowid))
def test_artist_table_get(self):
artist = db.artist.Table.insert("Test Artist", "Test Sort")

View File

@ -32,7 +32,7 @@ class TestDecadeTable(unittest.TestCase):
db.decade.Table.delete(decade)
self.assertIsNone(db.decade.Table.lookup(2020))
self.assertIsNone(db.state.Table.get(int(state)))
self.assertIsNone(db.state.Table.get(state.rowid))
def test_decade_table_get(self):
decade = db.decade.Table.insert(2020)

View File

@ -46,7 +46,7 @@ class TestDiscTable(unittest.TestCase):
db.disc.Table.delete(disc)
self.assertIsNone(db.disc.Table.lookup(album, 1))
self.assertIsNone(db.state.Table.get(int(state)))
self.assertIsNone(db.state.Table.get(state.rowid))
def test_disc_table_get(self):
artist = db.artist.Table.insert("Test Artist", "Test Sort")

View File

@ -36,7 +36,7 @@ class TestGenreTable(unittest.TestCase):
state = genre.playlist_state
db.genre.Table.delete(genre)
self.assertIsNone(db.genre.Table.lookup("Test Genre"))
self.assertIsNone(db.state.Table.get(int(state)))
self.assertIsNone(db.state.Table.get(state.rowid))
def test_genre_table_get(self):
genre = db.genre.Table.insert("Test Genre")

View File

@ -35,7 +35,7 @@ class TestLibraryTable(unittest.TestCase):
db.library.Table.delete(library)
self.assertIsNone(db.library.Table.lookup(pathlib.Path("/a/b/c")))
self.assertIsNone(db.state.Table.get(int(state)))
self.assertIsNone(db.state.Table.get(state.rowid))
self.assertIsNone(db.track.Table.get(int(track)))
def test_library_table_get(self):

View File

@ -5,49 +5,69 @@ import unittest
from gi.repository import GObject
class TestPlaylistState(unittest.TestCase):
def test_init(self):
state = db.state.Table.insert()
self.assertIsInstance(state, GObject.GObject)
self.assertIsNotNone(state._plstateid)
self.assertEqual(state.rowid, state._plstateid)
def test_random(self):
state = db.state.Table.insert()
self.assertFalse(state._random)
self.assertFalse(state.get_property("random"))
state.random = True
self.assertTrue(state._random)
def test_loop(self):
state = db.state.Table.insert()
self.assertFalse(state._loop)
self.assertFalse(state.get_property("loop"))
state.loop = True
self.assertTrue(state._loop)
def test_current(self):
state = db.state.Table.insert()
self.assertEqual(state._current, -1)
self.assertEqual(state.current, -1)
state.current = 3
self.assertEqual(state._current, 3)
def test_sort(self):
state = db.state.Table.insert()
self.assertEqual(state._sort, "")
self.assertEqual(state.sort, "")
state.sort = "test"
self.assertEqual(state._sort, "test")
class TestPlaylistStateTable(unittest.TestCase):
def setUp(self):
db.reset()
def test_playlist_state_table_init(self):
def test_init(self):
table = db.state.PlaylistStateTable()
self.assertIsInstance(table, db.table.Table)
self.assertEqual(table.table, "playlist_states")
self.assertIsInstance(db.state.Table, db.state.PlaylistStateTable)
db.sql.execute("SELECT plstateid,random,loop,current,sort "
"FROM playlist_states")
def test_playlist_state_table_insert(self):
state = db.state.Table.insert(False, False)
def test_insert(self):
table = db.state.PlaylistStateTable()
state = table.insert()
self.assertFalse(state.random)
self.assertFalse(state.loop)
self.assertEqual(state.current, -1)
self.assertEqual(state.sort, "")
def test_playlist_state_table_delete(self):
state = db.state.Table.insert(False, False)
db.state.Table.delete(state)
self.assertIsNone(db.state.Table.get(int(state)))
def test_playlist_state_table_get(self):
state = db.state.Table.insert(False, False)
self.assertEqual(db.state.Table.get(int(state)), state)
self.assertIsNone(db.year.Table.get(int(state) + 1))
def test_playlist_state_table_lookup(self):
state = db.state.Table.insert(False, False)
def test_lookup(self):
with self.assertRaises(NotImplementedError):
db.state.Table.lookup()
def test_playlist_state_properties(self):
state = db.state.Table.insert(False, False)
state.random = True
self.assertTrue(state.random)
state.loop = True
self.assertTrue(state.loop)
state.current = 3
self.assertEqual(state.current, 3)
state.sort = "album:True;artist:False"
self.assertEqual(state.sort, "album:True;artist:False")

View File

@ -33,7 +33,7 @@ class TestYearTable(unittest.TestCase):
state = year.playlist_state
db.year.Table.delete(year)
self.assertIsNone(db.year.Table.lookup(2021))
self.assertIsNone(db.state.Table.get(int(state)))
self.assertIsNone(db.state.Table.get(state.rowid))
def test_year_table_get(self):
year = db.year.Table.insert(2021)

View File

@ -26,7 +26,7 @@ class Playlist(objects.Tag):
@GObject.Property
def playlist_state(self):
return state.PlaylistState(self.get_column("plstateid"))
return state.Table.get(self.get_column("plstateid"))
class PlaylistTable(objects.Table):
@ -46,7 +46,7 @@ class PlaylistTable(objects.Table):
def do_insert(self, name, loop=False):
plstate = state.Table.insert(random=False, loop=loop)
return execute("INSERT INTO playlists (plstateid, name, sort) "
"VALUES (?, ?, ?)", (int(plstate), name, name.casefold()))
"VALUES (?, ?, ?)", (plstate.rowid, name, name.casefold()))
def do_delete(self, playlist):
Map.delete_playlist(playlist)

View File

@ -25,7 +25,7 @@ class Year(objects.Row):
@GObject.Property
def playlist_state(self):
return state.PlaylistState(self.get_column("plstateid"))
return state.Table.get(self.get_column("plstateid"))
@GObject.Property
def year(self):
@ -50,7 +50,7 @@ class YearTable(objects.Table):
plstate = state.Table.insert(random=False, loop=False)
return execute("INSERT INTO years (decadeid, plstateid, year) "
"VALUES (?, ?, ?)",
[ int(dec), int(plstate), year ])
[ int(dec), plstate.rowid, year ])
def do_delete(self, year):
state.Table.delete(year.playlist_state)