Change the parameter name to omit_single_disc (vs previously zero_disc_if_single_disc)
Add return of 'fields_set' so that, if triggered by the command line `beets zero`, it will still effect the item.write.
Added tests.
Adds a zero_disc_number_if_single_disc boolean to the zero plugin for writing to files. Adds the logic that, if disctotal is set and there is only one disc in disctotal, that the disc is not set.
This keeps tags cleaner, only using disc on multi-disc albums. The disctotal is not touched, particularly as this is not usually displayed in most clients.
The field is removed only for writing the tags, but the disc number is maintained in the database to avoid breaking anything that may depend on a disc number or avoid possible loops or failed logic.
This PR moves the `vfs.py` module, which is only used by plugins, to
avoid polluting the main beets namespace. Also exposes the `vfs` and
`art` module from beets with a deprecation warning.
Prevents this crash:
```
$ beet import ~/Music/Music/_/[1405]/00.mp3
Traceback (most recent call last):
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/bin/.beet-wrapped", line 9, in <module>
sys.exit(main())
~~~~^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/ui/__init__.py", line 1859, in main
_raw_main(args)
~~~~~~~~~^^^^^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/ui/__init__.py", line 1838, in _raw_main
subcommand.func(lib, suboptions, subargs)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/ui/commands.py", line 1390, in import_func
import_files(lib, byte_paths, query)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/ui/commands.py", line 1330, in import_files
session.run()
~~~~~~~~~~~^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/importer/session.py", line 234, in run
pl.run_parallel(QUEUE_SIZE)
~~~~~~~~~~~~~~~^^^^^^^^^^^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/util/pipeline.py", line 471, in run_parallel
raise exc_info[1].with_traceback(exc_info[2])
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/util/pipeline.py", line 336, in run
out = self.coro.send(msg)
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/util/pipeline.py", line 219, in coro
func(*(args + (task,)))
~~~~^^^^^^^^^^^^^^^^^^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/importer/stages.py", line 141, in lookup_candidates
plugins.send("import_task_start", session=session, task=task)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/plugins.py", line 505, in send
result = handler(**arguments)
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/plugins.py", line 200, in wrapper
return func(*args, **kwargs)
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beetsplug/fromfilename.py", line 165, in filename_task
apply_matches(d, self._log)
~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beetsplug/fromfilename.py", line 124, in apply_matches
item.title = str(d[item][title_field])
~~~~~~~^^^^^^^^^^^^^
KeyError: 'title'
```
experimental, even though a tag last.fm very often returns (in top 20
tag charts!), it is too broad of a term to be pinned downed with any
particular genre, thus can't really be used for canonicalization.
Fixes to the beets default tree and whitlist files I collected over the
years; Includes Tags last.fm returns quite often; Also the
chart.getTopTags API endpoint was checked to make sure the top 100
charts are included in beets default tree and whitelist.
instead of codecs.open(), which most probably is a relict of beets' Python2/3 compatibility area.
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
To ensure proper fallback to the next stage, in each stage we do a full
combine/resolve/log.
Also we directly return if have satisfied results. As a bonus this
improves readability.
Some duplicate code on the label magic though...
- Remove "early whitelist check", since it breaks canonicalization of
actually unwanted genres (not whitelisted) resolving "up" to parent
genres.
- Remove the filter_valid_genres method entirely and get back to inline
list comprehensions. The caveat is that None genres are not catched
that way (see below, should be one of the last functions that finally
returns lists only)
- Along the way, fix _last_lookup's rearly return to empty list instead
of None.