db: Add a Track object
The Track object represents a single track in the Library along with all their corresponding metadata. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
afb599dcf4
commit
24cb87d298
|
@ -0,0 +1,64 @@
|
||||||
|
# Copyright 2022 (c) Anna Schumaker.
|
||||||
|
"""A custom Gio.ListModel for working with tracks."""
|
||||||
|
from gi.repository import GObject
|
||||||
|
from . import table
|
||||||
|
|
||||||
|
|
||||||
|
PLAYED_THRESHOLD = 2 / 3
|
||||||
|
|
||||||
|
|
||||||
|
class Track(table.Row):
|
||||||
|
"""Our custom Track object."""
|
||||||
|
|
||||||
|
trackid = GObject.Property(type=int)
|
||||||
|
libraryid = GObject.Property(type=int)
|
||||||
|
mediumid = GObject.Property(type=int)
|
||||||
|
year = GObject.Property(type=int)
|
||||||
|
|
||||||
|
active = GObject.Property(type=bool, default=False)
|
||||||
|
favorite = GObject.Property(type=bool, default=False)
|
||||||
|
|
||||||
|
path = GObject.Property(type=GObject.TYPE_PYOBJECT)
|
||||||
|
mbid = GObject.Property(type=str)
|
||||||
|
title = GObject.Property(type=str)
|
||||||
|
artist = GObject.Property(type=str)
|
||||||
|
number = GObject.Property(type=int)
|
||||||
|
length = GObject.Property(type=float)
|
||||||
|
mtime = GObject.Property(type=float)
|
||||||
|
playcount = GObject.Property(type=int)
|
||||||
|
added = GObject.Property(type=GObject.TYPE_PYOBJECT)
|
||||||
|
|
||||||
|
laststarted = GObject.Property(type=GObject.TYPE_PYOBJECT)
|
||||||
|
lastplayed = GObject.Property(type=GObject.TYPE_PYOBJECT)
|
||||||
|
restarted = GObject.Property(type=GObject.TYPE_PYOBJECT)
|
||||||
|
|
||||||
|
def do_update(self, column: str) -> bool:
|
||||||
|
"""Update a Track object."""
|
||||||
|
match column:
|
||||||
|
case "trackid" | "libraryid" | "active" | "path" | "playcount" | \
|
||||||
|
"laststarted" | "lastplayed" | "restarted": pass
|
||||||
|
case _: return super().do_update(column)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_library(self) -> table.Row | None:
|
||||||
|
"""Get the Library associated with this Track."""
|
||||||
|
return self.table.sql.libraries.rows.get(self.libraryid)
|
||||||
|
|
||||||
|
def get_medium(self) -> table.Row | None:
|
||||||
|
"""Get the Medium associated with this Track."""
|
||||||
|
return self.table.sql.media.rows.get(self.mediumid)
|
||||||
|
|
||||||
|
def get_year(self) -> table.Row | None:
|
||||||
|
"""Get the Year associated with this Track."""
|
||||||
|
return self.table.sql.years.rows.get(self.year)
|
||||||
|
|
||||||
|
def update_properties(self, **kwargs) -> None:
|
||||||
|
"""Update one or more of this Track's properties."""
|
||||||
|
for (property, newval) in kwargs.items():
|
||||||
|
if self.get_property(property) != newval:
|
||||||
|
self.set_property(property, newval)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def primary_key(self) -> int:
|
||||||
|
"""Get the primary key for this Track."""
|
||||||
|
return self.trackid
|
|
@ -0,0 +1,105 @@
|
||||||
|
# Copyright 2022 (c) Anna Schumaker.
|
||||||
|
"""Tests our track Gio.ListModel."""
|
||||||
|
import datetime
|
||||||
|
import pathlib
|
||||||
|
import emmental.db.tracks
|
||||||
|
import tests.util
|
||||||
|
import unittest.mock
|
||||||
|
from gi.repository import Gio
|
||||||
|
|
||||||
|
|
||||||
|
class TestTrackObject(tests.util.TestCase):
|
||||||
|
"""Tests our track object."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Set up common variables."""
|
||||||
|
super().setUp()
|
||||||
|
self.table = Gio.ListStore()
|
||||||
|
self.table.sql = self.sql
|
||||||
|
self.table.update = unittest.mock.Mock()
|
||||||
|
|
||||||
|
self.library = self.sql.libraries.create(pathlib.Path("/a/b"))
|
||||||
|
self.album = self.sql.albums.create("Test Album", "Test Artist",
|
||||||
|
release="1988-06")
|
||||||
|
self.medium = self.sql.media.create(self.album, "", number=1)
|
||||||
|
self.year = self.sql.years.create(1988)
|
||||||
|
|
||||||
|
self.track = emmental.db.tracks.Track(trackid=12345, table=self.table,
|
||||||
|
libraryid=self.library.libraryid,
|
||||||
|
mediumid=self.medium.mediumid,
|
||||||
|
year=self.year.year,
|
||||||
|
path=pathlib.Path("/a/b/c.ogg"))
|
||||||
|
|
||||||
|
def test_constants(self):
|
||||||
|
"""Test constant values."""
|
||||||
|
self.assertEqual(emmental.db.tracks.PLAYED_THRESHOLD, (2 / 3))
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
"""Test that the Track is set up properly."""
|
||||||
|
self.assertIsInstance(self.track, emmental.db.table.Row)
|
||||||
|
self.assertEqual(self.track.table, self.table)
|
||||||
|
self.assertEqual(self.track.trackid, 12345)
|
||||||
|
self.assertEqual(self.track.primary_key, 12345)
|
||||||
|
self.assertEqual(self.track.libraryid, self.library.libraryid)
|
||||||
|
self.assertEqual(self.track.mediumid, self.medium.mediumid)
|
||||||
|
self.assertEqual(self.track.year, self.year.year)
|
||||||
|
|
||||||
|
self.assertFalse(self.track.active)
|
||||||
|
self.assertFalse(self.track.favorite)
|
||||||
|
|
||||||
|
self.assertEqual(self.track.path, pathlib.Path("/a/b/c.ogg"))
|
||||||
|
self.assertEqual(self.track.mbid, "")
|
||||||
|
self.assertEqual(self.track.title, "")
|
||||||
|
self.assertEqual(self.track.artist, "")
|
||||||
|
self.assertEqual(self.track.number, 0)
|
||||||
|
self.assertEqual(self.track.length, 0.0)
|
||||||
|
self.assertEqual(self.track.mtime, 0.0)
|
||||||
|
self.assertEqual(self.track.playcount, 0)
|
||||||
|
|
||||||
|
self.assertIsNone(self.track.added)
|
||||||
|
self.assertIsNone(self.track.laststarted)
|
||||||
|
self.assertIsNone(self.track.lastplayed)
|
||||||
|
self.assertIsNone(self.track.restarted)
|
||||||
|
|
||||||
|
def test_get_library(self):
|
||||||
|
"""Test getting the Library associated with a Track."""
|
||||||
|
self.assertEqual(self.track.get_library(), self.library)
|
||||||
|
|
||||||
|
def test_get_medium(self):
|
||||||
|
"""Test getting a Medium playlist."""
|
||||||
|
self.assertEqual(self.track.get_medium(), self.medium)
|
||||||
|
|
||||||
|
def test_get_year(self):
|
||||||
|
"""Test getting a Year playlist."""
|
||||||
|
self.assertEqual(self.track.get_year(), self.year)
|
||||||
|
|
||||||
|
def test_update_properties(self):
|
||||||
|
"""Test updating track properties."""
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
self.track.update_properties(trackid=1, libraryid=1, active=True,
|
||||||
|
path=pathlib.Path("/a/b/c.ogg"),
|
||||||
|
playcount=1, laststarted=now,
|
||||||
|
lastplayed=now, restarted=now)
|
||||||
|
self.table.update.assert_not_called()
|
||||||
|
|
||||||
|
self.track.update_properties(mediumid=2, favorite=True, year=1985,
|
||||||
|
mbid="ab-cd-ef", title="New Title",
|
||||||
|
artist="New Artist", number=2,
|
||||||
|
length=12.345, mtime=67.890)
|
||||||
|
self.table.update.assert_has_calls(
|
||||||
|
[unittest.mock.call(self.track, "mediumid", 2),
|
||||||
|
unittest.mock.call(self.track, "favorite", True),
|
||||||
|
unittest.mock.call(self.track, "year", 1985),
|
||||||
|
unittest.mock.call(self.track, "mbid", "ab-cd-ef"),
|
||||||
|
unittest.mock.call(self.track, "title", "New Title"),
|
||||||
|
unittest.mock.call(self.track, "artist", "New Artist"),
|
||||||
|
unittest.mock.call(self.track, "number", 2),
|
||||||
|
unittest.mock.call(self.track, "length", 12.345),
|
||||||
|
unittest.mock.call(self.track, "mtime", 67.890)])
|
||||||
|
|
||||||
|
self.table.update.reset_mock()
|
||||||
|
self.track.update_properties(mediumid=2, favorite=True, year=1985,
|
||||||
|
mbid="ab-cd-ef", title="New Title",
|
||||||
|
artist="New Artist", number=2,
|
||||||
|
length=12.345, mtime=67.890)
|
||||||
|
self.table.update.assert_not_called()
|
Loading…
Reference in New Issue