1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Porting supysonic.watcher

Which mostly means fixing the scanner
This commit is contained in:
Alban Féron 2022-12-11 15:40:23 +01:00
parent cd369f6c7f
commit c5246c74bb
No known key found for this signature in database
GPG Key ID: 8CE0313646D16165
4 changed files with 57 additions and 68 deletions

View File

@ -291,19 +291,20 @@ class Scanner(Thread):
except Track.DoesNotExist: except Track.DoesNotExist:
return return
tr_dst = Track.get(path=dst_path) try:
if tr_dst is not None: tr_dst = Track.get(path=dst_path)
root = tr_dst.root_folder root = tr_dst.root_folder
folder = tr_dst.folder folder = tr_dst.folder
self.remove_file(dst_path) self.remove_file(dst_path)
tr.root_folder = root tr.root_folder = root
tr.folder = folder tr.folder = folder
else: except Track.DoesNotExist:
root = self.__find_root_folder(dst_path) root = self.__find_root_folder(dst_path)
folder = self.__find_folder(dst_path) folder = self.__find_folder(dst_path)
tr.root_folder = root tr.root_folder = root
tr.folder = folder tr.folder = folder
tr.path = dst_path tr.path = dst_path
tr.save()
def find_cover(self, dirpath): def find_cover(self, dirpath):
if not isinstance(dirpath, str): # pragma: nocover if not isinstance(dirpath, str): # pragma: nocover
@ -312,8 +313,9 @@ class Scanner(Thread):
if not os.path.exists(dirpath): if not os.path.exists(dirpath):
return return
folder = Folder.get(path=dirpath) try:
if folder is None: folder = Folder.get(path=dirpath)
except Folder.DoesNotExist:
return return
album_name = None album_name = None
@ -323,18 +325,21 @@ class Scanner(Thread):
cover = find_cover_in_folder(folder.path, album_name) cover = find_cover_in_folder(folder.path, album_name)
folder.cover_art = cover.name if cover is not None else None folder.cover_art = cover.name if cover is not None else None
folder.save()
def add_cover(self, path): def add_cover(self, path):
if not isinstance(path, str): # pragma: nocover if not isinstance(path, str): # pragma: nocover
raise TypeError("Expecting string, got " + str(type(path))) raise TypeError("Expecting string, got " + str(type(path)))
folder = Folder.get(path=os.path.dirname(path)) try:
if folder is None: folder = Folder.get(path=os.path.dirname(path))
except Folder.DoesNotExist:
return return
cover_name = os.path.basename(path) cover_name = os.path.basename(path)
if not folder.cover_art: if not folder.cover_art:
folder.cover_art = cover_name folder.cover_art = cover_name
folder.save()
elif folder.cover_art != cover_name: elif folder.cover_art != cover_name:
album_name = None album_name = None
track = folder.tracks.select().first() track = folder.tracks.select().first()
@ -345,6 +350,7 @@ class Scanner(Thread):
new_cover = CoverFile(cover_name, album_name) new_cover = CoverFile(cover_name, album_name)
if new_cover.score > current_cover.score: if new_cover.score > current_cover.score:
folder.cover_art = cover_name folder.cover_art = cover_name
folder.save()
def __find_album(self, artist, album): def __find_album(self, artist, album):
ar = self.__find_artist(artist) ar = self.__find_artist(artist)
@ -379,9 +385,11 @@ class Scanner(Thread):
drive, _ = os.path.splitdrive(path) drive, _ = os.path.splitdrive(path)
path = os.path.dirname(path) path = os.path.dirname(path)
while path not in (drive, "/"): while path not in (drive, "/"):
folder = Folder.get(path=path) try:
if folder is not None: folder = Folder.get(path=path)
break break
except Folder.DoesNotExist:
pass
created = datetime.fromtimestamp(os.path.getmtime(path)) created = datetime.fromtimestamp(os.path.getmtime(path))
children.append( children.append(
@ -396,7 +404,7 @@ class Scanner(Thread):
assert folder is not None assert folder is not None
while children: while children:
folder = Folder(parent=folder, **children.pop()) folder = Folder.create(parent=folder, **children.pop())
return folder return folder

View File

@ -49,9 +49,9 @@ class SupysonicWatcherEventHandler(PatternMatchingEventHandler):
self.queue.put(event.src_path, op) self.queue.put(event.src_path, op)
dirname = os.path.dirname(event.src_path) dirname = os.path.dirname(event.src_path)
with db_session: try:
folder = Folder.get(path=dirname) Folder.get(path=dirname)
if folder is None: except Folder.DoesNotExist:
self.queue.put(dirname, op | FLAG_COVER) self.queue.put(dirname, op | FLAG_COVER)
else: else:
self.queue.put(event.src_path, op | FLAG_COVER) self.queue.put(event.src_path, op | FLAG_COVER)
@ -289,9 +289,8 @@ class SupysonicWatcher:
self.__observer = Observer() self.__observer = Observer()
self.__handler.queue = self.__queue self.__handler.queue = self.__queue
with db_session: for folder in Folder.select().where(Folder.root):
for folder in Folder.select(lambda f: f.root): self.add_folder(folder)
self.add_folder(folder)
logger.info("Starting watcher") logger.info("Starting watcher")
self.__queue.start() self.__queue.start()

View File

@ -109,6 +109,8 @@ class ScannerTestCase(unittest.TestCase):
track = db.Track.select().first() track = db.Track.select().first()
new_path = track.path.replace("silence", "silence_moved") new_path = track.path.replace("silence", "silence_moved")
self.scanner.move_file(track.path, new_path) self.scanner.move_file(track.path, new_path)
track = db.Track.select().first()
self.assertEqual(db.Track.select().count(), 1) self.assertEqual(db.Track.select().count(), 1)
self.assertEqual(track.path, new_path) self.assertEqual(track.path, new_path)

View File

@ -13,7 +13,6 @@ import time
import unittest import unittest
from hashlib import sha1 from hashlib import sha1
from pony.orm import db_session
from supysonic.db import init_database, release_database, Track, Artist, Folder from supysonic.db import init_database, release_database, Track, Artist, Folder
from supysonic.managers.folder import FolderManager from supysonic.managers.folder import FolderManager
@ -64,8 +63,7 @@ class WatcherTestCase(WatcherTestBase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.__dir = tempfile.mkdtemp() self.__dir = tempfile.mkdtemp()
with db_session: FolderManager.add("Folder", self.__dir)
FolderManager.add("Folder", self.__dir)
self._start() self._start()
def tearDown(self): def tearDown(self):
@ -101,7 +99,6 @@ class WatcherTestCase(WatcherTestBase):
class AudioWatcherTestCase(WatcherTestCase): class AudioWatcherTestCase(WatcherTestCase):
@db_session
def assertTrackCountEqual(self, expected): def assertTrackCountEqual(self, expected):
self.assertEqual(Track.select().count(), expected) self.assertEqual(Track.select().count(), expected)
@ -124,57 +121,49 @@ class AudioWatcherTestCase(WatcherTestCase):
self._addfile() self._addfile()
self.assertTrackCountEqual(0) self.assertTrackCountEqual(0)
self._sleep() self._sleep()
with db_session:
self.assertEqual(Track.select().count(), 3) self.assertEqual(Track.select().count(), 3)
self.assertEqual(Artist.select().count(), 1) self.assertEqual(Artist.select().count(), 1)
def test_change(self): def test_change(self):
path = self._addfile() path = self._addfile()
self._sleep() self._sleep()
trackid = None trackid = None
with db_session: self.assertEqual(Track.select().count(), 1)
self.assertEqual(Track.select().count(), 1) self.assertEqual(Artist.select().where(Artist.name == "Some artist").count(), 1)
self.assertEqual( trackid = Track.select().first().id
Artist.select(lambda a: a.name == "Some artist").count(), 1
)
trackid = Track.select().first().id
tags = mutagen.File(path, easy=True) tags = mutagen.File(path, easy=True)
tags["artist"] = "Renamed" tags["artist"] = "Renamed"
tags.save() tags.save()
self._sleep() self._sleep()
with db_session: self.assertEqual(Track.select().count(), 1)
self.assertEqual(Track.select().count(), 1) self.assertEqual(Artist.select().where(Artist.name == "Some artist").count(), 0)
self.assertEqual( self.assertEqual(Artist.select().where(Artist.name == "Renamed").count(), 1)
Artist.select(lambda a: a.name == "Some artist").count(), 0 self.assertEqual(Track.select().first().id, trackid)
)
self.assertEqual(Artist.select(lambda a: a.name == "Renamed").count(), 1)
self.assertEqual(Track.select().first().id, trackid)
def test_rename(self): def test_rename(self):
path = self._addfile() path = self._addfile()
self._sleep() self._sleep()
trackid = None trackid = None
with db_session: self.assertEqual(Track.select().count(), 1)
self.assertEqual(Track.select().count(), 1) trackid = Track.select().first().id
trackid = Track.select().first().id
newpath = self._temppath(".mp3") newpath = self._temppath(".mp3")
shutil.move(path, newpath) shutil.move(path, newpath)
self._sleep() self._sleep()
with db_session: track = Track.select().first()
track = Track.select().first() self.assertIsNotNone(track)
self.assertIsNotNone(track) self.assertNotEqual(track.path, path)
self.assertNotEqual(track.path, path) self.assertEqual(track.path, newpath)
self.assertEqual(track.path, newpath) self.assertEqual(
self.assertEqual( track._path_hash, memoryview(sha1(newpath.encode("utf-8")).digest())
track._path_hash, memoryview(sha1(newpath.encode("utf-8")).digest()) )
) self.assertEqual(track.id, trackid)
self.assertEqual(track.id, trackid)
def test_move_in(self): def test_move_in(self):
filename = self._tempname() + ".mp3" filename = self._tempname() + ".mp3"
@ -255,16 +244,14 @@ class CoverWatcherTestCase(WatcherTestCase):
path = self._addcover() path = self._addcover()
self._sleep() self._sleep()
with db_session: self.assertEqual(Folder.select().first().cover_art, os.path.basename(path))
self.assertEqual(Folder.select().first().cover_art, os.path.basename(path))
def test_add_cover_then_file(self): def test_add_cover_then_file(self):
path = self._addcover() path = self._addcover()
self._addfile() self._addfile()
self._sleep() self._sleep()
with db_session: self.assertEqual(Folder.select().first().cover_art, os.path.basename(path))
self.assertEqual(Folder.select().first().cover_art, os.path.basename(path))
def test_remove_cover(self): def test_remove_cover(self):
self._addfile() self._addfile()
@ -274,8 +261,7 @@ class CoverWatcherTestCase(WatcherTestCase):
os.unlink(path) os.unlink(path)
self._sleep() self._sleep()
with db_session: self.assertIsNone(Folder.select().first().cover_art)
self.assertIsNone(Folder.select().first().cover_art)
def test_naming_add_good(self): def test_naming_add_good(self):
self._addcover() self._addcover()
@ -283,8 +269,7 @@ class CoverWatcherTestCase(WatcherTestCase):
good = os.path.basename(self._addcover("cover")) good = os.path.basename(self._addcover("cover"))
self._sleep() self._sleep()
with db_session: self.assertEqual(Folder.select().first().cover_art, good)
self.assertEqual(Folder.select().first().cover_art, good)
def test_naming_add_bad(self): def test_naming_add_bad(self):
good = os.path.basename(self._addcover("cover")) good = os.path.basename(self._addcover("cover"))
@ -292,8 +277,7 @@ class CoverWatcherTestCase(WatcherTestCase):
self._addcover() self._addcover()
self._sleep() self._sleep()
with db_session: self.assertEqual(Folder.select().first().cover_art, good)
self.assertEqual(Folder.select().first().cover_art, good)
def test_naming_remove_good(self): def test_naming_remove_good(self):
bad = self._addcover() bad = self._addcover()
@ -302,8 +286,7 @@ class CoverWatcherTestCase(WatcherTestCase):
os.unlink(good) os.unlink(good)
self._sleep() self._sleep()
with db_session: self.assertEqual(Folder.select().first().cover_art, os.path.basename(bad))
self.assertEqual(Folder.select().first().cover_art, os.path.basename(bad))
def test_naming_remove_bad(self): def test_naming_remove_bad(self):
bad = self._addcover() bad = self._addcover()
@ -312,8 +295,7 @@ class CoverWatcherTestCase(WatcherTestCase):
os.unlink(bad) os.unlink(bad)
self._sleep() self._sleep()
with db_session: self.assertEqual(Folder.select().first().cover_art, os.path.basename(good))
self.assertEqual(Folder.select().first().cover_art, os.path.basename(good))
def test_rename(self): def test_rename(self):
path = self._addcover() path = self._addcover()
@ -322,17 +304,15 @@ class CoverWatcherTestCase(WatcherTestCase):
shutil.move(path, newpath) shutil.move(path, newpath)
self._sleep() self._sleep()
with db_session: self.assertEqual(Folder.select().first().cover_art, os.path.basename(newpath))
self.assertEqual(
Folder.select().first().cover_art, os.path.basename(newpath)
)
def test_add_to_folder_without_track(self): def test_add_to_folder_without_track(self):
path = self._addcover(depth=1) path = self._addcover(depth=1)
self._sleep() self._sleep()
with db_session: self.assertFalse(
self.assertFalse(Folder.exists(cover_art=os.path.basename(path))) Folder.select().where(Folder.cover_art == os.path.basename(path)).exists()
)
def test_remove_from_folder_without_track(self): def test_remove_from_folder_without_track(self):
path = self._addcover(depth=1) path = self._addcover(depth=1)