diff --git a/test/plugins/test_playlist.py b/test/plugins/test_playlist.py index 02c8cf6aa..ecdeb49c8 100644 --- a/test/plugins/test_playlist.py +++ b/test/plugins/test_playlist.py @@ -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