From c3ea1ded301bd30fadd1ce807524057aee092336 Mon Sep 17 00:00:00 2001 From: Thomas Scholtes Date: Thu, 10 Apr 2014 15:26:05 +0200 Subject: [PATCH] Add item.try_write() to log errors Many commands and plugins use `item.write()` to update tags. Since the success of the call is not critical to the functionality of most consumers we want to catch any exceptions, log an error and continue with our task. The new method encapsulates this logic. This fixes #675. --- beets/importer.py | 5 +---- beets/library.py | 12 ++++++++++++ beets/ui/commands.py | 10 ++-------- beetsplug/chroma.py | 2 +- beetsplug/echonest.py | 2 +- beetsplug/echonest_tempo.py | 2 +- beetsplug/ftintitle.py | 2 +- beetsplug/lastgenre/__init__.py | 2 +- beetsplug/lyrics.py | 2 +- beetsplug/mbsync.py | 9 ++------- beetsplug/replaygain.py | 4 ++-- beetsplug/scrub.py | 2 +- 12 files changed, 26 insertions(+), 28 deletions(-) diff --git a/beets/importer.py b/beets/importer.py index b02ee0ede..d3cd623d4 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -895,10 +895,7 @@ def manipulate_files(session): item.move(True) if config['import']['write'] and task.should_write_tags(): - try: - item.write() - except library.FileOperationError as exc: - log.error(exc) + item.try_write() # Save new paths. with session.lib.transaction(): diff --git a/beets/library.py b/beets/library.py index f9285cabb..499d67403 100644 --- a/beets/library.py +++ b/beets/library.py @@ -454,6 +454,18 @@ class Item(LibModel): self.mtime = self.current_mtime() plugins.send('after_write', item=self, path=path) + def try_write(self, path=None): + """Calls `write()` but catches and logs `FileOperationError`s. + + Returns `False` an exception was caught and `True` otherwise. + """ + try: + self.write(path) + return True + except FileOperationError as exc: + log.error(exc) + return False + # Files themselves. diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 1b1aab5b0..32050accd 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -1135,10 +1135,7 @@ def modify_items(lib, mods, dels, query, write, move, album, confirm): else: changed_items = changed for item in changed_items: - try: - item.write() - except library.FileOperationError as exc: - log.error(exc) + item.try_write() modify_cmd = ui.Subcommand('modify', help='change metadata fields', aliases=('mod',)) @@ -1249,10 +1246,7 @@ def write_items(lib, query, pretend): library.Item._media_fields, always=True) if changed and not pretend: - try: - item.write() - except library.FileOperationError as exc: - log.error(exc) + item.try_write() write_cmd = ui.Subcommand('write', help='write tag information to files') write_cmd.parser.add_option('-p', '--pretend', action='store_true', diff --git a/beetsplug/chroma.py b/beetsplug/chroma.py index d1624c6be..9221e107e 100644 --- a/beetsplug/chroma.py +++ b/beetsplug/chroma.py @@ -270,7 +270,7 @@ def fingerprint_item(item, write=False): log.info(u'{0}: writing fingerprint'.format( util.displayable_path(item.path) )) - item.write() + item.try_write() if item._db: item.store() return item.acoustid_fingerprint diff --git a/beetsplug/echonest.py b/beetsplug/echonest.py index 4ac000885..8b6509a55 100644 --- a/beetsplug/echonest.py +++ b/beetsplug/echonest.py @@ -414,7 +414,7 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): # Write and save. if write: - item.write() + item.try_write() item.store() diff --git a/beetsplug/echonest_tempo.py b/beetsplug/echonest_tempo.py index 11db03de2..0e144fb4d 100644 --- a/beetsplug/echonest_tempo.py +++ b/beetsplug/echonest_tempo.py @@ -55,7 +55,7 @@ def fetch_item_tempo(lib, loglevel, item, write): (item.artist, item.title)) item.bpm = int(tempo) if write: - item.write() + item.try_write() item.store() diff --git a/beetsplug/ftintitle.py b/beetsplug/ftintitle.py index e9aae1ed1..731d8116c 100644 --- a/beetsplug/ftintitle.py +++ b/beetsplug/ftintitle.py @@ -121,6 +121,6 @@ class FtInTitlePlugin(BeetsPlugin): ft_in_title(item) item.store() if write: - item.write() + item.try_write() cmd.func = func return [cmd] diff --git a/beetsplug/lastgenre/__init__.py b/beetsplug/lastgenre/__init__.py index c398bf7e3..b166af034 100644 --- a/beetsplug/lastgenre/__init__.py +++ b/beetsplug/lastgenre/__init__.py @@ -358,7 +358,7 @@ class LastGenrePlugin(plugins.BeetsPlugin): )) if write: - item.write() + item.try_write() lastgenre_cmd.func = lastgenre_func return [lastgenre_cmd] diff --git a/beetsplug/lyrics.py b/beetsplug/lyrics.py index 28949b307..50d1529e1 100644 --- a/beetsplug/lyrics.py +++ b/beetsplug/lyrics.py @@ -450,7 +450,7 @@ class LyricsPlugin(BeetsPlugin): item.lyrics = lyrics if write: - item.write() + item.try_write() item.store() def get_lyrics(self, artist, title): diff --git a/beetsplug/mbsync.py b/beetsplug/mbsync.py index 8df913472..f5551f5a1 100644 --- a/beetsplug/mbsync.py +++ b/beetsplug/mbsync.py @@ -38,13 +38,8 @@ def _print_and_apply_changes(lib, item, old_data, move, pretend, write): if move and lib.directory in util.ancestry(item.path): item.move(with_album=False) - if write: - try: - item.write() - except Exception as exc: - log.error(u'could not sync {0}: {1}'.format( - util.displayable_path(item.path), exc)) - return False + if write and not item.try_write(): + return False item.store() return True diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py index 9fa894177..6a0cf593d 100644 --- a/beetsplug/replaygain.py +++ b/beetsplug/replaygain.py @@ -547,7 +547,7 @@ class ReplayGainPlugin(BeetsPlugin): album_gain.track_gains): self.store_track_gain(item, track_gain) if write: - item.write() + item.try_write() except ReplayGainError as e: log.warn(u"ReplayGain error: {1}".format(e)) except FatalReplayGainError as e: @@ -581,7 +581,7 @@ class ReplayGainPlugin(BeetsPlugin): self.store_track_gain(item, track_gains[0]) if write: - item.write() + item.try_write() except ReplayGainError as e: log.warn(u"ReplayGain error: {1}".format(e)) except FatalReplayGainError as e: diff --git a/beetsplug/scrub.py b/beetsplug/scrub.py index ddd7fd0cc..ca37538f6 100644 --- a/beetsplug/scrub.py +++ b/beetsplug/scrub.py @@ -77,7 +77,7 @@ class ScrubPlugin(BeetsPlugin): # Restore tags, if enabled. if opts.write: log.debug(u'writing new tags after scrub') - item.write() + item.try_write() if art: log.info('restoring art') mf = mediafile.MediaFile(item.path)