beetbox / beetbox/beets

`fetchart.ART_SOURCES` does not support item assignment

Open
#5,794 2 comments 0 reactions 0 assignees View on GitHub
fetchart
Dominant language
Python
Stars
15.7k
Forks
2.1k
Avg merge
4d 21h
Merged PRs (30d)
31

Description

### Problem

Running this command in verbose (`-vv`) mode:

```sh
$ beet -vv import -LI 'id::^9664$'
```

Led to this problem:

```
user configuration: /home/sarunas/.config/beets/config.yaml
data directory: /home/sarunas/.config/beets
plugin paths:
fetchart: google: Disabling art source due to missing key
inline: adding item field has_lyrics
inline: adding item field label_or_albumartist
inline: adding item field singleton_track_artist
inline: adding item field track_artist
inline: adding item field album_name
inline: adding item field track_identification
inline: adding item field withdrawn
inline: adding album field label_or_albumartist
inline: adding album field multiple_artists
Sending event: pluginload
Traceback (most recent call last):
File "/home/sarunas/.local/bin/beet", line 5, in
main()
File "/home/sarunas/repo/beets/beets/ui/__init__.py", line 1878, in main
_raw_main(args)
File "/home/sarunas/repo/beets/beets/ui/__init__.py", line 1853, in _raw_main
subcommands, plugins, lib = _setup(options, lib)
File "/home/sarunas/repo/beets/beets/ui/__init__.py", line 1693, in _setup
plugins.send("pluginload")
File "/home/sarunas/repo/beets/beets/plugins.py", line 634, in send
result = handler(**arguments)
File "/home/sarunas/repo/beets/beets/plugins.py", line 206, in wrapper
return func(*args, **kwargs)
File "/home/sarunas/repo/beetcamp/beetsplug/bandcamp/__init__.py", line 178, in loaded
fetchart.ART_SOURCES[self.data_source] = BandcampAlbumArt
TypeError: 'set' object does not support item assignment
```

### Setup

* OS: Arch Linux x86_64 / Linux 6.14.6-arch1-1
* Python version: Python 3.9.20
* beets version: most recent commit on master, 79c87e58
* Turning off plugins made problem go away (yes/no): yes

My configuration (output of `beet config`) is:

Relevant configuration which triggers the error
```yaml
plugins: bandcamp
bandcamp:
art: yes
```

Setting `art` to `no` fixes the issue.
```yaml
plugins: bandcamp
bandcamp:
art: no
```

### Context

Due to lack of an ability for plugins to register their own `fetchart` art sources, `beetcamp` has been relying on [this patch](https://github.com/snejus/beetcamp/blob/64c7afc9d87682fb2b7c9f2deb76525e44afb248/beetsplug/bandcamp/__init__.py#L174) to force its art source in:

```py
class BandcampAlbumArt(..., fetchart.RemoteArtSource):
NAME = "Bandcamp"

def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.config = self._config

def get(self, album: AlbumInfo, *_: Any) -> Iterable[fetchart.Candidate]:
"""Return the url for the cover from the bandcamp album page.

This only returns cover art urls for bandcamp albums (by id).
"""
url = album.mb_albumid
if not self.from_bandcamp(url):
self._info("Not fetching art for a non-bandcamp album URL")
else:
with self.handle_error(url):
if image := self.guru(url).image:
yield self._candidate(
url=image, match=fetchart.Candidate.MATCH_EXACT
)

class BandcampPlugin:
data_source = "bandcamp"

def __init__(self) -> None:
...

if self.config["art"]:
self.register_listener("pluginload", self.loaded)

def loaded(self) -> None:
"""Add our own artsource to the fetchart plugin."""
for plugin in plugins.find_plugins():
if isinstance(plugin, fetchart.FetchArtPlugin):
fetchart.ART_SOURCES[self.data_source] = BandcampAlbumArt
fetchart.SOURCE_NAMES[BandcampAlbumArt] = self.data_source
fetchart.SOURCES_ALL.append(self.data_source)
bandcamp_fetchart = BandcampAlbumArt(self._log, self.config)
plugin.sources = [bandcamp_fetchart, *plugin.sources]
break
```

Seems like these global variables have been adjusted in #5716 which made it explode. I myself rely on this art source every day; I think people who use this plugin generally do, too.

@beetbox/maintainers what do you reckon would be the best way to go about this longer term? I understand this is a private API so I wouldn't expect adjustments to be made in beets source - I'll do it on my end. On the other hand, the fix will involve more of the same - patching internal fetchart API. Have we ever considered making art source registration public?

Contributor guide

Open the contributing guide

Research direction

Start with beetsplug/bandcamp/__init__.py and the fetchart registration globals involved in the traceback, then reproduce the failure with the provided `beet -vv import -LI 'id::^9664$'` command. Done should provide a supported way for the plugin to register its art source without assigning private globals or raising the reported TypeError.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.