Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions beets/test/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,15 +364,17 @@ def add_album_fixture(
items.append(item)
return self.lib.add_album(items)

def create_mediafile_fixture(self, ext="mp3", images=[]):
def create_mediafile_fixture(self, ext="mp3", images=[], target_dir=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Replace mutable default arguments with None (default-mutable-arg)

"""Copy a fixture mediafile with the extension to `temp_dir`.

`images` is a subset of 'png', 'jpg', and 'tiff'. For each
specified extension a cover art image is added to the media
file.
"""
if not target_dir:
target_dir = self.temp_dir
src = os.path.join(_common.RSRC, util.bytestring_path(f"full.{ext}"))
handle, path = mkstemp(dir=self.temp_dir)
handle, path = mkstemp(dir=target_dir)
path = bytestring_path(path)
os.close(handle)
shutil.copyfile(syspath(src), syspath(path))
Expand Down
9 changes: 7 additions & 2 deletions beetsplug/_utils/art.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,14 @@ def extract_first(log, outpath, items):
return real_path


def clear_item(item, log):
if mediafile.MediaFile(syspath(item.path)).images:
log.debug("Clearing art for {}", item)
item.try_write(tags={"images": None})


def clear(log, lib, query):
items = lib.items(query)
log.info("Clearing album art from {} items", len(items))
for item in items:
log.debug("Clearing art for {}", item)
item.try_write(tags={"images": None})
clear_item(item, log)
10 changes: 10 additions & 0 deletions beetsplug/embedart.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def __init__(self):
"ifempty": False,
"remove_art_file": False,
"quality": 0,
"clearart_on_import": False,
}
)

Expand All @@ -82,6 +83,9 @@ def __init__(self):

self.register_listener("art_set", self.process_album)

if self.config["clearart_on_import"].get(bool):
self.register_listener("import_task_files", self.import_task_files)

def commands(self):
# Embed command.
embed_cmd = ui.Subcommand(
Expand Down Expand Up @@ -278,3 +282,9 @@ def remove_artfile(self, album):
os.remove(syspath(album.artpath))
album.artpath = None
album.store()

def import_task_files(self, session, task):
"""Automatically clearart of imported files."""
for item in task.imported_items():
self._log.debug("clearart-on-import {.filepath}", item)
art.clear_item(item, self._log)
41 changes: 40 additions & 1 deletion test/plugins/test_embedart.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,29 @@
# included in all copies or substantial portions of the Software.


import os
import os.path
import shutil
import tempfile
import unittest
from unittest.mock import MagicMock, patch

import pytest
from mediafile import MediaFile

from beets import config, logging, ui
from beets.test import _common
from beets.test.helper import (
ImportHelper,
BeetsTestCase,
FetchImageHelper,
IOMixin,
PluginMixin,
)
from beets.util import bytestring_path, displayable_path, syspath
from beets.util.artresizer import ArtResizer
from beetsplug._utils import art
from test.test_art_resize import DummyIMBackend

Check failure on line 38 in test/plugins/test_embedart.py

View workflow job for this annotation

GitHub Actions / Check linting

Ruff (I001)

test/plugins/test_embedart.py:16:1: I001 Import block is un-sorted or un-formatted


def require_artresizer_compare(test):
Expand Down Expand Up @@ -75,7 +76,9 @@
return wrapper


class EmbedartCliTest(IOMixin, PluginMixin, FetchImageHelper, BeetsTestCase):
class EmbedartCliTest(
ImportHelper, IOMixin, PluginMixin, FetchImageHelper, BeetsTestCase
):
plugin = "embedart"
small_artpath = os.path.join(_common.RSRC, b"image-2x3.jpg")
abbey_artpath = os.path.join(_common.RSRC, b"abbey.jpg")
Expand Down Expand Up @@ -225,10 +228,20 @@
item = album.items()[0]
self.io.addinput("y")
self.run_command("embedart", "-f", self.small_artpath)
embedded_time = os.path.getmtime(syspath(item.path))

self.io.addinput("y")
self.run_command("clearart")
mediafile = MediaFile(syspath(item.path))
assert not mediafile.images
clear_time = os.path.getmtime(syspath(item.path))
assert clear_time > embedded_time

# A run on a file without an image should not be modified
self.io.addinput("y")
self.run_command("clearart")
no_clear_time = os.path.getmtime(syspath(item.path))
assert no_clear_time == clear_time

def test_clear_art_with_no_input(self):
self._setup_data()
Expand Down Expand Up @@ -273,6 +286,32 @@
mediafile = MediaFile(syspath(item.path))
assert not mediafile.images

def test_clearart_on_import_disabled(self):
file_path = self.create_mediafile_fixture(
images=["jpg"], target_dir=self.import_path
)
self.import_media.append(file_path)
with self.configure_plugin({"clearart_on_import": False}):
importer = self.setup_importer(autotag=False, write=True)
importer.run()

item = self.lib.items()[0]
assert MediaFile(os.path.join(item.path)).images

def test_clearart_on_import_enabled(self):
file_path = self.create_mediafile_fixture(
images=["jpg"], target_dir=self.import_path
)
self.import_media.append(file_path)
# Force re-init the plugin to register the listener
self.unload_plugins()
with self.configure_plugin({"clearart_on_import": True}):
importer = self.setup_importer(autotag=False, write=True)
importer.run()

item = self.lib.items()[0]
assert not MediaFile(os.path.join(item.path)).images


class DummyArtResizer(ArtResizer):
"""An `ArtResizer` which pretends that ImageMagick is available, and has
Expand Down
Loading