Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
14 changes: 13 additions & 1 deletion beetsplug/beatport4/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,19 @@ def import_task_files(self, task: object) -> None:

# All tracks on a Beatport release share the same cover
# art, so fetch the image once using the first track.
first_id = items[0].get("mb_trackid")
# Take the track ID from the match info rather than the
# imported items: other plugins (e.g. zero) may blank
# mb_trackid on the items before this handler runs (#38).
info = task.match.info
if isinstance(info, AlbumInfo):
first_id = next(
(t.track_id for t in info.tracks if t.track_id), None
)
else:
first_id = info.track_id
if not first_id:
self._log.debug("No Beatport track ID in match; skipping art")
return
image_data = self.client.get_image(
first_id,
self.config["art_width"].get(),
Expand Down
65 changes: 58 additions & 7 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,13 +498,16 @@ def test_setup_token_write_oserror_does_not_crash(self, plugin, tmp_path):
def _make_mock_task(data_source="Beatport", track_ids=None):
"""Create a mock import task with the given data source."""
task = MagicMock()
task.match.info.data_source = data_source
items = []
for tid in track_ids or ["123"]:
item = MagicMock()
item.get.return_value = tid
items.append(item)
task.imported_items.return_value = items
track_ids = track_ids or ["123"]
task.match.info = AlbumInfo(
album="Album",
album_id="1000",
artist="Artist",
artist_id="2000",
tracks=[TrackInfo(track_id=tid) for tid in track_ids],
data_source=data_source,
)
task.imported_items.return_value = [MagicMock() for _ in track_ids]
return task


Expand Down Expand Up @@ -564,6 +567,54 @@ def test_embeds_art_successfully(self, plugin_with_client, mock_client):
mock_client.get_image.assert_called_once()
mock_art.embed_item.assert_called_once()

def test_uses_match_track_id_not_item_mb_trackid(
self, plugin_with_client, mock_client
):
"""Regression (#38): plugins like zero can blank mb_trackid on the
imported items before this handler runs, so the track ID must come
from the match info, not the items."""
plugin_with_client.config["art"].set(True)
plugin_with_client.config["art_overwrite"].set(True)
task = _make_mock_task(track_ids=["123"])
# Simulate the zero plugin having cleared mb_trackid
for item in task.imported_items.return_value:
item.get.return_value = ""
mock_client.get_image.return_value = b"\x89PNG fake"

with patch("beetsplug.beatport4.plugin.art") as mock_art:
plugin_with_client.import_task_files(task)
mock_client.get_image.assert_called_once()
assert mock_client.get_image.call_args[0][0] == "123"
mock_art.embed_item.assert_called_once()

def test_singleton_uses_match_track_id(
self, plugin_with_client, mock_client
):
"""Singleton imports carry a TrackInfo match instead of AlbumInfo."""
plugin_with_client.config["art"].set(True)
plugin_with_client.config["art_overwrite"].set(True)
task = MagicMock()
task.match.info = TrackInfo(track_id="456", data_source="Beatport")
task.imported_items.return_value = [MagicMock()]
mock_client.get_image.return_value = b"\x89PNG fake"

with patch("beetsplug.beatport4.plugin.art") as mock_art:
plugin_with_client.import_task_files(task)
mock_client.get_image.assert_called_once()
assert mock_client.get_image.call_args[0][0] == "456"
mock_art.embed_item.assert_called_once()

def test_skips_when_match_has_no_track_ids(
self, plugin_with_client, mock_client
):
plugin_with_client.config["art"].set(True)
task = _make_mock_task(track_ids=[None])

with patch("beetsplug.beatport4.plugin.art") as mock_art:
plugin_with_client.import_task_files(task)
mock_client.get_image.assert_not_called()
mock_art.embed_item.assert_not_called()

def test_returns_early_on_none_image_data(
self, plugin_with_client, mock_client
):
Expand Down
Loading