Merge pull request #720 from sampsyo/import-refactor

Import refactor
This commit is contained in:
Adrian Sampson 2014-04-27 09:51:10 -07:00
commit 9f5f70aeab
12 changed files with 616 additions and 646 deletions

File diff suppressed because it is too large Load diff

View file

@ -740,7 +740,7 @@ class TerminalImportSession(importer.ImportSession):
pass
elif sel == 'r':
# Remove old.
task.remove_duplicates = True
task.should_remove_duplicates = True
else:
assert False

View file

@ -137,6 +137,51 @@ def multiple(messages):
return MultiMessage(messages)
def stage(func):
"""Decorate a function to become a simple stage.
>>> @stage
... def add(n, i):
... return i + n
>>> pipe = Pipeline([
... iter([1, 2, 3]),
... add(2),
... ])
>>> list(pipe.pull())
[3, 4, 5]
"""
def coro(*args):
task = None
while True:
task = yield task
task = func(*(args + (task,)))
return coro
def mutator_stage(func):
"""Decorate a function that manipulates items in a coroutine to
become a simple stage.
>>> @mutator_stage
... def setkey(key, item):
... item[key] = True
>>> pipe = Pipeline([
... iter([{'x': False}, {'a': False}]),
... setkey('x'),
... ])
>>> list(pipe.pull())
[{'x': True}, {'a': False, 'x': True}]
"""
def coro(*args):
task = None
while True:
task = yield task
func(*(args + (task,)))
return coro
def _allmsgs(obj):
"""Returns a list of all the messages encapsulated in obj. If obj
is a MultiMessage, returns its enclosed messages. If obj is BUBBLE,

View file

@ -278,8 +278,7 @@ class FetchArtPlugin(BeetsPlugin):
# For any other choices (e.g., TRACKS), do nothing.
return
album = session.lib.get_album(task.album_id)
path = art_for_album(album, task.paths, self.maxwidth, local)
path = art_for_album(task.album, task.paths, self.maxwidth, local)
if path:
self.art_paths[task] = path
@ -290,7 +289,7 @@ class FetchArtPlugin(BeetsPlugin):
if task in self.art_paths:
path = self.art_paths.pop(task)
album = session.lib.get_album(task.album_id)
album = task.album
src_removed = (config['import']['delete'].get(bool) or
config['import']['move'].get(bool))
album.set_art(path, not src_removed)

View file

@ -382,7 +382,7 @@ class LastGenrePlugin(plugins.BeetsPlugin):
def imported(self, session, task):
"""Event hook called when an import task finishes."""
if task.is_album:
album = session.lib.get_album(task.album_id)
album = task.album
album.genre, src = self._get_genre(album)
log.debug(u'added last.fm album genre ({0}): {1}'.format(
src, album.genre

View file

@ -601,8 +601,7 @@ class ReplayGainPlugin(BeetsPlugin):
return
if task.is_album:
album = session.lib.get_album(task.album_id)
self.handle_album(album, False)
self.handle_album(task.album, False)
else:
self.handle_track(task.item, False)

View file

@ -349,7 +349,7 @@ class TestImportSession(importer.ImportSession):
if res == self.Resolution.SKIP:
task.set_choice(importer.action.SKIP)
elif res == self.Resolution.REMOVE:
task.remove_duplicates = True
task.should_remove_duplicates = True
def generate_album_info(album_id, track_ids):

View file

@ -222,7 +222,7 @@ class ArtImporterTest(_common.TestCase):
# Import task for the coroutine.
self.task = importer.ImportTask(None, None, [self.i])
self.task.is_album = True
self.task.album_id = self.album.id
self.task.album = self.album
info = AlbumInfo(
album = 'some album',
album_id = 'albumid',

View file

@ -15,10 +15,7 @@ class IHatePluginTest(unittest.TestCase):
genre='TestGenre',
album=u'TestAlbum',
artist=u'TestArtist')
task = importer.ImportTask()
task.items = [test_item]
task.item = test_item
task.is_album = False
task = importer.SingletonImportTask(test_item)
# Empty query should let it pass.
self.assertFalse(IHatePlugin.do_i_hate_this(task, match_pattern))

View file

@ -867,12 +867,9 @@ class InferAlbumDataTest(_common.TestCase):
items=self.items)
self.task.set_null_candidates()
def _infer(self):
importer._infer_album_fields(self.task)
def test_asis_homogenous_single_artist(self):
self.task.set_choice(importer.action.ASIS)
self._infer()
self.task.infer_album_fields()
self.assertFalse(self.items[0].comp)
self.assertEqual(self.items[0].albumartist, self.items[2].artist)
@ -881,7 +878,7 @@ class InferAlbumDataTest(_common.TestCase):
self.items[1].artist = 'some other artist'
self.task.set_choice(importer.action.ASIS)
self._infer()
self.task.infer_album_fields()
self.assertTrue(self.items[0].comp)
self.assertEqual(self.items[0].albumartist, 'Various Artists')
@ -891,7 +888,7 @@ class InferAlbumDataTest(_common.TestCase):
self.items[1].artist = 'some other artist'
self.task.set_choice(importer.action.ASIS)
self._infer()
self.task.infer_album_fields()
for item in self.items:
self.assertTrue(item.comp)
@ -901,7 +898,7 @@ class InferAlbumDataTest(_common.TestCase):
self.items[0].artist = 'another artist'
self.task.set_choice(importer.action.ASIS)
self._infer()
self.task.infer_album_fields()
self.assertFalse(self.items[0].comp)
self.assertEqual(self.items[0].albumartist, self.items[2].artist)
@ -914,7 +911,7 @@ class InferAlbumDataTest(_common.TestCase):
item.mb_albumartistid = 'some album artist id'
self.task.set_choice(importer.action.ASIS)
self._infer()
self.task.infer_album_fields()
self.assertEqual(self.items[0].albumartist,
'some album artist')
@ -924,7 +921,7 @@ class InferAlbumDataTest(_common.TestCase):
def test_apply_gets_artist_and_id(self):
self.task.set_choice(AlbumMatch(0, None, {}, set(), set())) # APPLY
self._infer()
self.task.infer_album_fields()
self.assertEqual(self.items[0].albumartist, self.items[0].artist)
self.assertEqual(self.items[0].mb_albumartistid,
@ -936,7 +933,7 @@ class InferAlbumDataTest(_common.TestCase):
item.mb_albumartistid = 'some album artist id'
self.task.set_choice(AlbumMatch(0, None, {}, set(), set())) # APPLY
self._infer()
self.task.infer_album_fields()
self.assertEqual(self.items[0].albumartist,
'some album artist')
@ -947,16 +944,9 @@ class InferAlbumDataTest(_common.TestCase):
self.items = [self.items[0]]
self.task.items = self.items
self.task.set_choice(importer.action.ASIS)
self._infer()
self.task.infer_album_fields()
self.assertFalse(self.items[0].comp)
def test_first_item_null_apply(self):
self.items[0] = None
self.task.set_choice(AlbumMatch(0, None, {}, set(), set())) # APPLY
self._infer()
self.assertFalse(self.items[1].comp)
self.assertEqual(self.items[1].albumartist, self.items[2].artist)
class ImportDuplicateAlbumTest(unittest.TestCase, TestHelper):

View file

@ -208,6 +208,32 @@ class MultiMessageTest(unittest.TestCase):
self.assertEqual(list(pl.pull()), [0, 0, 1, -1, 2, -2, 3, -3, 4, -4])
class StageDecoratorTest(unittest.TestCase):
def test_stage_decorator(self):
@pipeline.stage
def add(n, i):
return i + n
pl = pipeline.Pipeline([
iter([1, 2, 3]),
add(2)
])
self.assertEqual(list(pl.pull()), [3, 4, 5])
def test_mutator_stage_decorator(self):
@pipeline.mutator_stage
def setkey(key, item):
item[key] = True
pl = pipeline.Pipeline([
iter([{'x': False}, {'a': False}]),
setkey('x'),
])
self.assertEqual(list(pl.pull()),
[{'x': True}, {'a': False, 'x': True}])
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)

View file

@ -473,32 +473,6 @@ class PrintTest(_common.TestCase):
del os.environ['LC_CTYPE']
class AutotagTest(_common.TestCase):
def setUp(self):
super(AutotagTest, self).setUp()
self.io.install()
def _no_candidates_test(self, result):
task = importer.ImportTask(
'toppath',
'path',
[_common.item()],
)
task.set_candidates('artist', 'album', [], autotag.Recommendation.none)
session = _common.import_session(cli=True)
res = session.choose_match(task)
self.assertEqual(res, result)
self.assertTrue('No match' in self.io.getoutput())
def test_choose_match_with_no_candidates_skip(self):
self.io.addinput('s')
self._no_candidates_test(importer.action.SKIP)
def test_choose_match_with_no_candidates_asis(self):
self.io.addinput('u')
self._no_candidates_test(importer.action.ASIS)
class ImportTest(_common.TestCase):
def test_quiet_timid_disallowed(self):
config['import']['quiet'] = True