mirror of
https://github.com/beetbox/beets.git
synced 2026-07-22 03:17:26 -04:00
Merge branch 'master' into overhacked/fix_log_line_numbers
This commit is contained in:
@@ -1,55 +1,61 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from shlex import quote
|
||||
|
||||
import beets
|
||||
from beets.test import _common
|
||||
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 = os.path.expanduser(os.path.join("~", "Music"))
|
||||
self.music_dir = (Path("~") / "Music").expanduser()
|
||||
|
||||
i1 = _common.item()
|
||||
i1.path = beets.util.normpath(
|
||||
os.path.join(self.music_dir, "a", "b", "c.mp3")
|
||||
)
|
||||
i1.title = "some item"
|
||||
i1.album = "some album"
|
||||
self.lib.add(i1)
|
||||
self.lib.add_album([i1])
|
||||
|
||||
i2 = _common.item()
|
||||
i2.path = beets.util.normpath(
|
||||
os.path.join(self.music_dir, "d", "e", "f.mp3")
|
||||
)
|
||||
i2.title = "another item"
|
||||
i2.album = "another album"
|
||||
self.lib.add(i2)
|
||||
self.lib.add_album([i2])
|
||||
|
||||
i3 = _common.item()
|
||||
i3.path = beets.util.normpath(
|
||||
os.path.join(self.music_dir, "x", "y", "z.mp3")
|
||||
)
|
||||
i3.title = "yet another item"
|
||||
i3.album = "yet another album"
|
||||
self.lib.add(i3)
|
||||
self.lib.add_album([i3])
|
||||
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"] = self.music_dir
|
||||
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
|
||||
|
||||
@@ -61,7 +67,7 @@ class PlaylistQueryTest:
|
||||
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(os.path.join(self.playlist_dir, 'absolute.m3u'))}"
|
||||
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"}
|
||||
|
||||
@@ -71,7 +77,7 @@ class PlaylistQueryTest:
|
||||
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(os.path.join(self.playlist_dir, 'relative.m3u'))}"
|
||||
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"}
|
||||
|
||||
@@ -81,113 +87,43 @@ class PlaylistQueryTest:
|
||||
assert set(results) == set()
|
||||
|
||||
def test_path_query_with_nonexisting_playlist(self):
|
||||
q = f"playlist:{os.path.join(self.playlist_dir, 'nonexisting.m3u')!r}"
|
||||
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):
|
||||
with open(os.path.join(self.playlist_dir, "absolute.m3u"), "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
os.path.join(self.music_dir, "a", "b", "c.mp3") + "\n",
|
||||
os.path.join(self.music_dir, "d", "e", "f.mp3") + "\n",
|
||||
os.path.join(self.music_dir, "nonexisting.mp3") + "\n",
|
||||
]
|
||||
)
|
||||
|
||||
with open(os.path.join(self.playlist_dir, "relative.m3u"), "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
os.path.join("a", "b", "c.mp3") + "\n",
|
||||
os.path.join("d", "e", "f.mp3") + "\n",
|
||||
"nonexisting.mp3\n",
|
||||
]
|
||||
)
|
||||
|
||||
self.config["playlist"]["relative_to"] = "library"
|
||||
|
||||
|
||||
class PlaylistTestRelativeToDir(PlaylistQueryTest, PlaylistTestCase):
|
||||
def setup_test(self):
|
||||
with open(os.path.join(self.playlist_dir, "absolute.m3u"), "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
os.path.join(self.music_dir, "a", "b", "c.mp3") + "\n",
|
||||
os.path.join(self.music_dir, "d", "e", "f.mp3") + "\n",
|
||||
os.path.join(self.music_dir, "nonexisting.mp3") + "\n",
|
||||
]
|
||||
)
|
||||
|
||||
with open(os.path.join(self.playlist_dir, "relative.m3u"), "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
os.path.join("a", "b", "c.mp3") + "\n",
|
||||
os.path.join("d", "e", "f.mp3") + "\n",
|
||||
"nonexisting.mp3\n",
|
||||
]
|
||||
)
|
||||
|
||||
self.config["playlist"]["relative_to"] = self.music_dir
|
||||
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):
|
||||
with open(os.path.join(self.playlist_dir, "absolute.m3u"), "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
os.path.join(self.music_dir, "a", "b", "c.mp3") + "\n",
|
||||
os.path.join(self.music_dir, "d", "e", "f.mp3") + "\n",
|
||||
os.path.join(self.music_dir, "nonexisting.mp3") + "\n",
|
||||
]
|
||||
)
|
||||
|
||||
with open(os.path.join(self.playlist_dir, "relative.m3u"), "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
os.path.relpath(
|
||||
os.path.join(self.music_dir, "a", "b", "c.mp3"),
|
||||
start=self.playlist_dir,
|
||||
)
|
||||
+ "\n",
|
||||
os.path.relpath(
|
||||
os.path.join(self.music_dir, "d", "e", "f.mp3"),
|
||||
start=self.playlist_dir,
|
||||
)
|
||||
+ "\n",
|
||||
os.path.relpath(
|
||||
os.path.join(self.music_dir, "nonexisting.mp3"),
|
||||
start=self.playlist_dir,
|
||||
)
|
||||
+ "\n",
|
||||
]
|
||||
)
|
||||
|
||||
self.config["playlist"]["relative_to"] = "playlist"
|
||||
self.config["playlist"]["playlist_dir"] = str(self.playlist_dir)
|
||||
|
||||
|
||||
class PlaylistUpdateTest:
|
||||
def setup_test(self):
|
||||
with open(os.path.join(self.playlist_dir, "absolute.m3u"), "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
os.path.join(self.music_dir, "a", "b", "c.mp3") + "\n",
|
||||
os.path.join(self.music_dir, "d", "e", "f.mp3") + "\n",
|
||||
os.path.join(self.music_dir, "nonexisting.mp3") + "\n",
|
||||
]
|
||||
)
|
||||
|
||||
with open(os.path.join(self.playlist_dir, "relative.m3u"), "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
os.path.join("a", "b", "c.mp3") + "\n",
|
||||
os.path.join("d", "e", "f.mp3") + "\n",
|
||||
"nonexisting.mp3\n",
|
||||
]
|
||||
)
|
||||
|
||||
self.config["playlist"]["auto"] = True
|
||||
self.config["playlist"]["relative_to"] = "library"
|
||||
|
||||
@@ -195,91 +131,75 @@ class PlaylistUpdateTest:
|
||||
class PlaylistTestItemMoved(PlaylistUpdateTest, PlaylistTestCase):
|
||||
def test_item_moved(self):
|
||||
# Emit item_moved event for an item that is in a playlist
|
||||
results = self.lib.items(
|
||||
f"path:{quote(os.path.join(self.music_dir, 'd', 'e', 'f.mp3'))}"
|
||||
)
|
||||
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=beets.util.bytestring_path(
|
||||
os.path.join(self.music_dir, "g", "h", "i.mp3")
|
||||
),
|
||||
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(os.path.join(self.music_dir, 'x', 'y', 'z.mp3'))}"
|
||||
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=beets.util.bytestring_path(
|
||||
os.path.join(self.music_dir, "u", "v", "w.mp3")
|
||||
),
|
||||
destination=os.fsencode(self.music_dir / self.w_track_path),
|
||||
)
|
||||
|
||||
# Emit cli_exit event
|
||||
beets.plugins.send("cli_exit", lib=self.lib)
|
||||
|
||||
# Check playlist with absolute paths
|
||||
playlist_path = os.path.join(self.playlist_dir, "absolute.m3u")
|
||||
with open(playlist_path) as f:
|
||||
lines = [line.strip() for line in f.readlines()]
|
||||
|
||||
assert lines == [
|
||||
os.path.join(self.music_dir, "a", "b", "c.mp3"),
|
||||
os.path.join(self.music_dir, "g", "h", "i.mp3"),
|
||||
os.path.join(self.music_dir, "nonexisting.mp3"),
|
||||
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
|
||||
playlist_path = os.path.join(self.playlist_dir, "relative.m3u")
|
||||
with open(playlist_path) as f:
|
||||
lines = [line.strip() for line in f.readlines()]
|
||||
|
||||
assert lines == [
|
||||
os.path.join("a", "b", "c.mp3"),
|
||||
os.path.join("g", "h", "i.mp3"),
|
||||
"nonexisting.mp3",
|
||||
]
|
||||
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
|
||||
results = self.lib.items(
|
||||
f"path:{quote(os.path.join(self.music_dir, 'd', 'e', 'f.mp3'))}"
|
||||
)
|
||||
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
|
||||
results = self.lib.items(
|
||||
f"path:{quote(os.path.join(self.music_dir, 'x', 'y', 'z.mp3'))}"
|
||||
)
|
||||
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
|
||||
playlist_path = os.path.join(self.playlist_dir, "absolute.m3u")
|
||||
with open(playlist_path) as f:
|
||||
lines = [line.strip() for line in f.readlines()]
|
||||
|
||||
assert lines == [
|
||||
os.path.join(self.music_dir, "a", "b", "c.mp3"),
|
||||
os.path.join(self.music_dir, "nonexisting.mp3"),
|
||||
]
|
||||
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
|
||||
playlist_path = os.path.join(self.playlist_dir, "relative.m3u")
|
||||
with open(playlist_path) as f:
|
||||
lines = [line.strip() for line in f.readlines()]
|
||||
|
||||
assert lines == [os.path.join("a", "b", "c.mp3"), "nonexisting.mp3"]
|
||||
lines = list(
|
||||
map(Path, self.relative_playlist_path.read_text().splitlines())
|
||||
)
|
||||
assert lines == expected_paths
|
||||
|
||||
Reference in New Issue
Block a user