Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions beetsplug/smartplaylist.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from __future__ import annotations

import os
from shlex import quote as shell_quote
from typing import TYPE_CHECKING, Any, TypeAlias
from urllib.parse import quote
from urllib.request import pathname2url
Expand Down Expand Up @@ -160,8 +161,10 @@ def update_cmd(self, lib: Library, opts: Any, args: list[str]) -> None:
}
if not playlists:
unmatched = [name for name, _, _ in self._unmatched_playlists]
unmatched.sort()
quoted_names = " ".join(shell_quote(name) for name in unmatched)
raise ui.UserError(
f"No playlist matching any of {unmatched} found"
f"No playlist matching any of {quoted_names} found"
)

self._matched_playlists = playlists
Expand Down Expand Up @@ -348,7 +351,7 @@ def update_playlists(self, lib: Library, pretend: bool = False) -> None:

if not pretend:
# Write all of the accumulated track lists to files.
for m3u in m3us:
for m3u, entries in m3us.items():
m3u_path = normpath(
os.path.join(playlist_dir, bytestring_path(m3u))
)
Expand All @@ -364,7 +367,7 @@ def update_playlists(self, lib: Library, pretend: bool = False) -> None:
if extm3u:
keys = self.config["fields"].get(list)
f.write(b"#EXTM3U\n")
for entry in m3us[m3u]:
for entry in entries:
item = entry.item
comment = ""
if extm3u:
Expand Down
4 changes: 4 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ New features
deprecate ``overwrite``.
- :doc:`plugins/autobpm`: The "BPM already exists for item" log message can now
be hidden with the ``--quiet`` flag.
- :doc:`plugins/smartplaylist`: The list of available playlists shown when an
unknown playlist name is passed as an argument is now sorted alphabetically
and printed space-delimited and POSIX shell-quoted when required. This makes
it easier to copy and paste multiple playlists for further use in the shell.

Bug fixes
~~~~~~~~~
Expand Down
17 changes: 17 additions & 0 deletions test/plugins/test_smartplaylist.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,3 +574,20 @@ def test_splupdate(self):
for name in (b"my_playlist.m3u", b"all.m3u"):
with open(path.join(self.temp_dir, name), "rb") as f:
assert f.read() == self.item.path + b"\n"

def test_splupdate_unknown_playlist_error_is_sorted_and_quoted(self):
config["smartplaylist"]["playlists"].set(
[
{"name": "z last.m3u", "query": self.item.title},
{"name": "rock'n roll.m3u", "query": self.item.title},
{"name": "a one.m3u", "query": self.item.title},
]
)

with pytest.raises(UserError) as exc_info:
self.run_with_output("splupdate", "tagada")

assert str(exc_info.value) == (
"No playlist matching any of "
"'a one.m3u' 'rock'\"'\"'n roll.m3u' 'z last.m3u' found"
)
Loading