Merge pull request #2258 from michaelbub/master

sanitize playlist names
This commit is contained in:
Adrian Sampson 2016-11-11 19:59:32 -05:00
commit 790a40dd25
3 changed files with 15 additions and 7 deletions

View file

@ -20,7 +20,8 @@ from __future__ import division, absolute_import, print_function
from beets.plugins import BeetsPlugin
from beets import ui
from beets.util import mkdirall, normpath, syspath, bytestring_path
from beets.util import (mkdirall, normpath, sanitize_path, syspath,
bytestring_path)
from beets.library import Item, Album, parse_query_string
from beets.dbcore import OrQuery
from beets.dbcore.query import MultipleSort, ParsingError
@ -187,6 +188,7 @@ class SmartPlaylistPlugin(BeetsPlugin):
# the items and generate the correct m3u file names.
for item in items:
m3u_name = item.evaluate_template(name, True)
m3u_name = sanitize_path(m3u_name, lib.replacements)
if m3u_name not in m3us:
m3us[m3u_name] = []
item_path = item.path

View file

@ -32,6 +32,8 @@ Deprecated configuration optional removals:
The are a couple of small new features:
* :doc:`/plugins/smartplaylist`: Playlist names will be sanitized to
ensure valid filenames. :bug:`2258`
* :doc:`/plugins/mpdupdate`, :doc:`/plugins/mpdstats`: When the ``host`` option
is not set, these plugins will now look for the ``$MPD_HOST`` environment
variable before falling back to ``localhost``. Thanks to :user:`tarruda`.

View file

@ -25,7 +25,7 @@ from beetsplug.smartplaylist import SmartPlaylistPlugin
from beets.library import Item, Album, parse_query_string
from beets.dbcore import OrQuery
from beets.dbcore.query import NullSort, MultipleSort, FixedFieldSort
from beets.util import syspath, bytestring_path, py3_path
from beets.util import syspath, bytestring_path, py3_path, CHAR_REPLACE
from beets.ui import UserError
from beets import config
@ -150,13 +150,17 @@ class SmartPlaylistTest(unittest.TestCase):
spl = SmartPlaylistPlugin()
i = Mock(path=b'/tagada.mp3')
i.evaluate_template.side_effect = lambda x, _: x
q = Mock()
a_q = Mock()
i.evaluate_template.side_effect = \
lambda pl, _: pl.replace(b'$title', b'ta:ga:da').decode()
lib = Mock()
lib.replacements = CHAR_REPLACE
lib.items.return_value = [i]
lib.albums.return_value = []
pl = b'my_playlist.m3u', (q, None), (a_q, None)
q = Mock()
a_q = Mock()
pl = b'$title-my<playlist>.m3u', (q, None), (a_q, None)
spl._matched_playlists = [pl]
dir = bytestring_path(mkdtemp())
@ -171,7 +175,7 @@ class SmartPlaylistTest(unittest.TestCase):
lib.items.assert_called_once_with(q, None)
lib.albums.assert_called_once_with(a_q, None)
m3u_filepath = path.join(dir, pl[0])
m3u_filepath = path.join(dir, b'ta_ga_da-my_playlist_.m3u')
self.assertTrue(path.exists(m3u_filepath))
with open(syspath(m3u_filepath), 'rb') as f:
content = f.read()