Skip to content

chroma: gate candidates on musicbrainz plugin being enabled#6532

Open
AnonymousAAArdvark wants to merge 2 commits intobeetbox:masterfrom
AnonymousAAArdvark:fix/chroma-gate-musicbrainz-simple
Open

chroma: gate candidates on musicbrainz plugin being enabled#6532
AnonymousAAArdvark wants to merge 2 commits intobeetbox:masterfrom
AnonymousAAArdvark:fix/chroma-gate-musicbrainz-simple

Conversation

@AnonymousAAArdvark
Copy link
Copy Markdown

Summary

Fixes #6212. Split out from #6522 per @semohr's suggestion.

The chroma plugin unconditionally instantiated its own private
MusicBrainzPlugin instance and called album_for_id /
track_for_id on it regardless of the user's plugin configuration.
This meant MusicBrainz-sourced candidates appeared during tagging even
when the user had not enabled the musicbrainz plugin.

This PR replaces the direct instantiation with a lookup through the
metadata-source registry (get_metadata_source("musicbrainz")).
When the musicbrainz plugin is not loaded, both candidates and
item_candidates short-circuit and return empty. Acoustid
fingerprinting itself is unaffected — acoustid_id and
acoustid_fingerprint fields are still populated as before.

Side-effect fix

The previous cached_property mb = MusicBrainzPlugin() pattern
created a second instance outside the plugin registry. This bypassed
any plugin that swaps the musicbrainz instance at runtime (e.g.
mbpseudo). Routing through get_metadata_source fixes this —
chroma now uses the same shared instance as the rest of beets.

Scope

This PR is intentionally scoped to the gating fix only. The richer
cross-reference routing (extracting Spotify/Discogs/etc. IDs from
MusicBrainz url-relations and dispatching to enabled external
plugins) is being developed separately in #6522.

Test plan

  • 4 new tests in test/plugins/test_chroma.py:
    candidates / item_candidates × with / without musicbrainz.
  • 2 existing chromasearch tests still pass.
  • 144 focused regression tests pass (chroma, musicbrainz,
    metadata_plugins, autotag/match, autotag/distance).
  • ruff check + ruff format --check clean.
  • mypy beetsplug/chroma.py clean.
  • sphinx-lint + docstrfmt (Python 3.10) clean.
  • Changelog entry + docs note added.

The chroma plugin uses Acoustid fingerprinting, which returns MusicBrainz
release and recording IDs. It then unconditionally resolved those IDs
through a privately instantiated MusicBrainzPlugin, so MusicBrainz-sourced
candidates appeared during tagging even when the user had not enabled the
musicbrainz plugin.

Replace the direct MusicBrainzPlugin() instantiation with a lookup through
the metadata-source registry via get_metadata_source("musicbrainz"). When
that returns None, short-circuit both candidates() and item_candidates()
to return empty. This also fixes an incidental issue where the private
instance bypassed any plugin that swaps the musicbrainz plugin at runtime
(e.g. mbpseudo).

Acoustid fingerprinting itself is unaffected — acoustid_id and
acoustid_fingerprint item fields are still populated as before.

Fixes beetbox#6212
@AnonymousAAArdvark AnonymousAAArdvark requested a review from a team as a code owner April 12, 2026 16:58
@github-actions github-actions bot added the chroma chroma plugin label Apr 12, 2026
@github-actions github-actions bot added the musicbrainz musicbrainz plugin label Apr 12, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.12%. Comparing base (c6409d2) to head (5425418).
⚠️ Report is 5 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6532      +/-   ##
==========================================
+ Coverage   70.67%   71.12%   +0.44%     
==========================================
  Files         150      150              
  Lines       18918    19130     +212     
  Branches     3078     3081       +3     
==========================================
+ Hits        13371    13606     +235     
+ Misses       4896     4867      -29     
- Partials      651      657       +6     
Files with missing lines Coverage Δ
beetsplug/chroma.py 46.61% <100.00%> (+10.07%) ⬆️

... and 3 files 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.

Copy link
Copy Markdown
Member

@snejus snejus left a comment

Choose a reason for hiding this comment

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

This is great, thanks. Just a pair of small comments.

@snejus
Copy link
Copy Markdown
Member

snejus commented Apr 13, 2026

I think this also fixed another issue related to mbpseudo as well? Is there a reported GitHub issue for that?

metadata_plugins.get_metadata_source.cache_clear()


def _load_plugins(*names: str) -> None:
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.

We should use our common plugin loading infrastructure here.

See

class PluginMixin(ConfigMixin):

- Use @cached_property named `mb` (per snejus/semohr) instead of a
  helper method, reducing the diff relative to the original code
- Move changelog entry to the Unreleased section (per snejus)
- Refactor tests to use PluginMixin from beets.test.helper (per
  semohr) instead of manually managing beets.plugins._instances
Comment on lines +87 to +91
# -----------------------------------------------------------------------------
# Regression tests for issue #6212: chroma must respect which metadata source
# plugins are enabled. When the musicbrainz plugin is not loaded, chroma must
# not produce any MusicBrainz-sourced candidates.
# -----------------------------------------------------------------------------
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.

Is it possible to use a single test class and include this in its docstring?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chroma chroma plugin musicbrainz musicbrainz plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

musicbrainz metadata source is used when the musicbrainz plugin is not activated

3 participants