diff --git a/beets/importer.py b/beets/importer.py index 3411c4b72..bbc87d952 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -685,7 +685,7 @@ def user_query(session): session.log_choice(task, True) recent.add(ident) -def show_progress(): +def show_progress(session): """This stage replaces the initial_lookup and user_query stages when the importer is run without autotagging. It displays the album name and artist as the files are added. diff --git a/test/_common.py b/test/_common.py index dbe09422c..23e72d8f0 100644 --- a/test/_common.py +++ b/test/_common.py @@ -30,6 +30,7 @@ except ImportError: sys.path.insert(0, '..') import beets.library from beets import importer +from beets.ui import commands import beets # Suppress logging output. @@ -75,8 +76,9 @@ def item(): }) # Dummy import session. -def import_session(lib, logfile=None, paths=[], query=[]): - return importer.ImportSession(lib, logfile, paths, query) +def import_session(lib=None, logfile=None, paths=[], query=[], cli=False): + cls = commands.TerminalImportSession if cli else importer.ImportSession + return cls(lib, logfile, paths, query) # Temporary config modifications. @contextlib.contextmanager diff --git a/test/test_autotag.py b/test/test_autotag.py index be331370f..6ba95fbbf 100644 --- a/test/test_autotag.py +++ b/test/test_autotag.py @@ -26,6 +26,7 @@ from beets.autotag import match from beets.library import Item from beets.util import plurality from beets.autotag import AlbumInfo, TrackInfo +from beets import config class PluralityTest(unittest.TestCase): def test_plurality_consensus(self): @@ -499,7 +500,9 @@ class ApplyTestUtil(object): mapping = {} for i, t in zip(self.items, info.tracks): mapping[i] = t - autotag.apply_metadata(info, mapping, per_disc_numbering) + with _common.temp_config(): + config['per_disc_numbering'] = per_disc_numbering + autotag.apply_metadata(info, mapping) class ApplyTest(unittest.TestCase, ApplyTestUtil): def setUp(self): diff --git a/test/test_importer.py b/test/test_importer.py index 45ddc2ac4..32353915f 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -24,6 +24,7 @@ from beets import library from beets import importer from beets import mediafile from beets.autotag import AlbumInfo, TrackInfo, AlbumMatch, TrackMatch +from beets import config TEST_TITLES = ('The Opener', 'The Second Track', 'The Last Track') class NonAutotaggedImportTest(unittest.TestCase): @@ -83,31 +84,17 @@ class NonAutotaggedImportTest(unittest.TestCase): })) # Run the UI "beet import" command! - importer.run_import( - lib=self.lib, - paths=[os.path.dirname(paths[0])], - copy=not move, - move=move, - write=True, - autot=False, - logfile=None, - threaded=threaded, - color=False, - delete=delete, - quiet=True, - resume=False, - quiet_fallback='skip', - choose_match_func = None, - should_resume_func = None, - singletons = singletons, - choose_item_func = None, - timid = False, - query = None, - incremental = False, - ignore = [], - resolve_duplicate_func = None, - per_disc_numbering = False, - ) + with _common.temp_config(): + config['import']['delete'] = delete + config['import']['threaded'] = threaded + config['import']['singletons'] = singletons + config['import']['move'] = move + config['import']['autotag'] = False + session = importer.ImportSession(self.lib, + logfile=None, + paths=[os.path.dirname(paths[0])], + query=None) + session.run() return paths @@ -168,7 +155,7 @@ class NonAutotaggedImportTest(unittest.TestCase): # Utilities for invoking the apply_choices, manipulate_files, and finalize # coroutines. -def _call_stages(config, items, choice_or_info, +def _call_stages(session, items, choice_or_info, stages=[importer.apply_choices, importer.manipulate_files, importer.finalize], @@ -187,7 +174,7 @@ def _call_stages(config, items, choice_or_info, # Call the coroutines. for stage in stages: - coro = stage(config) + coro = stage(session) coro.next() coro.send(task) @@ -204,6 +191,7 @@ class ImportApplyTest(unittest.TestCase, _common.ExtraAsserts): ('singleton:true', 'three'), ('comp:true', 'two'), ] + self.session = _common.import_session(self.lib) self.srcdir = os.path.join(_common.RSRC, 'testsrcdir') os.mkdir(self.srcdir) @@ -233,36 +221,36 @@ class ImportApplyTest(unittest.TestCase, _common.ExtraAsserts): os.unlink(self.libpath) def test_finalize_no_delete(self): - config = _common.iconfig(self.lib, delete=False) - _call_stages(config, [self.i], self.info) + with _common.temp_config(): + config['import']['delete'] = False + _call_stages(self.session, [self.i], self.info) self.assertExists(self.srcpath) def test_finalize_with_delete(self): - config = _common.iconfig(self.lib, delete=True) - _call_stages(config, [self.i], self.info) + with _common.temp_config(): + config['import']['delete'] = True + _call_stages(self.session, [self.i], self.info) self.assertNotExists(self.srcpath) def test_finalize_with_delete_prunes_directory_empty(self): - config = _common.iconfig(self.lib, delete=True) - _call_stages(config, [self.i], self.info, - toppath=self.srcdir) + with _common.temp_config(): + config['import']['delete'] = True + _call_stages(self.session, [self.i], self.info, + toppath=self.srcdir) self.assertNotExists(os.path.dirname(self.srcpath)) def test_apply_asis_uses_album_path(self): - config = _common.iconfig(self.lib) - _call_stages(config, [self.i], importer.action.ASIS) + _call_stages(self.session, [self.i], importer.action.ASIS) self.assertExists(os.path.join(self.libdir, 'one.mp3')) def test_apply_match_uses_album_path(self): - config = _common.iconfig(self.lib) - _call_stages(config, [self.i], self.info) + _call_stages(self.session, [self.i], self.info) self.assertExists(os.path.join(self.libdir, 'one.mp3')) def test_apply_tracks_uses_singleton_path(self): - config = _common.iconfig(self.lib) - apply_coro = importer.apply_choices(config) + apply_coro = importer.apply_choices(self.session) apply_coro.next() - manip_coro = importer.manipulate_files(config) + manip_coro = importer.manipulate_files(self.session) manip_coro.next() task = importer.ImportTask.item_task(self.i) @@ -275,14 +263,13 @@ class ImportApplyTest(unittest.TestCase, _common.ExtraAsserts): ) def test_apply_sentinel(self): - coro = importer.apply_choices(_common.iconfig(self.lib)) + coro = importer.apply_choices(self.session) coro.next() coro.send(importer.ImportTask.done_sentinel('toppath')) # Just test no exception for now. def test_apply_populates_old_paths(self): - config = _common.iconfig(self.lib) - task = _call_stages(config, [self.i], self.info) + task = _call_stages(self.session, [self.i], self.info) self.assertEqual(task.old_paths, [self.srcpath]) def test_reimport_inside_file_moves_and_does_not_add_to_old_paths(self): @@ -300,8 +287,7 @@ class ImportApplyTest(unittest.TestCase, _common.ExtraAsserts): self.i.comp = False # Then, re-import the same file. - config =_common.iconfig(self.lib) - task = _call_stages(config, [self.i], self.info) + task = _call_stages(self.session, [self.i], self.info) # Old file should be gone. self.assertNotExists(internal_srcpath) @@ -321,8 +307,7 @@ class ImportApplyTest(unittest.TestCase, _common.ExtraAsserts): self.lib._connection().commit() # Then, re-import the same file. - config = _common.iconfig(self.lib) - task = _call_stages(config, [self.i], self.info) + task = _call_stages(self.session, [self.i], self.info) # Old file should still exist. self.assertExists(self.srcpath) @@ -333,31 +318,34 @@ class ImportApplyTest(unittest.TestCase, _common.ExtraAsserts): self.assertEqual(task.old_paths, [self.srcpath]) def test_apply_with_move(self): - config = _common.iconfig(self.lib, move=True) - _call_stages(config, [self.i], self.info) + with _common.temp_config(): + config['import']['move'] = True + _call_stages(self.session, [self.i], self.info) self.assertExists(list(self.lib.items())[0].path) self.assertNotExists(self.srcpath) def test_apply_with_move_prunes_empty_directory(self): - config = _common.iconfig(self.lib, move=True) - _call_stages(config, [self.i], self.info, toppath=self.srcdir) + with _common.temp_config(): + config['import']['move'] = True + _call_stages(self.session, [self.i], self.info, toppath=self.srcdir) self.assertNotExists(os.path.dirname(self.srcpath)) def test_manipulate_files_with_null_move(self): """It should be possible to "move" a file even when the file is already at the destination. """ - config = _common.iconfig(self.lib, move=True) self.lib.move(self.i) # Already at destination. - _call_stages(config, [self.i], self.info, toppath=self.srcdir, - stages=[importer.manipulate_files]) + with _common.temp_config(): + config['import']['move'] = True + _call_stages(self.session, [self.i], self.info, toppath=self.srcdir, + stages=[importer.manipulate_files]) self.assertExists(self.i.path) class AsIsApplyTest(unittest.TestCase): def setUp(self): self.dbpath = os.path.join(_common.RSRC, 'templib.blb') self.lib = library.Library(self.dbpath) - self.config = _common.iconfig(self.lib, write=False, copy=False) + self.session = _common.import_session(self.lib) # Make an "album" that has a homogenous artist. (Modified by # individual tests.) @@ -376,7 +364,7 @@ class AsIsApplyTest(unittest.TestCase): def _apply_result(self): """Run the "apply" coroutines and get the resulting Album.""" - _call_stages(self.config, self.items, importer.action.ASIS, + _call_stages(self.session, self.items, importer.action.ASIS, stages=[importer.apply_choices]) return self.lib.albums()[0] @@ -408,7 +396,12 @@ class ApplyExistingItemsTest(unittest.TestCase, _common.ExtraAsserts): self.lib.path_formats = [ ('default', '$artist/$title'), ] - self.config = _common.iconfig(self.lib, write=False, copy=False) + self.session = _common.import_session(self.lib) + + self.config_ctx = _common.temp_config() + self.config_ctx.__enter__() + config['import']['write'] = False + config['import']['copy'] = False self.srcpath = os.path.join(self.libdir, 'srcfile.mp3') shutil.copy(os.path.join(_common.RSRC, 'full.mp3'), self.srcpath) @@ -416,12 +409,13 @@ class ApplyExistingItemsTest(unittest.TestCase, _common.ExtraAsserts): self.i.comp = False def tearDown(self): + self.config_ctx.__exit__(None, None, None) os.remove(self.dbpath) shutil.rmtree(self.libdir) def _apply_asis(self, items, album=True): """Run the "apply" coroutine.""" - _call_stages(self.config, items, importer.action.ASIS, album=album, + _call_stages(self.session, items, importer.action.ASIS, album=album, stages=[importer.apply_choices, importer.manipulate_files]) @@ -458,16 +452,17 @@ class ApplyExistingItemsTest(unittest.TestCase, _common.ExtraAsserts): def test_apply_existing_item_new_metadata_does_not_duplicate(self): # We want to copy the item to a new location. - self.config.copy = True + with _common.temp_config(): + config['import']['copy'] = True - # Import with existing metadata. - self._apply_asis([self.i]) + # Import with existing metadata. + self._apply_asis([self.i]) - # Import again with new metadata. - item = self.lib.items().next() - new_item = library.Item.from_path(item.path) - new_item.title = 'differentTitle' - self._apply_asis([new_item]) + # Import again with new metadata. + item = self.lib.items().next() + new_item = library.Item.from_path(item.path) + new_item.title = 'differentTitle' + self._apply_asis([new_item]) # Should not be duplicated. self.assertEqual(len(list(self.lib.items())), 1) @@ -475,12 +470,14 @@ class ApplyExistingItemsTest(unittest.TestCase, _common.ExtraAsserts): def test_apply_existing_item_new_metadata_moves_files(self): # As above, import with old metadata and then reimport with new. - self.config.copy = True - self._apply_asis([self.i]) - item = self.lib.items().next() - new_item = library.Item.from_path(item.path) - new_item.title = 'differentTitle' - self._apply_asis([new_item]) + with _common.temp_config(): + config['import']['copy'] = True + + self._apply_asis([self.i]) + item = self.lib.items().next() + new_item = library.Item.from_path(item.path) + new_item.title = 'differentTitle' + self._apply_asis([new_item]) item = self.lib.items().next() self.assertTrue('differentTitle' in item.path) @@ -488,25 +485,29 @@ class ApplyExistingItemsTest(unittest.TestCase, _common.ExtraAsserts): def test_apply_existing_item_new_metadata_copy_disabled(self): # Import *without* copying to ensure that the path does *not* change. - self.config.copy = False - self._apply_asis([self.i]) - item = self.lib.items().next() - new_item = library.Item.from_path(item.path) - new_item.title = 'differentTitle' - self._apply_asis([new_item]) + with _common.temp_config(): + config['import']['copy'] = False + + self._apply_asis([self.i]) + item = self.lib.items().next() + new_item = library.Item.from_path(item.path) + new_item.title = 'differentTitle' + self._apply_asis([new_item]) item = self.lib.items().next() self.assertFalse('differentTitle' in item.path) self.assertExists(item.path) def test_apply_existing_item_new_metadata_removes_old_files(self): - self.config.copy = True - self._apply_asis([self.i]) - item = self.lib.items().next() - oldpath = item.path - new_item = library.Item.from_path(item.path) - new_item.title = 'differentTitle' - self._apply_asis([new_item]) + with _common.temp_config(): + config['import']['copy'] = True + + self._apply_asis([self.i]) + item = self.lib.items().next() + oldpath = item.path + new_item = library.Item.from_path(item.path) + new_item.title = 'differentTitle' + self._apply_asis([new_item]) item = self.lib.items().next() self.assertNotExists(oldpath) @@ -514,14 +515,16 @@ class ApplyExistingItemsTest(unittest.TestCase, _common.ExtraAsserts): def test_apply_existing_item_new_metadata_delete_enabled(self): # The "delete" flag should be ignored -- only the "copy" flag # controls whether files move. - self.config.copy = True - self.config.delete = True # ! - self._apply_asis([self.i]) - item = self.lib.items().next() - oldpath = item.path - new_item = library.Item.from_path(item.path) - new_item.title = 'differentTitle' - self._apply_asis([new_item]) + with _common.temp_config(): + config['import']['copy'] = True + config['import']['delete'] = True # ! + + self._apply_asis([self.i]) + item = self.lib.items().next() + oldpath = item.path + new_item = library.Item.from_path(item.path) + new_item.title = 'differentTitle' + self._apply_asis([new_item]) item = self.lib.items().next() self.assertNotExists(oldpath) @@ -530,12 +533,14 @@ class ApplyExistingItemsTest(unittest.TestCase, _common.ExtraAsserts): def test_apply_existing_item_preserves_file(self): # With copying enabled, import the item twice with same metadata. - self.config.copy = True - self._apply_asis([self.i]) - item = self.lib.items().next() - oldpath = item.path - new_item = library.Item.from_path(item.path) - self._apply_asis([new_item]) + with _common.temp_config(): + config['import']['copy'] = True + + self._apply_asis([self.i]) + item = self.lib.items().next() + oldpath = item.path + new_item = library.Item.from_path(item.path) + self._apply_asis([new_item]) self.assertEqual(len(list(self.lib.items())), 1) item = self.lib.items().next() @@ -543,12 +548,14 @@ class ApplyExistingItemsTest(unittest.TestCase, _common.ExtraAsserts): self.assertExists(oldpath) def test_apply_existing_item_preserves_file_delete_enabled(self): - self.config.copy = True - self.config.delete = True # ! - self._apply_asis([self.i]) - item = self.lib.items().next() - new_item = library.Item.from_path(item.path) - self._apply_asis([new_item]) + with _common.temp_config(): + config['import']['copy'] = True + config['import']['delete'] = True # ! + + self._apply_asis([self.i]) + item = self.lib.items().next() + new_item = library.Item.from_path(item.path) + self._apply_asis([new_item]) self.assertEqual(len(list(self.lib.items())), 1) item = self.lib.items().next() @@ -755,12 +762,14 @@ class DuplicateCheckTest(unittest.TestCase): class TagLogTest(unittest.TestCase): def test_tag_log_line(self): sio = StringIO.StringIO() - importer.tag_log(sio, 'status', 'path') + session = _common.import_session(logfile=sio) + session.tag_log('status', 'path') assert 'status path' in sio.getvalue() def test_tag_log_unicode(self): sio = StringIO.StringIO() - importer.tag_log(sio, 'status', 'caf\xc3\xa9') + session = _common.import_session(logfile=sio) + session.tag_log('status', 'caf\xc3\xa9') assert 'status caf' in sio.getvalue() def suite(): diff --git a/test/test_the.py b/test/test_the.py index 5ed30a858..d93a0b9fe 100644 --- a/test/test_the.py +++ b/test/test_the.py @@ -1,6 +1,8 @@ """Tests for the 'the' plugin""" from _common import unittest +import _common +from beets import config from beetsplug.the import ThePlugin, PATTERN_A, PATTERN_THE, FORMAT @@ -30,11 +32,13 @@ class ThePluginTest(unittest.TestCase): 'A Thing, An') self.assertEqual(ThePlugin().unthe('the An Arse', PATTERN_A), 'the An Arse') - ThePlugin().strip = True - self.assertEqual(ThePlugin().unthe('The Something', PATTERN_THE), - 'Something') - self.assertEqual(ThePlugin().unthe('An A', PATTERN_A), 'A') - ThePlugin().strip = False + + def test_unthe_with_strip(self): + with _common.temp_config(): + config['the']['strip'] = True + self.assertEqual(ThePlugin().unthe('The Something', PATTERN_THE), + 'Something') + self.assertEqual(ThePlugin().unthe('An A', PATTERN_A), 'A') def test_template_function_with_defaults(self): ThePlugin().patterns = [PATTERN_THE, PATTERN_A] @@ -43,15 +47,17 @@ class ThePluginTest(unittest.TestCase): self.assertEqual(ThePlugin().the_template_func('An A'), 'A, An') def test_custom_pattern(self): - ThePlugin().patterns = [ u'^test\s'] - ThePlugin().format = FORMAT - self.assertEqual(ThePlugin().the_template_func('test passed'), - 'passed, test') + with _common.temp_config(): + config['the']['patterns'] = [u'^test\s'] + config['the']['format'] = FORMAT + self.assertEqual(ThePlugin().the_template_func('test passed'), + 'passed, test') def test_custom_format(self): - ThePlugin().patterns = [PATTERN_THE, PATTERN_A] - ThePlugin().format = '{1} ({0})' - self.assertEqual(ThePlugin().the_template_func('The A'), 'The (A)') + with _common.temp_config(): + config['the']['patterns'] = [PATTERN_THE, PATTERN_A] + config['the']['format'] = u'{1} ({0})' + self.assertEqual(ThePlugin().the_template_func('The A'), 'The (A)') def suite(): diff --git a/test/test_ui.py b/test/test_ui.py index 6e14ef098..d4c1175bf 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -454,7 +454,8 @@ class AutotagTest(unittest.TestCase): [_common.item()], ) task.set_candidates('artist', 'album', [], autotag.RECOMMEND_NONE) - res = commands.choose_match(_common.import_session(None), task) + session = _common.import_session(cli=True) + res = session.choose_match(task) self.assertEqual(res, result) self.assertTrue('No match' in self.io.getoutput()) @@ -501,7 +502,7 @@ class ConfigTest(unittest.TestCase): ui._raw_main(args + ['test'], StringIO(config)) def test_paths_section_respected(self): - def func(lib, config, opts, args): + def func(lib, opts, args): key, template = lib.path_formats[0] self.assertEqual(key, 'x') self.assertEqual(template.original, 'y') @@ -510,7 +511,7 @@ class ConfigTest(unittest.TestCase): x=y"""), func) def test_default_paths_preserved(self): - def func(lib, config, opts, args): + def func(lib, opts, args): self.assertEqual(lib.path_formats[1:], ui.DEFAULT_PATH_FORMATS) self._run_main([], textwrap.dedent(""" @@ -522,7 +523,7 @@ class ConfigTest(unittest.TestCase): ui.main(['version']) def test_nonexistant_db(self): - def func(lib, config, opts, args): + def func(lib, opts, args): pass with self.assertRaises(ui.UserError): self._run_main([], textwrap.dedent(""" @@ -531,7 +532,7 @@ class ConfigTest(unittest.TestCase): """), func) def test_replacements_parsed(self): - def func(lib, config, opts, args): + def func(lib, opts, args): replacements = lib.replacements self.assertEqual(replacements, [(re.compile(ur'[xy]'), u'z')]) self._run_main([], textwrap.dedent(""" @@ -539,7 +540,7 @@ class ConfigTest(unittest.TestCase): replace=[xy] z"""), func) def test_replacements_parsed_unicode(self): - def func(lib, config, opts, args): + def func(lib, opts, args): replacements = lib.replacements self.assertEqual(replacements, [(re.compile(ur'\u2019'), u'z')]) self._run_main([], textwrap.dedent(u""" @@ -547,7 +548,7 @@ class ConfigTest(unittest.TestCase): replace=\u2019 z"""), func) def test_empty_replacements_produce_none(self): - def func(lib, config, opts, args): + def func(lib, opts, args): replacements = lib.replacements self.assertFalse(replacements) self._run_main([], textwrap.dedent(""" @@ -555,7 +556,7 @@ class ConfigTest(unittest.TestCase): """), func) def test_multiple_replacements_parsed(self): - def func(lib, config, opts, args): + def func(lib, opts, args): replacements = lib.replacements self.assertEqual(replacements, [ (re.compile(ur'[xy]'), u'z'),