When checking whether a title or artist contains a feature, it now also
detects them when they are in parentheses or brackets, i.e., "Song Name
(feat. XYZ)" will return true.
- Fix imports
- Fix pytest issues
- Do not assign lambda as variable
- Use isinstance instead of type to check type
- Rename ambiguously named variables
- Name custom errors with Error suffix
and put to use in Spotify plugin.
- Make _get_id() a staticmethod usable from outside a metadata source plugin.
- id_regex now has to be passed as an argument instead of assuming it is
accessible via an instance variable (self.id_regex).
- In the Spotify plugin, import spotify_id_regex from util.id_extractors
- Originally a list of "artists" was generated and joined together to a final
string later.
- This simplifies by concatinating to a final string within the main loop.
- Also this commit gets rid of a mysterious replacement code (` ,' -> ',')
Add an optional argument to MetadataSourcePlugin.get_artist method that enables
making use of a field containing a keyword supposed to be used to combine
artists together into a single string like "Feat.", "And", "Vs." and so on.
In
766c8b190b from [1]
a slight hack was introduced that allowed to add new arguments to
plugin events without breaking legacy plugins that did not feature
those arguments in the signature of their handler functions.
When improving logging management for plugins in
327b62b610 from [2]
this hack was removed, to be restored with
7f34c101d7 from [3]
Now in addition to inspecting the function signature, an assumption is
made about the string message of the TypeError that occurs for legacy
handler functions (namely, that it start with func.__name__).
In Python 3.10, the TypeError uses func.__qualname__ [4], however, due
to the patch [5]. Thus, checking whether the TypeError is due to an
outdated function signature or something internal to the handler fais.
As a fix, instead of using __name__ or __qualname__ depending on Python
version, let's just revert to the old hack from [1], I'm not seeing a
significant advantage in [3]. The latter might be a bit faster since it
doesn't construct a new dict for each call, but only for legacy calls in
the excption handler. I doubt that really matters, and if it does, we
should try to think of a better fix than inspecting error messages with
no guarantees about their content in such a central place in the code.
[1] https://github.com/beetbox/beets/pull/652
[2] https://github.com/beetbox/beets/pull/1320
[3] https://github.com/beetbox/beets/pull/1359
[4] https://docs.python.org/3.10/glossary.html#term-qualified-name
[5] https://bugs.python.org/issue40679
This function is called from library.Item._getters(), making it a hot
path when exporting data. We cache plugin instances but previously we
reran `import` for each module on each call. We now return the cached
values providing a speed boost for `beet export`.
This has a small effect on `beet ls` speed: for me it went 11.00s ->
10.40.
It had a significant effect on `beet export` speed when combined with
https://github.com/beetbox/beets/pull/3762/.
Before:
$ time /home/sam/.local/bin/beet 'export' '--library' '--format' 'jsonlines' '--include-keys' 'artist,title,path,mb_artistid,mb_trackid' 'artist+ title+' > /dev/null
Executed in 25.13 secs
After:
$ time /home/sam/.local/bin/beet 'export' '--library' '--format' 'jsonlines' '--include-keys' 'artist,title,path,mb_artistid,mb_trackid' 'artist+ title+' > /dev/null
Executed in 10.49 secs
An event listener that expects too few arguments won't crash, arguments
will be cut off instead. This restores a backwards-compatibility hack
that was removed in commit 327b62b6.
'verbose' is now an int and not a boolean. '-v' is level 1, '-vv' level
2. In the configuration it can be set with 'verbose: 1' or 'verbose: 2'.
Improve #1244: auditing current log levels of plugins remains.
Delete the remaining usages of BeetsPlugin.listen().
Since BeetsPlugin.listeners are wrapped by a loglevel-setting function,
we cannot easily check their unicity anymore.
BeetsPlugin._raw_listeners set holds the raw listeners.
Legacy plugins that did not handle enough arguments in their listenings
functions may break: dedicated code is now deleted for it would not work
with the decorated listeners.
Tests got fixed. Some modifications were done empirically: if it passes
then it's okay.
Listeners get logging level modulations, like import_stages already did.
Add extensive tests:
- explicit plugin commands are logged like core beets (INFO or DEBUG)
- import stages are more silent
- event listeners are like import stages
Delete @BeetsPlugin.listen decorator since listeners need plugin instance
context to set its logging level.
Improve #1244. Next is multiple verbosity levels.
Include import of __future__ features division, absolute_imports and
print_function everywhere. Don't add unicode_literals yet for it is
harder to convert.
Goal is smoothing the transition to python 3.
We now add the plugin name to messages in verbose mode. This may not be the
best final policy, but it does help make the output more readable when many
plugins are talking at once.
This restores the -v flag affecting plugins. By default, plugin loggers use
the NOTSET level, which just reuses the base `beets` logger level. The level
is only auto-adjusted for the importer when not in verbose mode.
Breaking changes: plugins should set set _import_stages instead of
import_stages. From outside the latter is replaced by import_stages().
This is because it is now wrapped with log level-getting & -setting
statements.
Following the convention of the other field sets and such. This helps avoid
any confusion with user-specified fields (although it's unlikely people will
want to name a flexible field "media_fields" :).