mirror of
https://github.com/beetbox/beets.git
synced 2026-07-22 04:26:50 -04:00
206 lines
7.1 KiB
Python
206 lines
7.1 KiB
Python
import os
|
|
from pathlib import Path
|
|
from shlex import quote
|
|
|
|
import beets
|
|
from beets.test.helper import PluginTestCase
|
|
|
|
|
|
class PlaylistTestCase(PluginTestCase):
|
|
plugin = "playlist"
|
|
preload_plugin = False
|
|
c_track_path = Path("a") / "b" / "c.mp3"
|
|
f_track_path = Path("d") / "e" / "f.mp3"
|
|
i_track_path = Path("g") / "h" / "i.mp3"
|
|
w_track_path = Path("u") / "v" / "w.mp3"
|
|
z_track_path = Path("x") / "y" / "z.mp3"
|
|
nonexisting_track_path = Path("nonexisting.mp3")
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
|
|
self.music_dir = (Path("~") / "Music").expanduser()
|
|
|
|
for p, title, album in [
|
|
(self.c_track_path, "some item", "some album"),
|
|
(self.f_track_path, "another item", "another album"),
|
|
(self.z_track_path, "yet another item", "yet another album"),
|
|
]:
|
|
self.add_album(path=self.music_dir / p, title=title, album=album)
|
|
|
|
self.playlist_dir = self.temp_dir_path / "playlists"
|
|
self.playlist_dir.mkdir(parents=True, exist_ok=True)
|
|
self.config["directory"] = str(self.music_dir)
|
|
self.config["playlist"]["playlist_dir"] = str(self.playlist_dir)
|
|
self.absolute_playlist_path = self.playlist_dir / "absolute.m3u"
|
|
self.relative_playlist_path = self.playlist_dir / "relative.m3u"
|
|
|
|
self.write_absolute_playlist()
|
|
self.write_relative_playlist()
|
|
self.setup_test()
|
|
self.load_plugins()
|
|
|
|
def write_absolute_playlist(self):
|
|
lines = [
|
|
self.music_dir / self.c_track_path,
|
|
self.music_dir / self.f_track_path,
|
|
self.music_dir / self.nonexisting_track_path,
|
|
]
|
|
self.absolute_playlist_path.write_text("\n".join(map(str, lines)))
|
|
|
|
def write_relative_playlist(self):
|
|
lines = [
|
|
self.c_track_path,
|
|
self.f_track_path,
|
|
self.nonexisting_track_path,
|
|
]
|
|
self.relative_playlist_path.write_text("\n".join(map(str, lines)))
|
|
|
|
def setup_test(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
class PlaylistQueryTest:
|
|
def test_name_query_with_absolute_paths_in_playlist(self):
|
|
q = "playlist:absolute"
|
|
results = self.lib.items(q)
|
|
assert {i.title for i in results} == {"some item", "another item"}
|
|
|
|
def test_path_query_with_absolute_paths_in_playlist(self):
|
|
q = f"playlist:{quote(str(self.absolute_playlist_path))}"
|
|
results = self.lib.items(q)
|
|
assert {i.title for i in results} == {"some item", "another item"}
|
|
|
|
def test_name_query_with_relative_paths_in_playlist(self):
|
|
q = "playlist:relative"
|
|
results = self.lib.items(q)
|
|
assert {i.title for i in results} == {"some item", "another item"}
|
|
|
|
def test_path_query_with_relative_paths_in_playlist(self):
|
|
q = f"playlist:{quote(str(self.relative_playlist_path))}"
|
|
results = self.lib.items(q)
|
|
assert {i.title for i in results} == {"some item", "another item"}
|
|
|
|
def test_name_query_with_nonexisting_playlist(self):
|
|
q = "playlist:nonexisting"
|
|
results = self.lib.items(q)
|
|
assert set(results) == set()
|
|
|
|
def test_path_query_with_nonexisting_playlist(self):
|
|
q = f"playlist:{quote(str(self.nonexisting_track_path))}"
|
|
results = self.lib.items(q)
|
|
assert set(results) == set()
|
|
|
|
|
|
class PlaylistTestRelativeToLib(PlaylistQueryTest, PlaylistTestCase):
|
|
def setup_test(self):
|
|
self.config["playlist"]["relative_to"] = "library"
|
|
|
|
|
|
class PlaylistTestRelativeToDir(PlaylistQueryTest, PlaylistTestCase):
|
|
def setup_test(self):
|
|
self.config["playlist"]["relative_to"] = str(self.music_dir)
|
|
|
|
|
|
class PlaylistTestRelativeToPls(PlaylistQueryTest, PlaylistTestCase):
|
|
def write_relative_playlist(self):
|
|
lines = [
|
|
os.path.relpath(
|
|
self.music_dir / self.c_track_path, self.playlist_dir
|
|
),
|
|
os.path.relpath(
|
|
self.music_dir / self.f_track_path, self.playlist_dir
|
|
),
|
|
os.path.relpath(
|
|
self.music_dir / self.nonexisting_track_path, self.playlist_dir
|
|
),
|
|
]
|
|
self.relative_playlist_path.write_text("\n".join(lines) + "\n")
|
|
|
|
def setup_test(self):
|
|
self.config["playlist"]["relative_to"] = "playlist"
|
|
self.config["playlist"]["playlist_dir"] = str(self.playlist_dir)
|
|
|
|
|
|
class PlaylistUpdateTest:
|
|
def setup_test(self):
|
|
self.config["playlist"]["auto"] = True
|
|
self.config["playlist"]["relative_to"] = "library"
|
|
|
|
|
|
class PlaylistTestItemMoved(PlaylistUpdateTest, PlaylistTestCase):
|
|
def test_item_moved(self):
|
|
# Emit item_moved event for an item that is in a playlist
|
|
q = f"path:{quote(str(self.music_dir / self.f_track_path))}"
|
|
results = self.lib.items(q)
|
|
item = results[0]
|
|
beets.plugins.send(
|
|
"item_moved",
|
|
item=item,
|
|
source=item.path,
|
|
destination=os.fsencode(self.music_dir / self.i_track_path),
|
|
)
|
|
|
|
# Emit item_moved event for an item that is not in a playlist
|
|
results = self.lib.items(
|
|
f"path:{quote(str(self.music_dir / self.z_track_path))}"
|
|
)
|
|
item = results[0]
|
|
beets.plugins.send(
|
|
"item_moved",
|
|
item=item,
|
|
source=item.path,
|
|
destination=os.fsencode(self.music_dir / self.w_track_path),
|
|
)
|
|
|
|
# Emit cli_exit event
|
|
beets.plugins.send("cli_exit", lib=self.lib)
|
|
|
|
expected_paths = [
|
|
self.c_track_path,
|
|
self.i_track_path,
|
|
self.nonexisting_track_path,
|
|
]
|
|
# Check playlist with absolute paths
|
|
lines = list(
|
|
map(Path, self.absolute_playlist_path.read_text().splitlines())
|
|
)
|
|
assert lines == [self.music_dir / p for p in expected_paths]
|
|
|
|
# Check playlist with relative paths
|
|
lines = list(
|
|
map(Path, self.relative_playlist_path.read_text().splitlines())
|
|
)
|
|
assert lines == expected_paths
|
|
|
|
|
|
class PlaylistTestItemRemoved(PlaylistUpdateTest, PlaylistTestCase):
|
|
def test_item_removed(self):
|
|
# Emit item_removed event for an item that is in a playlist
|
|
q = f"path:{quote(str(self.music_dir / self.f_track_path))}"
|
|
results = self.lib.items(q)
|
|
item = results[0]
|
|
beets.plugins.send("item_removed", item=item)
|
|
|
|
# Emit item_removed event for an item that is not in a playlist
|
|
q = f"path:{quote(str(self.music_dir / self.z_track_path))}"
|
|
results = self.lib.items(q)
|
|
item = results[0]
|
|
beets.plugins.send("item_removed", item=item)
|
|
|
|
# Emit cli_exit event
|
|
beets.plugins.send("cli_exit", lib=self.lib)
|
|
|
|
expected_paths = [self.c_track_path, self.nonexisting_track_path]
|
|
# Check playlist with absolute paths
|
|
lines = list(
|
|
map(Path, self.absolute_playlist_path.read_text().splitlines())
|
|
)
|
|
assert lines == [self.music_dir / p for p in expected_paths]
|
|
|
|
# Check playlist with relative paths
|
|
lines = list(
|
|
map(Path, self.relative_playlist_path.read_text().splitlines())
|
|
)
|
|
assert lines == expected_paths
|