def setUp(self): self.setup_beets() self.load_plugins('edit') # Create some mediafiles, and store them for comparison. self._create_import_dir(3) self.items_orig = [Item.from_path(f.path) for f in self.media_files] self.matcher = AutotagStub().install() self.matcher.matching = AutotagStub.GOOD self.config['import']['timid'] = True
def setUp(self): self.setup_plugin_loader() self.setup_beets() self._create_import_dir(3) self._setup_import_session() self.matcher = AutotagStub().install() # keep track of ui.input_option() calls self.input_options_patcher = patch('beets.ui.input_options', side_effect=ui.input_options) self.mock_input_options = self.input_options_patcher.start()
def setUp(self): preserve_plugin_listeners() self.setup_beets() self.load_plugins('importadded') self._create_import_dir(2) # Different mtimes on the files to be imported in order to test the # plugin modify_mtimes((mfile.path for mfile in self.media_files)) self.min_mtime = min( os.path.getmtime(mfile.path) for mfile in self.media_files) self.matcher = AutotagStub().install() self.matcher.macthin = AutotagStub.GOOD self._setup_import_session() self.importer.add_choice(importer.action.APPLY)
class MBSubmitPluginTest(TerminalImportSessionSetup, unittest.TestCase, ImportHelper, TestHelper): def setUp(self): self.setup_beets() self.load_plugins('mbsubmit') self._create_import_dir(2) self._setup_import_session() self.matcher = AutotagStub().install() def tearDown(self): self.unload_plugins() self.teardown_beets() self.matcher.restore() def test_print_tracks_output(self): """Test the output of the "print tracks" choice.""" self.matcher.matching = AutotagStub.BAD with capture_stdout() as output: with control_stdin('\n'.join(['p', 's'])): # Print tracks; Skip self.importer.run() # Manually build the string for comparing the output. tracklist = ('Print tracks? ' '01. Tag Title 1 - Tag Artist (0:01)\n' '02. Tag Title 2 - Tag Artist (0:01)') self.assertIn(tracklist, output.getvalue()) def test_print_tracks_output_as_tracks(self): """Test the output of the "print tracks" choice, as singletons.""" self.matcher.matching = AutotagStub.BAD with capture_stdout() as output: with control_stdin('\n'.join(['t', 's', 'p', 's'])): # as Tracks; Skip; Print tracks; Skip self.importer.run() # Manually build the string for comparing the output. tracklist = ('Print tracks? ' '02. Tag Title 2 - Tag Artist (0:01)') self.assertIn(tracklist, output.getvalue())
class MBSubmitPluginTest(TerminalImportSessionSetup, unittest.TestCase, ImportHelper, TestHelper): def setUp(self): self.setup_beets() self.load_plugins('mbsubmit') self._create_import_dir(2) self._setup_import_session() self.matcher = AutotagStub().install() def tearDown(self): self.unload_plugins() self.teardown_beets() self.matcher.restore() def test_print_tracks_output(self): """Test the output of the "print tracks" choice.""" self.matcher.matching = AutotagStub.BAD with capture_stdout() as output: with control_stdin('\n'.join(['p', 's'])): # Print tracks; Skip self.importer.run() # Manually build the string for comparing the output. tracklist = (u'Print tracks? ' u'01. Tag Title 1 - Tag Artist (0:01)\n' u'02. Tag Title 2 - Tag Artist (0:01)') self.assertIn(tracklist, output.getvalue()) def test_print_tracks_output_as_tracks(self): """Test the output of the "print tracks" choice, as singletons.""" self.matcher.matching = AutotagStub.BAD with capture_stdout() as output: with control_stdin('\n'.join(['t', 's', 'p', 's'])): # as Tracks; Skip; Print tracks; Skip self.importer.run() # Manually build the string for comparing the output. tracklist = (u'Print tracks? ' u'02. Tag Title 2 - Tag Artist (0:01)') self.assertIn(tracklist, output.getvalue())
def setUp(self): preserve_plugin_listeners() self.setup_beets() self.load_plugins("importadded") self._create_import_dir(2) # Different mtimes on the files to be imported in order to test the # plugin modify_mtimes((mfile.path for mfile in self.media_files)) self.min_mtime = min(os.path.getmtime(mfile.path) for mfile in self.media_files) self.matcher = AutotagStub().install() self.matcher.macthin = AutotagStub.GOOD self._setup_import_session() self.importer.add_choice(importer.action.APPLY)
class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, ImportHelper, TestHelper): def setUp(self): self.setup_plugin_loader() self.setup_beets() self._create_import_dir(3) self._setup_import_session() self.matcher = AutotagStub().install() # keep track of ui.input_option() calls self.input_options_patcher = patch('beets.ui.input_options', side_effect=ui.input_options) self.mock_input_options = self.input_options_patcher.start() def tearDown(self): self.input_options_patcher.stop() self.teardown_plugin_loader() self.teardown_beets() self.matcher.restore() def test_plugin_choices_in_ui_input_options_album(self): """Test the presence of plugin choices on the prompt (album).""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ui.commands.PromptChoice('f', u'Foo', None), ui.commands.PromptChoice('r', u'baR', None)] self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', u'enter Id', u'aBort') + (u'Foo', u'baR') self.importer.add_choice(action.SKIP) self.importer.run() self.mock_input_options.assert_called_once_with(opts, default='a', require=ANY) def test_plugin_choices_in_ui_input_options_singleton(self): """Test the presence of plugin choices on the prompt (singleton).""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ui.commands.PromptChoice('f', u'Foo', None), ui.commands.PromptChoice('r', u'baR', None)] self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'Enter search', u'enter Id', u'aBort') + (u'Foo', u'baR') config['import']['singletons'] = True self.importer.add_choice(action.SKIP) self.importer.run() self.mock_input_options.assert_called_with(opts, default='a', require=ANY) def test_choices_conflicts(self): """Test the short letter conflict solving.""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ui.commands.PromptChoice('a', u'A foo', None), # dupe ui.commands.PromptChoice('z', u'baZ', None), # ok ui.commands.PromptChoice('z', u'Zupe', None), # dupe ui.commands.PromptChoice('z', u'Zoo', None)] # dupe self.register_plugin(DummyPlugin) # Default options + not dupe extra choices by the plugin ('baZ') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', u'enter Id', u'aBort') + (u'baZ',) self.importer.add_choice(action.SKIP) self.importer.run() self.mock_input_options.assert_called_once_with(opts, default='a', require=ANY) def test_plugin_callback(self): """Test that plugin callbacks are being called upon user choice.""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ui.commands.PromptChoice('f', u'Foo', self.foo)] def foo(self, session, task): pass self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', u'enter Id', u'aBort') + (u'Foo',) # DummyPlugin.foo() should be called once with patch.object(DummyPlugin, 'foo', autospec=True) as mock_foo: with helper.control_stdin('\n'.join(['f', 's'])): self.importer.run() self.assertEqual(mock_foo.call_count, 1) # input_options should be called twice, as foo() returns None self.assertEqual(self.mock_input_options.call_count, 2) self.mock_input_options.assert_called_with(opts, default='a', require=ANY) def test_plugin_callback_return(self): """Test that plugin callbacks that return a value exit the loop.""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ui.commands.PromptChoice('f', u'Foo', self.foo)] def foo(self, session, task): return action.SKIP self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', u'enter Id', u'aBort') + (u'Foo',) # DummyPlugin.foo() should be called once with helper.control_stdin('f\n'): self.importer.run() # input_options should be called once, as foo() returns SKIP self.mock_input_options.assert_called_once_with(opts, default='a', require=ANY)
class ImportAddedTest(unittest.TestCase, ImportHelper): # The minimum mtime of the files to be imported min_mtime = None def setUp(self): preserve_plugin_listeners() self.setup_beets() self.load_plugins('importadded') self._create_import_dir(2) # Different mtimes on the files to be imported in order to test the # plugin modify_mtimes((mfile.path for mfile in self.media_files)) self.min_mtime = min( os.path.getmtime(mfile.path) for mfile in self.media_files) self.matcher = AutotagStub().install() self.matcher.macthin = AutotagStub.GOOD self._setup_import_session() self.importer.add_choice(importer.action.APPLY) def tearDown(self): self.unload_plugins() self.teardown_beets() self.matcher.restore() def find_media_file(self, item): """Find the pre-import MediaFile for an Item""" for m in self.media_files: if m.title.replace('Tag', 'Applied') == item.title: return m raise AssertionError(u"No MediaFile found for Item " + util.displayable_path(item.path)) def assertEqualTimes(self, first, second, msg=None): # noqa """For comparing file modification times at a sufficient precision""" self.assertAlmostEqual(first, second, places=4, msg=msg) def assertAlbumImport(self): # noqa self.importer.run() album = self.lib.albums().get() self.assertEqual(album.added, self.min_mtime) for item in album.items(): self.assertEqual(item.added, self.min_mtime) def test_import_album_with_added_dates(self): self.assertAlbumImport() def test_import_album_inplace_with_added_dates(self): self.config['import']['copy'] = False self.config['import']['move'] = False self.config['import']['link'] = False self.assertAlbumImport() def test_import_album_with_preserved_mtimes(self): self.config['importadded']['preserve_mtimes'] = True self.importer.run() album = self.lib.albums().get() self.assertEqual(album.added, self.min_mtime) for item in album.items(): self.assertEqualTimes(item.added, self.min_mtime) mediafile_mtime = os.path.getmtime(self.find_media_file(item).path) self.assertEqualTimes(item.mtime, mediafile_mtime) self.assertEqualTimes(os.path.getmtime(item.path), mediafile_mtime) def test_reimported_album_skipped(self): # Import and record the original added dates self.importer.run() album = self.lib.albums().get() album_added_before = album.added items_added_before = dict( (item.path, item.added) for item in album.items()) # Newer Item path mtimes as if Beets had modified them modify_mtimes(items_added_before.keys(), offset=10000) # Reimport self._setup_import_session(import_dir=album.path) self.importer.run() # Verify the reimported items album = self.lib.albums().get() self.assertEqualTimes(album.added, album_added_before) items_added_after = dict( (item.path, item.added) for item in album.items()) for item_path, added_after in items_added_after.iteritems(): self.assertEqualTimes( items_added_before[item_path], added_after, u"reimport modified Item.added for " + item_path) def test_import_singletons_with_added_dates(self): self.config['import']['singletons'] = True self.importer.run() for item in self.lib.items(): mfile = self.find_media_file(item) self.assertEqualTimes(item.added, os.path.getmtime(mfile.path)) def test_import_singletons_with_preserved_mtimes(self): self.config['import']['singletons'] = True self.config['importadded']['preserve_mtimes'] = True self.importer.run() for item in self.lib.items(): mediafile_mtime = os.path.getmtime(self.find_media_file(item).path) self.assertEqualTimes(item.added, mediafile_mtime) self.assertEqualTimes(item.mtime, mediafile_mtime) self.assertEqualTimes(os.path.getmtime(item.path), mediafile_mtime) def test_reimported_singletons_skipped(self): self.config['import']['singletons'] = True # Import and record the original added dates self.importer.run() items_added_before = dict( (item.path, item.added) for item in self.lib.items()) # Newer Item path mtimes as if Beets had modified them modify_mtimes(items_added_before.keys(), offset=10000) # Reimport import_dir = os.path.dirname(items_added_before.keys()[0]) self._setup_import_session(import_dir=import_dir, singletons=True) self.importer.run() # Verify the reimported items items_added_after = dict( (item.path, item.added) for item in self.lib.items()) for item_path, added_after in items_added_after.iteritems(): self.assertEqualTimes( items_added_before[item_path], added_after, u"reimport modified Item.added for " + item_path)
class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, ImportHelper, TestHelper): def setUp(self): self.setup_plugin_loader() self.setup_beets() self._create_import_dir(3) self._setup_import_session() self.matcher = AutotagStub().install() # keep track of ui.input_option() calls self.input_options_patcher = patch('beets.ui.input_options', side_effect=ui.input_options) self.mock_input_options = self.input_options_patcher.start() def tearDown(self): self.input_options_patcher.stop() self.teardown_plugin_loader() self.teardown_beets() self.matcher.restore() def test_plugin_choices_in_ui_input_options_album(self): """Test the presence of plugin choices on the prompt (album).""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ ui.commands.PromptChoice('f', 'Foo', None), ui.commands.PromptChoice('r', 'baR', None) ] self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', u'enter Id', u'aBort') + ('Foo', 'baR') self.importer.add_choice(action.SKIP) self.importer.run() self.mock_input_options.assert_called_once_with(opts, default='a', require=ANY) def test_plugin_choices_in_ui_input_options_singleton(self): """Test the presence of plugin choices on the prompt (singleton).""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ ui.commands.PromptChoice('f', 'Foo', None), ui.commands.PromptChoice('r', 'baR', None) ] self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'Enter search', u'enter Id', u'aBort') + ('Foo', 'baR') config['import']['singletons'] = True self.importer.add_choice(action.SKIP) self.importer.run() self.mock_input_options.assert_called_with(opts, default='a', require=ANY) def test_choices_conflicts(self): """Test the short letter conflict solving.""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ ui.commands.PromptChoice('a', 'A foo', None), # dupe ui.commands.PromptChoice('z', 'baZ', None), # ok ui.commands.PromptChoice('z', 'Zupe', None), # dupe ui.commands.PromptChoice('z', 'Zoo', None) ] # dupe self.register_plugin(DummyPlugin) # Default options + not dupe extra choices by the plugin ('baZ') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', u'enter Id', u'aBort') + ('baZ', ) self.importer.add_choice(action.SKIP) self.importer.run() self.mock_input_options.assert_called_once_with(opts, default='a', require=ANY) def test_plugin_callback(self): """Test that plugin callbacks are being called upon user choice.""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ui.commands.PromptChoice('f', 'Foo', self.foo)] def foo(self, session, task): pass self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', u'enter Id', u'aBort') + ('Foo', ) # DummyPlugin.foo() should be called once with patch.object(DummyPlugin, 'foo', autospec=True) as mock_foo: with helper.control_stdin('\n'.join(['f', 's'])): self.importer.run() self.assertEqual(mock_foo.call_count, 1) # input_options should be called twice, as foo() returns None self.assertEqual(self.mock_input_options.call_count, 2) self.mock_input_options.assert_called_with(opts, default='a', require=ANY) def test_plugin_callback_return(self): """Test that plugin callbacks that return a value exit the loop.""" class DummyPlugin(plugins.BeetsPlugin): def __init__(self): super(DummyPlugin, self).__init__() self.register_listener('before_choose_candidate', self.return_choices) def return_choices(self, session, task): return [ui.commands.PromptChoice('f', 'Foo', self.foo)] def foo(self, session, task): return action.SKIP self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', u'enter Id', u'aBort') + ('Foo', ) # DummyPlugin.foo() should be called once with helper.control_stdin('f\n'): self.importer.run() # input_options should be called once, as foo() returns SKIP self.mock_input_options.assert_called_once_with(opts, default='a', require=ANY)
def setUp(self): self.setup_beets() self.load_plugins('mbsubmit') self._create_import_dir(2) self._setup_import_session() self.matcher = AutotagStub().install()
class EditDuringImporterTest(TerminalImportSessionSetup, unittest.TestCase, ImportHelper, TestHelper, EditMixin): """TODO """ IGNORED = ['added', 'album_id', 'id', 'mtime', 'path'] def setUp(self): self.setup_beets() self.load_plugins('edit') # Create some mediafiles, and store them for comparison. self._create_import_dir(3) self.items_orig = [Item.from_path(f.path) for f in self.media_files] self.matcher = AutotagStub().install() self.matcher.matching = AutotagStub.GOOD self.config['import']['timid'] = True def tearDown(self): EditPlugin.listeners = None self.unload_plugins() self.teardown_beets() self.matcher.restore() def test_edit_apply_asis(self): """Edit the album field for all items in the library, apply changes, using the original item tags. """ self._setup_import_session() # Edit track titles. self.run_mocked_interpreter({'replacements': {u'Tag Title': u'Edited Title'}}, # eDit, Apply changes. ['d', 'a']) # Check that only the 'title' field is modified. self.assertItemFieldsModified(self.lib.items(), self.items_orig, ['title'], self.IGNORED + ['albumartist', 'mb_albumartistid']) self.assertTrue(all('Edited Title' in i.title for i in self.lib.items())) # Ensure album is *not* fetched from a candidate. self.assertEqual(self.lib.albums()[0].mb_albumid, u'') def test_edit_discard_asis(self): """Edit the album field for all items in the library, discard changes, using the original item tags. """ self._setup_import_session() # Edit track titles. self.run_mocked_interpreter({'replacements': {u'Tag Title': u'Edited Title'}}, # eDit, Cancel, Use as-is. ['d', 'c', 'u']) # Check that nothing is modified, the album is imported ASIS. self.assertItemFieldsModified(self.lib.items(), self.items_orig, [], self.IGNORED + ['albumartist', 'mb_albumartistid']) self.assertTrue(all('Tag Title' in i.title for i in self.lib.items())) # Ensure album is *not* fetched from a candidate. self.assertEqual(self.lib.albums()[0].mb_albumid, u'') def test_edit_apply_candidate(self): """Edit the album field for all items in the library, apply changes, using a candidate. """ self._setup_import_session() # Edit track titles. self.run_mocked_interpreter({'replacements': {u'Applied Title': u'Edited Title'}}, # edit Candidates, 1, Apply changes. ['c', '1', 'a']) # Check that 'title' field is modified, and other fields come from # the candidate. self.assertTrue(all('Edited Title ' in i.title for i in self.lib.items())) self.assertTrue(all('match ' in i.mb_trackid for i in self.lib.items())) # Ensure album is fetched from a candidate. self.assertIn('albumid', self.lib.albums()[0].mb_albumid) def test_edit_discard_candidate(self): """Edit the album field for all items in the library, discard changes, using a candidate. """ self._setup_import_session() # Edit track titles. self.run_mocked_interpreter({'replacements': {u'Applied Title': u'Edited Title'}}, # edit Candidates, 1, Apply changes. ['c', '1', 'a']) # Check that 'title' field is modified, and other fields come from # the candidate. self.assertTrue(all('Edited Title ' in i.title for i in self.lib.items())) self.assertTrue(all('match ' in i.mb_trackid for i in self.lib.items())) # Ensure album is fetched from a candidate. self.assertIn('albumid', self.lib.albums()[0].mb_albumid) def test_edit_apply_asis_singleton(self): """Edit the album field for all items in the library, apply changes, using the original item tags and singleton mode. """ self._setup_import_session(singletons=True) # Edit track titles. self.run_mocked_interpreter({'replacements': {u'Tag Title': u'Edited Title'}}, # eDit, Apply changes, aBort. ['d', 'a', 'b']) # Check that only the 'title' field is modified. self.assertItemFieldsModified(self.lib.items(), self.items_orig, ['title'], self.IGNORED + ['albumartist', 'mb_albumartistid']) self.assertTrue(all('Edited Title' in i.title for i in self.lib.items())) def test_edit_apply_candidate_singleton(self): """Edit the album field for all items in the library, apply changes, using a candidate and singleton mode. """ self._setup_import_session() # Edit track titles. self.run_mocked_interpreter({'replacements': {u'Applied Title': u'Edited Title'}}, # edit Candidates, 1, Apply changes, aBort. ['c', '1', 'a', 'b']) # Check that 'title' field is modified, and other fields come from # the candidate. self.assertTrue(all('Edited Title ' in i.title for i in self.lib.items())) self.assertTrue(all('match ' in i.mb_trackid for i in self.lib.items()))
class ImportAddedTest(unittest.TestCase, ImportHelper): # The minimum mtime of the files to be imported min_mtime = None def setUp(self): preserve_plugin_listeners() self.setup_beets() self.load_plugins('importadded') self._create_import_dir(2) # Different mtimes on the files to be imported in order to test the # plugin modify_mtimes((mfile.path for mfile in self.media_files)) self.min_mtime = min(os.path.getmtime(mfile.path) for mfile in self.media_files) self.matcher = AutotagStub().install() self.matcher.macthin = AutotagStub.GOOD self._setup_import_session() self.importer.add_choice(importer.action.APPLY) def tearDown(self): self.unload_plugins() self.teardown_beets() self.matcher.restore() def find_media_file(self, item): """Find the pre-import MediaFile for an Item""" for m in self.media_files: if m.title.replace('Tag', 'Applied') == item.title: return m raise AssertionError(u"No MediaFile found for Item " + util.displayable_path(item.path)) def assertEqualTimes(self, first, second, msg=None): # noqa """For comparing file modification times at a sufficient precision""" self.assertAlmostEqual(first, second, places=4, msg=msg) def assertAlbumImport(self): # noqa self.importer.run() album = self.lib.albums().get() self.assertEqual(album.added, self.min_mtime) for item in album.items(): self.assertEqual(item.added, self.min_mtime) def test_import_album_with_added_dates(self): self.assertAlbumImport() def test_import_album_inplace_with_added_dates(self): self.config['import']['copy'] = False self.config['import']['move'] = False self.config['import']['link'] = False self.config['import']['hardlink'] = False self.assertAlbumImport() def test_import_album_with_preserved_mtimes(self): self.config['importadded']['preserve_mtimes'] = True self.importer.run() album = self.lib.albums().get() self.assertEqual(album.added, self.min_mtime) for item in album.items(): self.assertEqualTimes(item.added, self.min_mtime) mediafile_mtime = os.path.getmtime(self.find_media_file(item).path) self.assertEqualTimes(item.mtime, mediafile_mtime) self.assertEqualTimes(os.path.getmtime(item.path), mediafile_mtime) def test_reimported_album_skipped(self): # Import and record the original added dates self.importer.run() album = self.lib.albums().get() album_added_before = album.added items_added_before = dict((item.path, item.added) for item in album.items()) # Newer Item path mtimes as if Beets had modified them modify_mtimes(items_added_before.keys(), offset=10000) # Reimport self._setup_import_session(import_dir=album.path) self.importer.run() # Verify the reimported items album = self.lib.albums().get() self.assertEqualTimes(album.added, album_added_before) items_added_after = dict((item.path, item.added) for item in album.items()) for item_path, added_after in items_added_after.items(): self.assertEqualTimes(items_added_before[item_path], added_after, u"reimport modified Item.added for " + util.displayable_path(item_path)) def test_import_singletons_with_added_dates(self): self.config['import']['singletons'] = True self.importer.run() for item in self.lib.items(): mfile = self.find_media_file(item) self.assertEqualTimes(item.added, os.path.getmtime(mfile.path)) def test_import_singletons_with_preserved_mtimes(self): self.config['import']['singletons'] = True self.config['importadded']['preserve_mtimes'] = True self.importer.run() for item in self.lib.items(): mediafile_mtime = os.path.getmtime(self.find_media_file(item).path) self.assertEqualTimes(item.added, mediafile_mtime) self.assertEqualTimes(item.mtime, mediafile_mtime) self.assertEqualTimes(os.path.getmtime(item.path), mediafile_mtime) def test_reimported_singletons_skipped(self): self.config['import']['singletons'] = True # Import and record the original added dates self.importer.run() items_added_before = dict((item.path, item.added) for item in self.lib.items()) # Newer Item path mtimes as if Beets had modified them modify_mtimes(items_added_before.keys(), offset=10000) # Reimport import_dir = os.path.dirname(list(items_added_before.keys())[0]) self._setup_import_session(import_dir=import_dir, singletons=True) self.importer.run() # Verify the reimported items items_added_after = dict((item.path, item.added) for item in self.lib.items()) for item_path, added_after in items_added_after.items(): self.assertEqualTimes(items_added_before[item_path], added_after, u"reimport modified Item.added for " + util.displayable_path(item_path))