From 0fd106948406c493ba0be9255edb55b1ea619556 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Sun, 22 Aug 2021 09:38:14 -0400 Subject: [PATCH] db: Add a PlaylistMap And create both permanent and temporary maps for tracks. The temporary map is intended to be used for the New Tracks and Previous playlists, since we don't store the state across restarts. Signed-off-by: Anna Schumaker --- db/__init__.py | 2 ++ db/playlist.py | 48 +++++++++++++++++++++++++ db/test_playlist.py | 85 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/db/__init__.py b/db/__init__.py index b6f72d8..3144c7f 100644 --- a/db/__init__.py +++ b/db/__init__.py @@ -39,3 +39,5 @@ def reset(): for mod in mods: mod.Table.do_create() genre.Map.reset() + playlist.Map.reset() + playlist.TempMap.reset() diff --git a/db/playlist.py b/db/playlist.py index 5c619c9..8f65a69 100644 --- a/db/playlist.py +++ b/db/playlist.py @@ -44,6 +44,8 @@ class PlaylistTable(objects.Table): "VALUES (?, ?)", (name, name.casefold())) def do_delete(self, playlist): + Map.delete_playlist(playlist) + TempMap.delete_playlist(playlist) return execute("DELETE FROM playlists WHERE playlistid=?", [ int(playlist) ]) def do_get(self, rowid): @@ -55,4 +57,50 @@ class PlaylistTable(objects.Table): "WHERE name=?", [ name ]) +class PlaylistMap(objects.Map): + def __init__(self, temp=False): + name = "playlist_map" if temp==False else "temp_playlist_map" + self.temporary = temp + + objects.Map.__init__(self, name, Playlist, track.Track) + self.lookup_tracks = self.lookup_rhs + self.lookup_playlists = self.lookup_lhs + + def do_create(self): + temp = "" if self.temporary == False else "TEMPORARY" + execute(f"CREATE {temp} TABLE IF NOT EXISTS {self.map_name} " + "(playlistid INTEGER, " + " trackid INTEGER, " + " FOREIGN KEY(playlistid) REFERENCES playlists(playlistid), " + " FOREIGN KEY(trackid) REFERENCES tracks(trackid), " + " UNIQUE(playlistid, trackid))") + + def do_insert(self, playlist, track): + execute(f"INSERT INTO {self.map_name} (playlistid, trackid) " + "VALUES (?, ?)", [ int(playlist), int(track) ]) + + def do_delete(self, playlist, track): + return execute(f"DELETE FROM {self.map_name} " + "WHERE playlistid=? AND trackid=?", + [ int(playlist), int(track) ]) + + def do_lookup_rhs(self, playlist): + return execute(f"SELECT trackid FROM {self.map_name} " + "WHERE playlistid=?", [ int(playlist) ]) + + def do_lookup_lhs(self, track): + return execute(f"SELECT playlistid FROM {self.map_name} " + "WHERE trackid=?", [ int(track) ]) + + def delete_track(self, track): + for playlist in self.lookup_playlists(track): + self.delete(playlist, track) + + def delete_playlist(self, playlist): + for track in self.lookup_tracks(playlist): + self.delete(playlist, track) + + Table = PlaylistTable() +Map = PlaylistMap(temp=False) +TempMap = PlaylistMap(temp=True) diff --git a/db/test_playlist.py b/db/test_playlist.py index 509f0ed..85e083b 100644 --- a/db/test_playlist.py +++ b/db/test_playlist.py @@ -41,8 +41,15 @@ class TestPlaylistTable(unittest.TestCase): def test_playlist_table_delete(self): playlist = db.playlist.Table.find("Test Playlist") + track = db.make_fake_track(1, 1.234, "Test Title", "/a/b.cde") + + db.playlist.Map.insert(playlist, track) + db.playlist.TempMap.insert(playlist, track) db.playlist.Table.delete(playlist) + self.assertIsNone(db.playlist.Table.lookup("Test Playlist")) + self.assertEqual(db.playlist.Map.lookup_playlists(track), [ ]) + self.assertEqual(db.playlist.TempMap.lookup_playlists(track), [ ]) def test_playlist_table_get(self): playlist = db.playlist.Playlist(1) @@ -53,3 +60,81 @@ class TestPlaylistTable(unittest.TestCase): playlist = db.playlist.Table.insert("Test Playlist") self.assertEqual(db.playlist.Table.lookup("Test Playlist"), playlist) self.assertIsNone(db.playlist.Table.lookup("none")) + + +class TestPlaylistMap(unittest.TestCase): + def setUp(self): + db.reset() + + def test_playlist_map_init(self): + self.assertIsInstance(db.playlist.Map, db.playlist.PlaylistMap) + self.assertIsInstance(db.playlist.TempMap, db.playlist.PlaylistMap) + + self.assertEqual(db.playlist.Map.map_lhs, db.playlist.Playlist) + self.assertEqual(db.playlist.Map.map_rhs, db.track.Track) + + self.assertFalse(db.playlist.Map.temporary) + self.assertTrue( db.playlist.TempMap.temporary) + + db.execute("SELECT playlistid,trackid FROM playlist_map") + db.execute("SELECT playlistid,trackid FROM temp_playlist_map") + + def test_playlist_map_insert(self): + track = db.make_fake_track(1, 1.234, "Test Title", "/a/b.cde") + collection = db.playlist.Table.find("Collection") + + db.playlist.Map.insert(collection, track) + with self.assertRaises(sqlite3.IntegrityError): + db.playlist.Map.insert(collection, track) + + def test_playlist_map_delete(self): + track = db.make_fake_track(1, 1.234, "Test Title", "/a/b.cde") + playlist = db.playlist.Table.find("Test Playlist") + + db.playlist.Map.insert(playlist, track) + db.playlist.Map.delete(playlist, track) + self.assertEqual(db.playlist.Map.lookup_tracks(playlist), [ ]) + + def test_playlist_map_lookup_tracks(self): + track1 = db.make_fake_track(1, 1.234, "Test Title", "/a/b.cde") + track2 = db.make_fake_track(2, 2.345, "Test Title 2", "/a/c.def") + playlist = db.playlist.Table.find("Collection") + + db.playlist.Map.insert(playlist, track1) + db.playlist.Map.insert(playlist, track2) + + lookup_res = db.playlist.Map.lookup_tracks(playlist) + self.assertEqual(lookup_res, [ track1, track2 ]) + + def test_playlist_map_lookup_playlists(self): + track = db.make_fake_track(1, 1.234, "Test Title", "/a/b.cde") + collection = db.playlist.Table.find("Collection") + favorites = db.playlist.Table.find("Favorites") + + db.playlist.Map.insert(collection, track) + db.playlist.Map.insert(favorites, track) + + lookup_res = db.playlist.Map.lookup_playlists(track) + self.assertEqual(lookup_res, [ collection, favorites ]) + + def test_playlist_map_delete_track(self): + track = db.make_fake_track(1, 1.234, "Test Title", "/a/b.cde") + collection = db.playlist.Table.find("Collection") + favorites = db.playlist.Table.find("Favorites") + + db.playlist.Map.insert(collection, track) + db.playlist.Map.insert(favorites, track) + + db.playlist.Map.delete_track(track) + self.assertEqual(db.playlist.Map.lookup_playlists(track), [ ]) + + def test_playlist_map_delete_playlist(self): + track1 = db.make_fake_track(1, 1.234, "Test Title", "/a/b.cde") + track2 = db.make_fake_track(2, 2.345, "Test Title 2", "/a/c.def") + playlist = db.playlist.Table.find("Collection") + + db.playlist.Map.insert(playlist, track1) + db.playlist.Map.insert(playlist, track2) + + db.playlist.Map.delete_playlist(playlist) + self.assertEqual(db.playlist.Map.lookup_tracks(playlist), [ ])