Update vendored beets to 1.6.0

Updates colorama to 0.4.6
Adds confuse version 1.7.0
Updates jellyfish to 0.9.0
Adds mediafile 0.10.1
Updates munkres to 1.1.4
Updates musicbrainzngs to 0.7.1
Updates mutagen to 1.46.0
Updates pyyaml to 6.0
Updates unidecode to 1.3.6
This commit is contained in:
Labrys of Knossos 2022-11-28 18:02:40 -05:00
commit 56c6773c6b
385 changed files with 25143 additions and 18080 deletions

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# This file is part of beets.
# Copyright 2016, Dang Mai <contact@dangmai.net>.
#
@ -16,30 +15,38 @@
"""Generates smart playlists based on beets queries.
"""
from __future__ import division, absolute_import, print_function
from beets.plugins import BeetsPlugin
from beets import ui
from beets.util import (mkdirall, normpath, sanitize_path, syspath,
bytestring_path)
bytestring_path, path_as_posix)
from beets.library import Item, Album, parse_query_string
from beets.dbcore import OrQuery
from beets.dbcore.query import MultipleSort, ParsingError
import os
import six
try:
from urllib.request import pathname2url
except ImportError:
# python2 is a bit different
from urllib import pathname2url
class SmartPlaylistPlugin(BeetsPlugin):
def __init__(self):
super(SmartPlaylistPlugin, self).__init__()
super().__init__()
self.config.add({
'relative_to': None,
'playlist_dir': u'.',
'playlist_dir': '.',
'auto': True,
'playlists': []
'playlists': [],
'forward_slash': False,
'prefix': '',
'urlencode': False,
})
self.config['prefix'].redact = True # May contain username/password.
self._matched_playlists = None
self._unmatched_playlists = None
@ -49,8 +56,8 @@ class SmartPlaylistPlugin(BeetsPlugin):
def commands(self):
spl_update = ui.Subcommand(
'splupdate',
help=u'update the smart playlists. Playlist names may be '
u'passed as arguments.'
help='update the smart playlists. Playlist names may be '
'passed as arguments.'
)
spl_update.func = self.update_cmd
return [spl_update]
@ -61,14 +68,14 @@ class SmartPlaylistPlugin(BeetsPlugin):
args = set(ui.decargs(args))
for a in list(args):
if not a.endswith(".m3u"):
args.add("{0}.m3u".format(a))
args.add(f"{a}.m3u")
playlists = set((name, q, a_q)
for name, q, a_q in self._unmatched_playlists
if name in args)
playlists = {(name, q, a_q)
for name, q, a_q in self._unmatched_playlists
if name in args}
if not playlists:
raise ui.UserError(
u'No playlist matching any of {0} found'.format(
'No playlist matching any of {} found'.format(
[name for name, _, _ in self._unmatched_playlists])
)
@ -81,7 +88,7 @@ class SmartPlaylistPlugin(BeetsPlugin):
def build_queries(self):
"""
Instanciate queries for the playlists.
Instantiate queries for the playlists.
Each playlist has 2 queries: one or items one for albums, each with a
sort. We must also remember its name. _unmatched_playlists is a set of
@ -99,22 +106,23 @@ class SmartPlaylistPlugin(BeetsPlugin):
for playlist in self.config['playlists'].get(list):
if 'name' not in playlist:
self._log.warning(u"playlist configuration is missing name")
self._log.warning("playlist configuration is missing name")
continue
playlist_data = (playlist['name'],)
try:
for key, Model in (('query', Item), ('album_query', Album)):
for key, model_cls in (('query', Item),
('album_query', Album)):
qs = playlist.get(key)
if qs is None:
query_and_sort = None, None
elif isinstance(qs, six.string_types):
query_and_sort = parse_query_string(qs, Model)
elif isinstance(qs, str):
query_and_sort = parse_query_string(qs, model_cls)
elif len(qs) == 1:
query_and_sort = parse_query_string(qs[0], Model)
query_and_sort = parse_query_string(qs[0], model_cls)
else:
# multiple queries and sorts
queries, sorts = zip(*(parse_query_string(q, Model)
queries, sorts = zip(*(parse_query_string(q, model_cls)
for q in qs))
query = OrQuery(queries)
final_sorts = []
@ -135,7 +143,7 @@ class SmartPlaylistPlugin(BeetsPlugin):
playlist_data += (query_and_sort,)
except ParsingError as exc:
self._log.warning(u"invalid query in playlist {}: {}",
self._log.warning("invalid query in playlist {}: {}",
playlist['name'], exc)
continue
@ -156,14 +164,14 @@ class SmartPlaylistPlugin(BeetsPlugin):
n, (q, _), (a_q, _) = playlist
if self.matches(model, q, a_q):
self._log.debug(
u"{0} will be updated because of {1}", n, model)
"{0} will be updated because of {1}", n, model)
self._matched_playlists.add(playlist)
self.register_listener('cli_exit', self.update_playlists)
self._unmatched_playlists -= self._matched_playlists
def update_playlists(self, lib):
self._log.info(u"Updating {0} smart playlists...",
self._log.info("Updating {0} smart playlists...",
len(self._matched_playlists))
playlist_dir = self.config['playlist_dir'].as_filename()
@ -177,7 +185,7 @@ class SmartPlaylistPlugin(BeetsPlugin):
for playlist in self._matched_playlists:
name, (query, q_sort), (album_query, a_q_sort) = playlist
self._log.debug(u"Creating playlist {0}", name)
self._log.debug("Creating playlist {0}", name)
items = []
if query:
@ -199,6 +207,7 @@ class SmartPlaylistPlugin(BeetsPlugin):
if item_path not in m3us[m3u_name]:
m3us[m3u_name].append(item_path)
prefix = bytestring_path(self.config['prefix'].as_str())
# Write all of the accumulated track lists to files.
for m3u in m3us:
m3u_path = normpath(os.path.join(playlist_dir,
@ -206,6 +215,10 @@ class SmartPlaylistPlugin(BeetsPlugin):
mkdirall(m3u_path)
with open(syspath(m3u_path), 'wb') as f:
for path in m3us[m3u]:
f.write(path + b'\n')
if self.config['forward_slash'].get():
path = path_as_posix(path)
if self.config['urlencode']:
path = bytestring_path(pathname2url(path))
f.write(prefix + path + b'\n')
self._log.info(u"{0} playlists updated", len(self._matched_playlists))
self._log.info("{0} playlists updated", len(self._matched_playlists))