diff --git a/beetsplug/zero.py b/beetsplug/zero.py index 8c65fe855..ed41511c8 100644 --- a/beetsplug/zero.py +++ b/beetsplug/zero.py @@ -17,7 +17,7 @@ import re import logging from beets.plugins import BeetsPlugin -from beets.library import Item +from beets.mediafile import MediaFile from beets.importer import action from beets.util import confit @@ -51,7 +51,7 @@ class ZeroPlugin(BeetsPlugin): log.warn(u'[zero] field \'{0}\' ignored, zeroing ' u'it would be dangerous'.format(field)) continue - if field not in Item._fields.keys(): + if field not in MediaFile.fields(): log.error(u'[zero] invalid field: {0}'.format(field)) continue @@ -59,7 +59,7 @@ class ZeroPlugin(BeetsPlugin): self.patterns[field] = self.config[field].as_str_seq() except confit.NotFoundError: # Matches everything - self.patterns[field] = [u''] + self.patterns[field] = True def import_task_choice_event(self, session, task): """Listen for import_task_choice event.""" @@ -73,23 +73,29 @@ class ZeroPlugin(BeetsPlugin): """Check if field (as string) is matching any of the patterns in the list. """ + if patterns is True: + return True for p in patterns: if re.search(p, unicode(field), flags=re.IGNORECASE): return True return False def write_event(self, item, path, tags): - """Listen for write event.""" + """Set values in tags to `None` if the key and value are matched + by `self.patterns`. + """ if not self.patterns: log.warn(u'[zero] no fields, nothing to do') return for field, patterns in self.patterns.items(): - if field not in tags: - log.error(u'[zero] no such field: {0}'.format(field)) - continue + if field in tags: + value = tags[field] + match = self.match_patterns(tags[field], patterns) + else: + value = '' + match = patterns is True - value = tags[field] - if self.match_patterns(value, patterns): + if match: log.debug(u'[zero] {0}: {1} -> None'.format(field, value)) tags[field] = None diff --git a/docs/changelog.rst b/docs/changelog.rst index 17ffaf462..bca325321 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -10,6 +10,7 @@ New: files as they are imported. Thanks to :user:`xsteadfastx`. :bug:`1098` * A new :doc:`/plugins/plexupdate` lets you notify a `Plex`_ server when the database changes. Thanks again to xsteadfastx. :bug:`1120` +* :doc:`/plugins/zero` can remove embedded images. Fixed: diff --git a/docs/plugins/zero.rst b/docs/plugins/zero.rst index 6a857e3de..c53a7b148 100644 --- a/docs/plugins/zero.rst +++ b/docs/plugins/zero.rst @@ -16,7 +16,9 @@ Make a ``zero:`` section in your configuration file. You can specify the fields to nullify and the conditions for nullifying them: * Set ``fields`` to a whitespace-separated list of fields to change. You can - get the list of all available fields by running ``beet fields``. + get the list of all available fields by running ``beet fields``. In + addition, the ``images`` field allows you to remove any images + embedded in the media file. * To conditionally filter a field, use ``field: [regexp, regexp]`` to specify regular expressions. diff --git a/test/helper.py b/test/helper.py index d23f94bf2..4cd7e8ef2 100644 --- a/test/helper.py +++ b/test/helper.py @@ -47,7 +47,7 @@ import beets.plugins from beets.library import Library, Item, Album from beets import importer from beets.autotag.hooks import AlbumInfo, TrackInfo -from beets.mediafile import MediaFile +from beets.mediafile import MediaFile, Image # TODO Move AutotagMock here import _common @@ -346,18 +346,33 @@ class TestHelper(object): items.append(item) return self.lib.add_album(items) - def create_mediafile_fixture(self, ext='mp3'): + def create_mediafile_fixture(self, ext='mp3', images=[]): """Copies a fixture mediafile with the extension to a temporary location and returns the path. It keeps track of the created locations and will delete the with `remove_mediafile_fixtures()` + + `images` is a subset of 'png', 'jpg', and 'tiff'. For each + specified extension a cover art image is added to the media + file. """ src = os.path.join(_common.RSRC, 'full.' + ext) handle, path = mkstemp() os.close(handle) shutil.copyfile(src, path) + if images: + mediafile = MediaFile(path) + imgs = [] + for img_ext in images: + img_path = os.path.join(_common.RSRC, + 'image-2x3.{0}'.format(img_ext)) + with open(img_path, 'rb') as f: + imgs.append(Image(f.read())) + mediafile.images = imgs + mediafile.save() + if not hasattr(self, '_mediafile_fixtures'): self._mediafile_fixtures = [] self._mediafile_fixtures.append(path) diff --git a/test/test_zero.py b/test/test_zero.py index 38b854e45..097ef49ed 100644 --- a/test/test_zero.py +++ b/test/test_zero.py @@ -82,6 +82,20 @@ class ZeroPluginTest(unittest.TestCase, TestHelper): self.assertEqual(item['year'], 2000) self.assertIsNone(mediafile.year) + def test_album_art(self): + path = self.create_mediafile_fixture(images=['jpg']) + item = Item.from_path(path) + + mediafile = MediaFile(item.path) + self.assertNotEqual(0, len(mediafile.images)) + + config['zero'] = {'fields': ['images']} + self.load_plugins('zero') + + item.write() + mediafile = MediaFile(item.path) + self.assertEqual(0, len(mediafile.images)) + def suite(): return unittest.TestLoader().loadTestsFromName(__name__)