From f4ee2cb55ee2f3a07ea0e6070a0e3126e12efa07 Mon Sep 17 00:00:00 2001 From: Solomon Victorino Date: Sun, 27 Oct 2024 20:08:01 -0600 Subject: [PATCH] get_playlist: join multiple title runs * Return complete titles when split on time-like strings: ```diff >>> yt.get_playlist("PLaZPMsuQNCsWn0iVMtGbaUXO6z-EdZaZm")["title"] -03 Jan +03 Jan 12:09 ``` * `test_get_playlist`: assert more props have the expected value/shape --- tests/mixins/test_playlists.py | 54 ++++++++++++++++++++++++++------- ytmusicapi/parsers/playlists.py | 2 +- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/tests/mixins/test_playlists.py b/tests/mixins/test_playlists.py index 20dc627c..b0d06f17 100644 --- a/tests/mixins/test_playlists.py +++ b/tests/mixins/test_playlists.py @@ -13,25 +13,57 @@ class TestPlaylists: @pytest.mark.parametrize( - ("test_file", "owned"), + ("test_file", "output"), [ - ("2024_03_get_playlist.json", True), - ("2024_03_get_playlist_public.json", False), - ("2024_07_get_playlist_collaborative.json", True), + ( + "2024_03_get_playlist.json", + { + "id": "PLaZPMsuQNCsWn0iVMtGbaUXO6z-EdZaZm", + "title": "03 Jan 12:09", + "owned": True, + "trackCount": 245, + "year": "2024", + "description": "Created by Playlist Generator Bot, @spotify_youtube_playlist_bot", + "duration": "5+ hours", + }, + ), + ( + "2024_03_get_playlist_public.json", + { + "id": "RDCLAK5uy_lWy02cQBnTVTlwuRauaGKeUDH3L6PXNxI", + "title": "Feel-Good Classic Rock", + "owned": False, + "trackCount": 101, + "year": "2024", + "description": "Hold on to the feeling.\n#essentials #rock #happy", + "duration": "6+ hours", + }, + ), + ( + "2024_07_get_playlist_collaborative.json", + { + "id": "PLEUijtLfpCOgI8LNOwiwvq0EJ8HAGj7dT", + "title": "Example_collaborative_playlist", + "owned": True, + "trackCount": 4, + "year": "2024", + "description": "Example playlist with collaboration", + "duration": "11 minutes, 15 seconds", + }, + ), ], ) - def test_get_playlist_2024(self, yt, test_file, owned): + def test_get_playlist(self, yt, test_file, output): with open(Path(__file__).parent.parent / "data" / test_file, encoding="utf8") as f: mock_response = json.load(f) with mock.patch("ytmusicapi.YTMusic._send_request", return_value=mock_response): playlist = yt.get_playlist("MPREabc") - assert playlist["year"] == "2024" - assert playlist["owned"] == owned - assert "hours" in playlist["duration"] or "minutes" in playlist["duration"] - assert playlist["id"] - assert isinstance(playlist["description"], str) and playlist["description"] - assert len(playlist["tracks"]) > 0 + assert playlist == playlist | output + + for thumbnail in playlist.get("thumbnails", []): + assert thumbnail["url"] and thumbnail["width"] and thumbnail["height"] + assert len(playlist["tracks"]) > 0 for track in playlist["tracks"]: assert isinstance(track["title"], str) and track["title"] diff --git a/ytmusicapi/parsers/playlists.py b/ytmusicapi/parsers/playlists.py index d72a4066..9ec34b73 100644 --- a/ytmusicapi/parsers/playlists.py +++ b/ytmusicapi/parsers/playlists.py @@ -40,7 +40,7 @@ def parse_playlist_header_meta(header: dict[str, Any]) -> dict[str, Any]: "views": None, "duration": None, "trackCount": None, - "title": nav(header, TITLE_TEXT, none_if_absent=True), + "title": "".join([run["text"] for run in header.get("title", {}).get("runs", [])]), "thumbnails": nav(header, THUMBNAILS), } if "runs" in header["secondSubtitle"]: