sung.playlists¶
Build Spotify playlists from human-friendly song descriptors.
Given a list of “song descriptors” — things like "Clocks",
"Clocks - Coldplay", ("Believer", "Imagine Dragons"), or
{"name": "Fix You", "artist": "Coldplay"} — resolve each to a Spotify
track and create a playlist in one call.
Example:
>>> from sung.playlists import playlist_from_songs
>>> playlist, report = playlist_from_songs(
... [
... ("Clocks", "Coldplay"),
... "Radioactive - Imagine Dragons",
... {"name": "Believer", "artist": "Imagine Dragons"},
... ],
... playlist_name="My Mix",
... )
>>> playlist.playlist_url
'https://open.spotify.com/playlist/...'
The lower-level resolve_song() returns the chosen match plus the full
ranked candidate list, which the CLI uses to surface ambiguous matches.
Functions
|
Parse a song descriptor into |
|
Search for each song, then create a playlist with the resolved tracks. |
|
Resolve one song descriptor to a Spotify track via search + ranking. |
|
Resolve a list of descriptors. |
Classes
|
Result of resolving a single song descriptor. |
- class sung.playlists.SongMatch(descriptor, query_name, query_artist, track_id, track_name, artist_names=<factory>, album_name=None, popularity=None, score=0.0, candidates=<factory>, ambiguous=False, not_found=False)[source]¶
Bases:
objectResult of resolving a single song descriptor.
- sung.playlists.parse_song_descriptor(descriptor)[source]¶
Parse a song descriptor into
(name, artist_or_None).Accepts:
a plain string:
"Clocks""Title - Artist"or"Title — Artist"or"Title by Artist"a 2-tuple/list
(name, artist)a dict with
name/titleand optionalartist/artists
>>> parse_song_descriptor("Clocks") ('Clocks', None) >>> parse_song_descriptor("Clocks - Coldplay") ('Clocks', 'Coldplay') >>> parse_song_descriptor("Clocks by Coldplay") ('Clocks', 'Coldplay') >>> parse_song_descriptor(("Believer", "Imagine Dragons")) ('Believer', 'Imagine Dragons') >>> parse_song_descriptor({"name": "Fix You", "artist": "Coldplay"}) ('Fix You', 'Coldplay')
- sung.playlists.playlist_from_songs(descriptors, playlist_name='New Playlist', *, public=True, market=None, search_limit=10, skip_missing=True, client=None)[source]¶
Search for each song, then create a playlist with the resolved tracks.
Returns
(playlist, matches).playlistisNoneif no songs resolved.matchesis the list ofSongMatchresults — one per descriptor — including any that werenot_foundorambiguous.Use
skip_missing=Falseto raise instead of silently dropping descriptors that could not be resolved.
- sung.playlists.resolve_song(descriptor, *, market=None, search_limit=10, ambiguous_score_gap=10.0, client=None)[source]¶
Resolve one song descriptor to a Spotify track via search + ranking.
Returns a
SongMatchwith the best candidate selected. The match is flaggedambiguouswhen the top two candidates score withinambiguous_score_gapof each other (callers may want to confirm).- Return type:
- sung.playlists.resolve_songs(descriptors, *, market=None, search_limit=10, client=None)[source]¶
Resolve a list of descriptors. See
resolve_song().