Skip to content
Open
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
10 changes: 5 additions & 5 deletions spotdl/types/song.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ def from_url(cls, url: str) -> "Song":
if raw_album_meta["copyrights"]
else None
),
genres=raw_album_meta["genres"] + raw_artist_meta["genres"],
genres=(raw_album_meta.get("genres") or []) + (raw_artist_meta.get("genres") or []),
disc_number=raw_track_meta["disc_number"],
disc_count=int(raw_album_meta["tracks"]["items"][-1]["disc_number"]),
disc_count=int(raw_album_meta.get("tracks", {}).get("items", [{}])[-1].get("disc_number", raw_track_meta["disc_number"])),
duration=int(raw_track_meta["duration_ms"] / 1000),
year=int(raw_album_meta["release_date"][:4]),
date=raw_album_meta["release_date"],
Expand All @@ -125,14 +125,14 @@ def from_url(cls, url: str) -> "Song":
isrc=raw_track_meta.get("external_ids", {}).get("isrc"),
song_id=raw_track_meta["id"],
explicit=raw_track_meta["explicit"],
publisher=raw_album_meta["label"],
publisher=raw_album_meta.get("label", ""),
url=raw_track_meta["external_urls"]["spotify"],
popularity=raw_track_meta["popularity"],
popularity=raw_track_meta.get("popularity"),
cover_url=(
max(raw_album_meta["images"], key=lambda i: i["width"] * i["height"])[
"url"
]
if raw_album_meta["images"]
if raw_album_meta.get("images")
else None
),
)
Expand Down
52 changes: 52 additions & 0 deletions tests/types/test_song.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from spotdl.types.album import Album
from spotdl.types.song import Song
from spotdl.utils.spotify import SpotifyClient


def test_song_init():
Expand Down Expand Up @@ -203,6 +204,57 @@ def test_song_from_data_dump_wrong_type():
Song.from_data_dump(1) # type: ignore


def test_song_from_url_missing_optional_spotify_fields(monkeypatch):
"""
Song.from_url() should tolerate partial Spotify payloads.
"""

class DummySpotifyClient:
def track(self, _url):
return {
"id": "track-id",
"name": "Test Track",
"duration_ms": 204000,
"disc_number": 1,
"track_number": 1,
"explicit": False,
"popularity": 17,
"external_urls": {"spotify": "https://open.spotify.com/track/track-id"},
"external_ids": {"isrc": "TEST12345678"},
"artists": [{"id": "artist-id", "name": "Test Artist"}],
"album": {"id": "album-id"},
}

def artist(self, _artist_id):
return {
"id": "artist-id",
"name": "Test Artist",
}

def album(self, _album_id):
return {
"id": "album-id",
"name": "Test Album",
"artists": [{"name": "Test Artist"}],
"release_date": "2024-01-02",
"total_tracks": 1,
"tracks": {"items": [{"disc_number": 1}]},
"copyrights": [],
}

monkeypatch.setattr(SpotifyClient, "_instance", DummySpotifyClient())

song = Song.from_url("https://open.spotify.com/track/track-id")

assert song.name == "Test Track"
assert song.artists == ["Test Artist"]
assert song.album_name == "Test Album"
assert song.genres == []
assert song.publisher == ""
assert song.cover_url is None
assert song.popularity == 17


def test_song_from_dict():
"""
Tests if Song.from_dict() works correctly.
Expand Down