`fetchart.ART_SOURCES` does not support item assignment
- 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
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