db: Give Artists knowledge about their Tracks & Properties
I expand on the artists_view to include additional playlist properties, and configure the default sort_order to sort albums in an intuitive way. I then configure the Artists table to us the system_tracks table to manage each artist's associated tracks and set up the artist_tracks_view to make it easy for Tracks to find their Artists. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
6762916899
commit
b4d8a7cfaa
|
@ -78,7 +78,7 @@ class Table(playlist.Table):
|
|||
def __init__(self, sql: GObject.TYPE_PYOBJECT,
|
||||
show_all: bool = False, **kwargs):
|
||||
"""Initialize an Artist model."""
|
||||
super().__init__(sql=sql, show_all=show_all,
|
||||
super().__init__(sql=sql, show_all=show_all, autodelete=True,
|
||||
filter=Filter(show_all=show_all), **kwargs)
|
||||
self.bind_property("show-all", self.get_filter(), "show-all")
|
||||
|
||||
|
|
|
@ -140,14 +140,16 @@ CREATE TABLE artists (
|
|||
);
|
||||
|
||||
CREATE VIEW artists_view AS
|
||||
SELECT artistid, propertyid, name, mbid, active
|
||||
SELECT artistid, propertyid, name, mbid,
|
||||
active, loop, shuffle, sort_order, current_trackid
|
||||
FROM artists
|
||||
JOIN playlist_properties USING (propertyid);
|
||||
|
||||
|
||||
CREATE TRIGGER artists_insert_trigger AFTER INSERT ON artists
|
||||
BEGIN
|
||||
INSERT INTO playlist_properties (active) VALUES (False);
|
||||
INSERT INTO playlist_properties (active, sort_order)
|
||||
VALUES (False, "release, album, mediumno, number");
|
||||
UPDATE artists SET propertyid = last_insert_rowid(),
|
||||
mbid = LOWER(NEW.mbid)
|
||||
WHERE artistid = NEW.artistid;
|
||||
|
@ -516,6 +518,14 @@ CREATE VIEW unplayed_tracks_view AS
|
|||
JOIN libraries USING (libraryid)
|
||||
WHERE tracks.playcount == 0 AND libraries.deleting = FALSE;
|
||||
|
||||
CREATE VIEW artist_tracks_view AS
|
||||
SELECT tracks.trackid, artists.artistid
|
||||
FROM tracks
|
||||
JOIN system_tracks USING (trackid)
|
||||
JOIN artists USING (propertyid)
|
||||
JOIN libraries USING (libraryid)
|
||||
WHERE libraries.deleting = False;
|
||||
|
||||
|
||||
/****************************************************
|
||||
* *
|
||||
|
|
|
@ -46,6 +46,10 @@ class Track(table.Row):
|
|||
case _: return super().do_update(column)
|
||||
return True
|
||||
|
||||
def get_artists(self) -> list[table.Row]:
|
||||
"""Get a list of Artists for this Track."""
|
||||
return self.table.get_artists(self)
|
||||
|
||||
def get_library(self) -> table.Row | None:
|
||||
"""Get the Library associated with this Track."""
|
||||
return self.table.sql.libraries.rows.get(self.libraryid)
|
||||
|
@ -192,6 +196,12 @@ class Table(table.Table):
|
|||
return self.sql(f"UPDATE tracks SET {column}=? WHERE trackid=?",
|
||||
newval, track.trackid)
|
||||
|
||||
def get_artists(self, track: Track) -> list[table.Row]:
|
||||
"""Get the set of Artists for a specific Track."""
|
||||
rows = self.sql("""SELECT artistid FROM artist_tracks_view
|
||||
WHERE trackid=?""", track.trackid).fetchall()
|
||||
return [self.sql.artists.rows.get(row["artistid"]) for row in rows]
|
||||
|
||||
def map_sort_order(self, ordering: str) -> dict[int, int]:
|
||||
"""Get a lookup table for Track sort keys."""
|
||||
ordering = ordering if len(ordering) > 0 else "trackid"
|
||||
|
|
|
@ -104,6 +104,8 @@ class TestArtistTable(tests.util.TestCase):
|
|||
self.assertIsInstance(self.table.get_filter(),
|
||||
emmental.db.artists.Filter)
|
||||
self.assertEqual(len(self.table), 0)
|
||||
self.assertTrue(self.table.autodelete)
|
||||
self.assertTrue(self.table.system_tracks)
|
||||
|
||||
def test_construct(self):
|
||||
"""Test constructing a new artist playlist."""
|
||||
|
@ -116,6 +118,7 @@ class TestArtistTable(tests.util.TestCase):
|
|||
self.assertEqual(artist.name, "Test Artist")
|
||||
self.assertEqual(artist.mbid, "ab-cd-ef")
|
||||
self.assertFalse(artist.active)
|
||||
self.assertFalse(artist.tracks_movable)
|
||||
|
||||
def test_create(self):
|
||||
"""Test creating an artist playlist."""
|
||||
|
@ -125,6 +128,8 @@ class TestArtistTable(tests.util.TestCase):
|
|||
self.assertIsInstance(artist1, emmental.db.artists.Artist)
|
||||
self.assertEqual(artist1.name, "Test Artist")
|
||||
self.assertEqual(artist1.mbid, "")
|
||||
self.assertEqual(artist1.sort_order,
|
||||
"release, album, mediumno, number")
|
||||
self.assertEqual(self.table[0], artist1)
|
||||
|
||||
cur = self.sql("SELECT COUNT(name) FROM artists")
|
||||
|
@ -243,10 +248,19 @@ class TestArtistTable(tests.util.TestCase):
|
|||
"""Test updating artist attributes."""
|
||||
artist = self.table.create("Test Artist")
|
||||
artist.active = True
|
||||
artist.loop = "Track"
|
||||
artist.sort_order = "trackid"
|
||||
artist.shuffle = True
|
||||
|
||||
row = self.sql("""SELECT active FROM playlist_properties
|
||||
WHERE propertyid=?""", artist.propertyid).fetchone()
|
||||
row = self.sql("""SELECT active, loop, sort_order,
|
||||
shuffle, current_trackid
|
||||
FROM artists_view WHERE artistid=?""",
|
||||
artist.artistid).fetchone()
|
||||
self.assertTrue(row["active"])
|
||||
self.assertEqual(row["loop"], "Track")
|
||||
self.assertEqual(row["sort_order"], "trackid")
|
||||
self.assertTrue(row["shuffle"])
|
||||
self.assertIsNone(row["current_trackid"])
|
||||
|
||||
def test_add_remove_album(self):
|
||||
"""Test adding an album to an artist."""
|
||||
|
|
|
@ -64,6 +64,12 @@ class TestTrackObject(tests.util.TestCase):
|
|||
self.assertIsNone(self.track.lastplayed)
|
||||
self.assertIsNone(self.track.restarted)
|
||||
|
||||
def test_get_artists(self):
|
||||
"""Test getting the Artist list for a Track."""
|
||||
self.table.get_artists = unittest.mock.Mock(return_value=[1, 2, 3])
|
||||
self.assertListEqual(self.track.get_artists(), [1, 2, 3])
|
||||
self.table.get_artists.assert_called_with(self.track)
|
||||
|
||||
def test_get_library(self):
|
||||
"""Test getting the Library associated with a Track."""
|
||||
self.assertEqual(self.track.get_library(), self.library)
|
||||
|
@ -442,6 +448,18 @@ class TestTrackTable(tests.util.TestCase):
|
|||
track.trackid).fetchone()
|
||||
self.assertFalse(row["active"])
|
||||
|
||||
def test_get_artists(self):
|
||||
"""Test finding the artists for a track."""
|
||||
track = self.tracks.create(self.library, pathlib.Path("a/b/1.ogg"),
|
||||
self.medium, self.year)
|
||||
artist1 = self.sql.artists.create("Artist 1")
|
||||
artist2 = self.sql.artists.create("Artist 2")
|
||||
|
||||
artist1.add_track(track)
|
||||
artist2.add_track(track)
|
||||
self.assertListEqual(self.tracks.get_artists(track),
|
||||
[artist1, artist2])
|
||||
|
||||
def test_mark_path_active(self):
|
||||
"""Test marking a path as active."""
|
||||
self.tracks.create(self.library, pathlib.Path("/a/b/1.ogg"),
|
||||
|
|
Loading…
Reference in New Issue