Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Please unblock package beets. This fixes one reported FTBFS due to test failures with newer python-mutagen (#851016), and one unreported FTBFS due to a different test failure with newer python-mutagen (previously masked by the other failure), by backporting upstream fixes. unblock beets/1.3.19-2.1 Regards, S
diffstat for beets-1.3.19 beets-1.3.19 changelog | 14 control | 4 patches/Test-true-FLAC-bitrate-from-Mutagen-1.35.patch | 24 + patches/mediafile-Cleanup-mutagen-error-handling.patch | 241 +++++++++++++++++ patches/series | 2 5 files changed, 283 insertions(+), 2 deletions(-) diff -Nru beets-1.3.19/debian/changelog beets-1.3.19/debian/changelog --- beets-1.3.19/debian/changelog 2016-08-30 06:07:14.000000000 +0100 +++ beets-1.3.19/debian/changelog 2017-01-23 09:41:08.000000000 +0000 @@ -1,3 +1,17 @@ +beets (1.3.19-2.1) unstable; urgency=medium + + * Non-maintainer upload. + * d/p/mediafile-Cleanup-mutagen-error-handling.patch: + Add patch backported from upstream to update exception handling for + python-mutagen >= 1.33. This fixes a test failure and + FTBFS (Closes: #851016) + * d/p/Test-true-FLAC-bitrate-from-Mutagen-1.35.patch: + Add patch backported from upstream to fix a failing test with + python-mutagen >= 1.35 + - d/control: depend and build-depend on a compatible version + + -- Simon McVittie <s...@debian.org> Mon, 23 Jan 2017 09:41:08 +0000 + beets (1.3.19-2) unstable; urgency=medium * Fix occasional FTBFS due to lack of mock cleanup. Thanks Santiago Vila. diff -Nru beets-1.3.19/debian/control beets-1.3.19/debian/control --- beets-1.3.19/debian/control 2016-08-30 04:40:16.000000000 +0100 +++ beets-1.3.19/debian/control 2017-01-23 09:41:08.000000000 +0000 @@ -17,7 +17,7 @@ python-mpd, python-munkres, python-musicbrainzngs (>= 0.4), - python-mutagen (>= 1.27), + python-mutagen (>= 1.35), python-pathlib, python-pylast, python-rarfile, @@ -41,7 +41,7 @@ libjs-underscore, python-enum34, python-musicbrainzngs (>= 0.4), - python-mutagen (>= 1.21), + python-mutagen (>= 1.35), python-pkg-resources, ${misc:Depends}, ${python:Depends} diff -Nru beets-1.3.19/debian/patches/mediafile-Cleanup-mutagen-error-handling.patch beets-1.3.19/debian/patches/mediafile-Cleanup-mutagen-error-handling.patch --- beets-1.3.19/debian/patches/mediafile-Cleanup-mutagen-error-handling.patch 1970-01-01 01:00:00.000000000 +0100 +++ beets-1.3.19/debian/patches/mediafile-Cleanup-mutagen-error-handling.patch 2017-01-23 09:41:08.000000000 +0000 @@ -0,0 +1,241 @@ +From: Christoph Reiter <reiter.christ...@gmail.com> +Date: Mon, 27 Jun 2016 09:43:48 +0200 +Subject: mediafile: Cleanup mutagen error handling + +Instead of the individial mutagen format exceptions use the +mutagen.MutagenError exception introduced in 1.25. + +Since 1.33 mutagen will only raise MutagenError for load/save/delete +and no longer raise IOError. Translate both errors to UnreadableFileError +to support older and newer mutagen versions. Unify error handling +in __init__(), save() and delete(). + +Since it's no longer possible to get an IOError from MediaFile, adjust +all callers and tests accordingly. + +This was tested with mutagen 1.27 and current mutagen master. + +[smcv: backported to 1.3.19 by replacing six.text_type with unicode] + +Origin: upstream, 1.4.1, commit:629241efd389bea7b4075f2591a06f2ef462dc82 +--- + beets/library.py | 8 +++---- + beets/mediafile.py | 65 +++++++++++++++++++++++--------------------------- + beetsplug/scrub.py | 13 ++++++---- + test/test_mediafile.py | 23 +++++++++++++++++- + 4 files changed, 64 insertions(+), 45 deletions(-) + +diff --git a/beets/library.py b/beets/library.py +index 3450a35a..70fff1a7 100644 +--- a/beets/library.py ++++ b/beets/library.py +@@ -25,7 +25,7 @@ import re + from unidecode import unidecode + + from beets import logging +-from beets.mediafile import MediaFile, MutagenError, UnreadableFileError ++from beets.mediafile import MediaFile, UnreadableFileError + from beets import plugins + from beets import util + from beets.util import bytestring_path, syspath, normpath, samefile +@@ -560,7 +560,7 @@ class Item(LibModel): + read_path = normpath(read_path) + try: + mediafile = MediaFile(syspath(read_path)) +- except (OSError, IOError, UnreadableFileError) as exc: ++ except UnreadableFileError as exc: + raise ReadError(read_path, exc) + + for key in self._media_fields: +@@ -607,14 +607,14 @@ class Item(LibModel): + try: + mediafile = MediaFile(syspath(path), + id3v23=beets.config['id3v23'].get(bool)) +- except (OSError, IOError, UnreadableFileError) as exc: ++ except UnreadableFileError as exc: + raise ReadError(self.path, exc) + + # Write the tags to the file. + mediafile.update(item_tags) + try: + mediafile.save() +- except (OSError, IOError, MutagenError) as exc: ++ except UnreadableFileError as exc: + raise WriteError(self.path, exc) + + # The file has a new mtime. +diff --git a/beets/mediafile.py b/beets/mediafile.py +index 556b41bb..026da3e1 100644 +--- a/beets/mediafile.py ++++ b/beets/mediafile.py +@@ -1344,32 +1344,12 @@ class MediaFile(object): + path = syspath(path) + self.path = path + +- unreadable_exc = ( +- mutagen.mp3.error, +- mutagen.id3.error, +- mutagen.flac.error, +- mutagen.monkeysaudio.MonkeysAudioHeaderError, +- mutagen.mp4.error, +- mutagen.oggopus.error, +- mutagen.oggvorbis.error, +- mutagen.ogg.error, +- mutagen.asf.error, +- mutagen.apev2.error, +- mutagen.aiff.error, +- ) + try: + self.mgfile = mutagen.File(path) +- except unreadable_exc as exc: +- log.debug(u'header parsing failed: {0}', unicode(exc)) ++ except (mutagen.MutagenError, IOError) as exc: ++ # Mutagen <1.33 could raise IOError ++ log.debug(u'parsing failed: {0}', unicode(exc)) + raise UnreadableFileError(path) +- except IOError as exc: +- if type(exc) == IOError: +- # This is a base IOError, not a subclass from Mutagen or +- # anywhere else. +- raise +- else: +- log.debug(u'{}', traceback.format_exc()) +- raise MutagenError(path, exc) + except Exception as exc: + # Isolate bugs in Mutagen. + log.debug(u'{}', traceback.format_exc()) +@@ -1426,7 +1406,8 @@ class MediaFile(object): + self.id3v23 = id3v23 and self.type == 'mp3' + + def save(self): +- """Write the object's tags back to the file. ++ """Write the object's tags back to the file. May ++ throw `UnreadableFileError`. + """ + # Possibly save the tags to ID3v2.3. + kwargs = {} +@@ -1438,27 +1419,41 @@ class MediaFile(object): + id3.update_to_v23() + kwargs['v2_version'] = 3 + +- # Isolate bugs in Mutagen. + try: + self.mgfile.save(**kwargs) +- except (IOError, OSError): +- # Propagate these through: they don't represent Mutagen bugs. +- raise ++ except (mutagen.MutagenError, IOError) as exc: ++ # Mutagen <1.33 could raise IOError ++ log.debug(u'saving failed: {0}', unicode(exc)) ++ raise UnreadableFileError(self.path) + except Exception as exc: ++ # Isolate bugs in Mutagen. + log.debug(u'{}', traceback.format_exc()) + log.error(u'uncaught Mutagen exception in save: {0}', exc) + raise MutagenError(self.path, exc) + + def delete(self): +- """Remove the current metadata tag from the file. ++ """Remove the current metadata tag from the file. May ++ throw `UnreadableFileError`. + """ ++ + try: +- self.mgfile.delete() +- except NotImplementedError: +- # For Mutagen types that don't support deletion (notably, +- # ASF), just delete each tag individually. +- for tag in self.mgfile.keys(): +- del self.mgfile[tag] ++ try: ++ self.mgfile.delete() ++ except NotImplementedError: ++ # FIXME: This is fixed in mutagen >=1.31 ++ # For Mutagen types that don't support deletion (notably, ++ # ASF), just delete each tag individually. ++ for tag in self.mgfile.keys(): ++ del self.mgfile[tag] ++ except (mutagen.MutagenError, IOError) as exc: ++ # Mutagen <1.33 could raise IOError ++ log.debug(u'deleting failed: {0}', unicode(exc)) ++ raise UnreadableFileError(self.path) ++ except Exception as exc: ++ # Isolate bugs in Mutagen. ++ log.debug(u'{}', traceback.format_exc()) ++ log.error(u'uncaught Mutagen exception in save: {0}', exc) ++ raise MutagenError(self.path, exc) + + # Convenient access to the set of available fields. + +diff --git a/beetsplug/scrub.py b/beetsplug/scrub.py +index ed4040d5..4dcefe57 100644 +--- a/beetsplug/scrub.py ++++ b/beetsplug/scrub.py +@@ -119,7 +119,7 @@ class ScrubPlugin(BeetsPlugin): + try: + mf = mediafile.MediaFile(util.syspath(item.path), + config['id3v23'].get(bool)) +- except IOError as exc: ++ except mediafile.UnreadableFileError as exc: + self._log.error(u'could not open file to scrub: {0}', + exc) + art = mf.art +@@ -133,10 +133,13 @@ class ScrubPlugin(BeetsPlugin): + item.try_write() + if art: + self._log.debug(u'restoring art') +- mf = mediafile.MediaFile(util.syspath(item.path), +- config['id3v23'].get(bool)) +- mf.art = art +- mf.save() ++ try: ++ mf = mediafile.MediaFile(util.syspath(item.path), ++ config['id3v23'].get(bool)) ++ mf.art = art ++ mf.save() ++ except mediafile.UnreadableFileError as exc: ++ self._log.error(u'could not write tags: {0}', exc) + + def import_task_files(self, session, task): + """Automatically scrub imported files.""" +diff --git a/test/test_mediafile.py b/test/test_mediafile.py +index e2fdd9fc..2ec3704f 100644 +--- a/test/test_mediafile.py ++++ b/test/test_mediafile.py +@@ -28,7 +28,7 @@ from test import _common + from test._common import unittest + from beets.mediafile import MediaFile, MediaField, Image, \ + MP3DescStorageStyle, StorageStyle, MP4StorageStyle, \ +- ASFStorageStyle, ImageType, CoverArtField ++ ASFStorageStyle, ImageType, CoverArtField, UnreadableFileError + from beets.library import Item + from beets.plugins import BeetsPlugin + from beets.util import bytestring_path +@@ -453,6 +453,27 @@ class ReadWriteTestBase(ArtTestMixin, GenreListTestMixin, + if os.path.isdir(self.temp_dir): + shutil.rmtree(self.temp_dir) + ++ def test_read_nonexisting(self): ++ mediafile = self._mediafile_fixture('full') ++ os.remove(mediafile.path) ++ self.assertRaises(UnreadableFileError, MediaFile, mediafile.path) ++ ++ def test_save_nonexisting(self): ++ mediafile = self._mediafile_fixture('full') ++ os.remove(mediafile.path) ++ try: ++ mediafile.save() ++ except UnreadableFileError: ++ pass ++ ++ def test_delete_nonexisting(self): ++ mediafile = self._mediafile_fixture('full') ++ os.remove(mediafile.path) ++ try: ++ mediafile.delete() ++ except UnreadableFileError: ++ pass ++ + def test_read_audio_properties(self): + mediafile = self._mediafile_fixture('full') + for key, value in self.audio_properties.items(): diff -Nru beets-1.3.19/debian/patches/series beets-1.3.19/debian/patches/series --- beets-1.3.19/debian/patches/series 2016-08-30 00:23:52.000000000 +0100 +++ beets-1.3.19/debian/patches/series 2017-01-23 09:41:08.000000000 +0000 @@ -3,3 +3,5 @@ fix-test_mediafile_edge fix-test_nonexistent_file skip-test_query-path-tests +mediafile-Cleanup-mutagen-error-handling.patch +Test-true-FLAC-bitrate-from-Mutagen-1.35.patch diff -Nru beets-1.3.19/debian/patches/Test-true-FLAC-bitrate-from-Mutagen-1.35.patch beets-1.3.19/debian/patches/Test-true-FLAC-bitrate-from-Mutagen-1.35.patch --- beets-1.3.19/debian/patches/Test-true-FLAC-bitrate-from-Mutagen-1.35.patch 1970-01-01 01:00:00.000000000 +0100 +++ beets-1.3.19/debian/patches/Test-true-FLAC-bitrate-from-Mutagen-1.35.patch 2017-01-23 09:41:08.000000000 +0000 @@ -0,0 +1,24 @@ +From: Adrian Sampson <adr...@radbox.org> +Date: Fri, 23 Dec 2016 20:23:23 -0500 +Subject: Test "true" FLAC bitrate from Mutagen 1.35 + +Fix #2343. + +Origin: upstream, 1.4.3, commit:10f0d03d790da2e849125104a718a9f14ac535e6 +--- + test/test_mediafile.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/test_mediafile.py b/test/test_mediafile.py +index 2ec3704f..6fea9ab7 100644 +--- a/test/test_mediafile.py ++++ b/test/test_mediafile.py +@@ -896,7 +896,7 @@ class FlacTest(ReadWriteTestBase, PartialTestMixin, + extension = 'flac' + audio_properties = { + 'length': 1.0, +- 'bitrate': 175120, ++ 'bitrate': 108688, + 'format': u'FLAC', + 'samplerate': 44100, + 'bitdepth': 16,