diff --git a/beets/library.py b/beets/library.py index 8a1687914..f13ac9e2a 100644 --- a/beets/library.py +++ b/beets/library.py @@ -320,11 +320,9 @@ class Item(object): read_path = normpath(read_path) try: f = MediaFile(syspath(read_path)) - except Exception: - log.debug(u'failed reading file: {0}'.format( - displayable_path(read_path)) - ) - raise + except (OSError, IOError) as exc: + raise util.FilesystemError(exc, 'read', (self.path,), + traceback.format_exc()) for key in ITEM_KEYS_META: setattr(self, key, getattr(f, key)) @@ -340,7 +338,12 @@ class Item(object): """ plugins.send('write', item=self) - f = MediaFile(syspath(self.path)) + try: + f = MediaFile(syspath(self.path)) + except (OSError, IOError) as exc: + raise util.FilesystemError(exc, 'read', (self.path,), + traceback.format_exc()) + for key in ITEM_KEYS_WRITABLE: setattr(f, key, getattr(self, key)) diff --git a/beets/mediafile.py b/beets/mediafile.py index 3bb3d3416..dd116494b 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -59,6 +59,10 @@ log = logging.getLogger('beets') class UnreadableFileError(IOError): pass +class FileIOError(UnreadableFileError, IOError): + def __init__(self, exc): + IOError.__init__(self, exc.errno, exc.strerror, exc.filename) + # Raised for files that don't seem to have a type MediaFile supports. class FileTypeError(UnreadableFileError): pass @@ -864,8 +868,8 @@ class MediaFile(object): except unreadable_exc as exc: log.debug(u'header parsing failed: {0}'.format(unicode(exc))) raise UnreadableFileError('Mutagen could not read file') - except IOError: - raise UnreadableFileError('could not read file') + except IOError as exc: + raise FileIOError(exc) except Exception as exc: # Hide bugs in Mutagen. log.debug(traceback.format_exc()) diff --git a/beets/util/__init__.py b/beets/util/__init__.py index d94b14e22..0efd5ae44 100644 --- a/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -97,7 +97,7 @@ class FilesystemError(HumanReadableException): clause = 'while {0} {1} to {2}'.format( self._gerund(), repr(self.paths[0]), repr(self.paths[1]) ) - elif self.verb in ('delete', 'write', 'create'): + elif self.verb in ('delete', 'write', 'create', 'read'): clause = 'while {0} {1}'.format( self._gerund(), repr(self.paths[0]) ) diff --git a/docs/changelog.rst b/docs/changelog.rst index 7a56160fa..0d79959fa 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -31,6 +31,8 @@ Changelog * The :ref:`fields-cmd` command shows template fields provided by plugins. Thanks again to Pedro Silva. * Album art filenames now respect the :ref:`replace` configuration. +* Friendly error messages are now printed when trying to read or write files + that go missing. 1.1.0 (April 29, 203) ---------------------