curds: Move the ThreadPoolExecutor into the track code
I think it makes sense to do this transparently through the Track code so higher layers don't have to do as much work. We'll just return a Future-object corresponding to the track that will be added. It makes sense to only have one thread in this case, since __add() needs exclusive access to the track_list for its entire execution. Anything more would just create conflicts and actually increase execution time. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
2c022163ad
commit
1eac742bc4
|
@ -1,15 +1,17 @@
|
|||
# Copyright 2019 (c) Anna Schumaker.
|
||||
import asyncio
|
||||
import concurrent.futures
|
||||
import mutagen
|
||||
import unittest
|
||||
import os
|
||||
import track
|
||||
import unittest
|
||||
|
||||
test_tracks = os.path.abspath("./trier/Test Album")
|
||||
test_library = os.path.abspath("./trier/Test Library")
|
||||
|
||||
class TestTrackClass(unittest.TestCase):
|
||||
def setUp(self):
|
||||
track.track_list.clear()
|
||||
|
||||
def test_init_basic(self):
|
||||
p = [ test_tracks, "01 - Test Track.ogg" ]
|
||||
t = track.Track(os.path.join(*p))
|
||||
|
@ -23,7 +25,7 @@ class TestTrackClass(unittest.TestCase):
|
|||
self.assertEqual(t.album.date, 2019)
|
||||
self.assertEqual(t.album.genre, "Test")
|
||||
self.assertEqual(t.album.albumartist, "Test Artist")
|
||||
self.assertEqual(len(track.tracklist), 0)
|
||||
self.assertEqual(len(track.track_list), 0)
|
||||
|
||||
def test_init_empty(self):
|
||||
p = [ test_tracks, "00 - Empty Track.ogg" ]
|
||||
|
@ -38,7 +40,7 @@ class TestTrackClass(unittest.TestCase):
|
|||
self.assertEqual(t.album.date, 0)
|
||||
self.assertEqual(t.album.genre, "Unknown")
|
||||
self.assertEqual(t.album.albumartist, "Unknown Artist")
|
||||
self.assertEqual(len(track.tracklist), 0)
|
||||
self.assertEqual(len(track.track_list), 0)
|
||||
|
||||
def test_init_discno_detect(self):
|
||||
join = os.path.join
|
||||
|
@ -53,35 +55,40 @@ class TestTrackClass(unittest.TestCase):
|
|||
self.assertEqual(track.Track(join(test_tracks, "10 - Test {Disc 20}.ogg")).discnumber, 20)
|
||||
|
||||
def test_track_add(self):
|
||||
track.tracklist.clear()
|
||||
t = track.add(os.path.join(test_tracks, "01 - Test Track.ogg"))
|
||||
fs = track.add(os.path.join(test_tracks, "01 - Test Track.ogg"))
|
||||
self.assertEqual(len(track.track_list), 0)
|
||||
t = fs.result()
|
||||
self.assertIsNotNone(t)
|
||||
self.assertEqual(len(track.tracklist), 1)
|
||||
self.assertIn(t, track.tracklist)
|
||||
self.assertEqual(len(track.track_list), 1)
|
||||
self.assertIn(t, track.track_list)
|
||||
|
||||
self.assertIsNone(track.add(os.path.join(test_tracks, "01 - Test Track.ogg")))
|
||||
self.assertEqual(len(track.tracklist), 1)
|
||||
self.assertIsNone(track.add("99 - No Such Track.ogg"))
|
||||
self.assertEqual(len(track.tracklist), 1)
|
||||
self.assertIsNone(track.add(os.path.join(test_tracks, "01 - Test Track.ogg")).result())
|
||||
self.assertEqual(len(track.track_list), 1)
|
||||
self.assertIsNone(track.add("99 - No Such Track.ogg").result())
|
||||
self.assertEqual(len(track.track_list), 1)
|
||||
|
||||
u = track.add(os.path.join(test_tracks, "02 - Test {Disc 2}.ogg"))
|
||||
fs = track.add(os.path.join(test_tracks, "02 - Test {Disc 2}.ogg"))
|
||||
u = fs.result()
|
||||
self.assertIsNotNone(u)
|
||||
self.assertEqual(len(track.tracklist), 2)
|
||||
self.assertIn(u, track.tracklist)
|
||||
self.assertEqual(len(track.track_list), 2)
|
||||
self.assertIn(u, track.track_list)
|
||||
|
||||
def test_parallel_add(self):
|
||||
track.tracklist.clear()
|
||||
count = 0
|
||||
tracks = [ ]
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as pool:
|
||||
for dirname, subdirs, files in os.walk(test_library):
|
||||
for f in files:
|
||||
tracks.append(pool.submit(track.add, os.path.join(dirname, f)))
|
||||
count += 1
|
||||
self.assertEqual(len(track.tracklist), count)
|
||||
self.assertEqual(len(tracks), count)
|
||||
for t in tracks:
|
||||
self.assertIsNotNone(t)
|
||||
|
||||
if __name__ == '__main--':
|
||||
unittest.main()
|
||||
count = 0
|
||||
futures = [ ]
|
||||
done = [ ]
|
||||
none = [ ]
|
||||
for dirname, subdirs, files in os.walk(test_library):
|
||||
for f in files:
|
||||
futures.append(track.add(os.path.join(dirname, f)))
|
||||
futures.append(track.add(os.path.join(dirname, f)))
|
||||
count += 1
|
||||
self.assertLess(len(track.track_list), count)
|
||||
for fs in concurrent.futures.as_completed(futures):
|
||||
if fs.result() is not None:
|
||||
done.append(fs.result())
|
||||
else:
|
||||
none.append(fs.result())
|
||||
self.assertEqual(len(done), count)
|
||||
self.assertEqual(len(none), count)
|
||||
self.assertEqual(len(track.track_list), count)
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
# Copyright 2019 (c) Anna Schumaker.
|
||||
import album
|
||||
import concurrent.futures
|
||||
import mutagen
|
||||
import os
|
||||
import re
|
||||
|
||||
discno_map = { "one" : "1", "two" : "2", "three" : "3", "four" : "4", "five" : "5" }
|
||||
tracklist = [ ]
|
||||
track_list = [ ]
|
||||
track_pool = concurrent.futures.ThreadPoolExecutor(max_workers = 1)
|
||||
|
||||
class Track:
|
||||
def __init__(self, path):
|
||||
|
@ -26,11 +28,14 @@ class Track:
|
|||
self.discnumber = int(discno_map.get(match.group(), match.group()))
|
||||
|
||||
|
||||
def add(path):
|
||||
def __add(path):
|
||||
try:
|
||||
if not any(t.path == path for t in tracklist):
|
||||
if not any(t.path == path for t in track_list):
|
||||
track = Track(path)
|
||||
tracklist.append(track)
|
||||
track_list.append(track)
|
||||
return track
|
||||
except mutagen.MutagenError:
|
||||
return None
|
||||
|
||||
def add(path):
|
||||
return track_pool.submit(__add, path)
|
||||
|
|
Loading…
Reference in New Issue