db: Detect deleted Tracks during Library scanning

And use the tagger.untag_track() function to clean up and remove them
from the database.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2023-04-12 16:57:49 -04:00
parent 3cda4caa76
commit eea763f133
2 changed files with 39 additions and 2 deletions

View File

@ -28,6 +28,13 @@ class Library(playlist.Playlist):
super().__init__(queue=idle.Queue(), **kwargs)
self.scan()
def __check_trackid(self, trackid: int) -> bool:
track = self.table.sql.tracks.rows.get(trackid)
if track is not None and not track.path.exists():
tagger.untag_track(self.table.sql, track)
track.delete()
return True
def __queue_delete(self) -> bool:
self.table.delete(self)
return True
@ -55,6 +62,9 @@ class Library(playlist.Playlist):
self.readdir = path.readdir_async(self.path)
if self.readdir is not None:
self.online = True
self.load_tracks()
self.queue.push_many(self.__check_trackid,
[(tid,) for tid in self.tracks.trackids])
self.queue.push(self.__queue_tracks)
self.tagger = tagger.Thread()
return True

View File

@ -75,6 +75,8 @@ class TestLibraryObject(tests.util.TestCase):
"""Test scanning an online Library path."""
self.assertEqual(self.library.queue[0],
(self.library._Library__scan_library,))
self.library.tracks.trackids = {1, 2, 3}
self.library.load_tracks = unittest.mock.Mock()
with unittest.mock.patch.object(self.library.queue,
"push") as mock_push:
@ -83,6 +85,7 @@ class TestLibraryObject(tests.util.TestCase):
mock_is_dir.return_value = True
self.assertTrue(self.library.queue.run_task())
self.library.load_tracks.assert_called()
mock_is_dir.assert_called()
self.assertTrue(self.library.online)
@ -91,8 +94,11 @@ class TestLibraryObject(tests.util.TestCase):
emmental.path.ReaddirThread)
self.assertIsInstance(self.library.tagger,
emmental.db.tagger.Thread)
self.assertEqual(self.library.queue[0],
(self.library._Library__queue_tracks,))
self.assertEqual(self.library.queue._tasks,
[(self.library._Library__check_trackid, 1),
(self.library._Library__check_trackid, 2),
(self.library._Library__check_trackid, 3),
(self.library._Library__queue_tracks,)])
def test_scan_offline(self):
"""Test scanning an offline Library path."""
@ -166,6 +172,27 @@ class TestLibraryObject(tests.util.TestCase):
tagger.tag_file.assert_not_called()
tagger.get_result.assert_called_with(self.sql, self.library)
@unittest.mock.patch("emmental.db.tagger.untag_track")
def test_scan_check_trackid(self, mock_untag: unittest.mock.Mock()):
"""Test that deleted Tracks are removed during scanning."""
track = unittest.mock.Mock()
track.path = pathlib.Path("/a/b/c/1.ogg")
self.library._Library__check_trackid(1)
mock_untag.assert_not_called()
self.sql.tracks.rows[1] = track
with unittest.mock.patch.object(type(track.path),
"exists") as mock_exists:
mock_exists.return_value = True
self.library._Library__check_trackid(1)
mock_untag.assert_not_called()
track.delete.assert_not_called()
self.library._Library__check_trackid(1)
mock_untag.assert_called_with(self.sql, track)
track.delete.assert_called()
def test_stop(self):
"""Test stopping a Library's background work."""
readdir = unittest.mock.Mock()