Skip to content

Add Embedded Art support to fetchart plugin - #6829

Open
overhacked wants to merge 7 commits into
beetbox:masterfrom
overhacked:overhacked/fetchart_embedded
Open

Add Embedded Art support to fetchart plugin#6829
overhacked wants to merge 7 commits into
beetbox:masterfrom
overhacked:overhacked/fetchart_embedded

Conversation

@overhacked

@overhacked overhacked commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Description

Add embedded source to extract embedded art from files. Add skip_embedded option to detect embedded art and skip fetching from other sources (if extracting isn't the desired end state).

If skip_embedded=yes, then files with embedded art are considered "done" and skipped by FetchArt. If the embedded source is enabled, then embedded artwork is always extracted. The two settings are independent of each other.

Fixes #1130.

To Do

  • Documentation.
  • Changelog.
  • Tests.

@overhacked
overhacked requested a review from a team as a code owner July 12, 2026 20:32
@github-actions github-actions Bot added the fetchart fetchart plugin label Jul 12, 2026
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.97561% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.66%. Comparing base (efc8970) to head (f63691c).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
beetsplug/fetchart.py 60.97% 11 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6829      +/-   ##
==========================================
- Coverage   75.68%   75.66%   -0.02%     
==========================================
  Files         163      163              
  Lines       21423    21459      +36     
  Branches     3387     3393       +6     
==========================================
+ Hits        16213    16238      +25     
- Misses       4410     4419       +9     
- Partials      800      802       +2     
Files with missing lines Coverage Δ
beetsplug/fetchart.py 73.41% <60.97%> (-0.47%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@overhacked
overhacked marked this pull request as draft July 13, 2026 00:14
@overhacked

Copy link
Copy Markdown
Contributor Author

Taking this to draft to do a little work to improve the test coverage.

@overhacked
overhacked force-pushed the overhacked/fetchart_embedded branch 2 times, most recently from 18cd2e7 to aac06ee Compare July 15, 2026 13:25
@overhacked
overhacked marked this pull request as ready for review July 15, 2026 13:25
@overhacked

Copy link
Copy Markdown
Contributor Author

@snejus, this is ready whenever you have time to take a look. There are some test coverage places I'd like to address, but when investigating I found that more test harness refactoring around when plugins read their configuration (e.g. @cached_property and PluginMixin.preload_plugin vs .configure_plugin()) would be necessary to get more coverage; also, the coverage gaps--while technically part of this PR's diff--already existed in the fetchart CLI test suite, so I'd be adding tests that don't test the Embedded source directly.

@semohr semohr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks! Looks mostly good from my side 👍

Comment thread beetsplug/_utils/art.py
Comment thread beetsplug/_utils/art.py
Comment thread beetsplug/_utils/art.py Outdated
Comment thread beetsplug/fetchart.py
matches = []
# can there be more than one releasegroupid per response?
for mbid, art in data.get("albums", {}).items():
for mbid, images in data.get("albums", {}).items():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why was this renamed from art to images ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

_utils.art is now imported, so this line triggers a variable-shadowing lint. I changed the loop variable name so as not to add to the number of linter warnings.

Comment thread beetsplug/fetchart.py Outdated
Comment thread docs/plugins/embedart.rst Outdated
Comment thread test/plugins/test_art.py
Comment on lines +357 to +358
for album in self.albums:
candidate = next(source.get(album, settings, None))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need to check every album? Would it be enough to get the first candidate instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This does get the first candidate for each album (next()) created in setup_beets(), but loops over all the albums to test embedded art extraction in all of the media formats. I was going to use pytest parameterization when I first wrote this, but it ended up being less complex code to just create mock albums for each format, IIRC.

For test safety to ensure no changes cause tests to make
real, unmocked requests for cover art.
"""
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we actually want to make real requests here?

Suggested change
return
yield

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There is no setup or teardown in this fixture, so yield is unnecessary, and it triggers the lint No teardown in fixture... use 'return' instead of 'yield'.

We don't want to make make real requests in test_fetchart.py, because all its tests are of the import and fetchart CLI logic of the plugin, so we want to fail a test if we've accidentally failed to mock something. The real art fetching tests are in test_art.py.

@overhacked
overhacked force-pushed the overhacked/fetchart_embedded branch 2 times, most recently from 1bfaee4 to 85d67e2 Compare August 1, 2026 01:39
Comment thread beetsplug/fetchart.py Outdated
Add `embedded` source to extract embedded art from files. Add
`skip_embedded` option to detect embedded art and skip fetching from
other sources (if extracting isn't the desired end state).

If `skip_embedded=yes`, then files with embedded art are considered "done" and
skipped by FetchArt. If the `embedded` source is enabled, then embedded
artwork is always extracted. The two settings are independent of each
other.

Fix variable shadowing lint due to added import of `_utils.art`.

Signed-off-by: Ross Williams <ross@ross-williams.net>
Add unit tests for Embedded source of FetchArt plugin.
Add integration tests for FetchArt plugin's handling of files with
embedded artwork.

Signed-off-by: Ross Williams <ross@ross-williams.net>
Signed-off-by: Ross Williams <ross@ross-williams.net>
Signed-off-by: Ross Williams <ross@ross-williams.net>
Signed-off-by: Ross Williams <ross@ross-williams.net>
Signed-off-by: Ross Williams <ross@ross-williams.net>
@overhacked
overhacked force-pushed the overhacked/fetchart_embedded branch from cab47f9 to fac8012 Compare August 1, 2026 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fetchart fetchart plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fetchart: Extract embedded art

4 participants