--- Begin Message ---
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,
--- End Message ---