Collections¶

The Spotify service implements the standard collection interfaces that are common across all services.

Library¶

The SpotifyLibrary represents the full spotify catalog from the perspective of an authenticated user.

from plistsync.services.spotify import SpotifyLibrary

library = SpotifyLibrary()

Track Lookup¶

The Spotify library collection supports lookup by global IDs, specifically by spotify_id and isrc. This allows for efficient retrieval of tracks using these identifiers.

# By spotify id
if track1 := library.find_by_global_ids({"spotify_id": "6fzwardfFs6sVfNA5R1ypt"}):
    print(track1)

# By isrc
if track2 := library.find_by_global_ids({"isrc": "GBBZH9601601"}):
    print(track2)

assert track1 == track2
SpotifyTrack(artist='Origin Unknown', title='Valley of the Shadows')
SpotifyTrack(artist='Origin Unknown', title='Valley of the Shadows')

If you need/want to lookup many tracks at once, consider using SpotifyLibrary.find_many_by_global_ids for better performance.

Playlists¶

The SpotifyPlaylist represents a playlist of an authenticated user.

Retrieving playlists¶

You can retrieve all playlists of a user using the library’s SpotifyLibrary.playlists property.

playlists = library.playlists
for playlist in playlists:
    print(f"Playlist: {playlist.name} ({len(playlist)} tracks)")
Playlist: plistsync (3 tracks)

If you just want a specific playlist, you can use the library’s SpotifyLibrary.get_playlist method to retrieve a playlist.

# By name
pl = library.get_playlist(
    name="plistsync"
    # id = "6tPAXg3zqkOgUPZPyD5Pph"
    # uri = "spotify:playlist:6tPAXg3zqkOgUPZPyD5Pph"
    # url = "https://open.spotify.com/playlist/6tPAXg3zqkOgUPZPyD5Pph"
)
if pl is not None:
    print(f"Found playlist: {pl.name} ({len(pl.tracks)} tracks)")
else:
    print("Playlist not found.")
Found playlist: plistsync (3 tracks)

Note

This method supports lookup by various identifiers, including name=, id=, url=, or uri=. Lookup by name will return None if no matching playlist is found, while lookups by other identifiers will raise a ValueError if the playlist cannot be resolved.

Creating playlists¶

By convention, playlist are always created within a library. To create a new playlist online, use the {py.meth}SpotifyLibrary.create_playlist <plistsync.services.spotify.SpotifyLibrar.create_playlist> method.

pl = library.create_playlist(
    name="My New Playlist",
    description="Created via plistsync",
)

Updating a playlist¶

For updating a playlist, you should use the playlist’s SpotifyPlaylist.edit context manager. This ensures that all changes are properly saved back to Spotify when you exit the context. This also minifies changes and therefore reduces API calls.

# Updating a playlist description/name
with pl.edit():
    pl.description = "Updated Description"

pl.description
'Updated Description'

You can add tracks to a playlist using the same context manager, again this will add the tracks when you exit the context.

from plistsync.services.spotify import SpotifyPlaylistTrack

new_track_1 = library.find_by_global_ids({"isrc": "GBBZH9601601"})
new_track_2 = library.find_by_global_ids({"isrc": "GBXJH1000082"})
assert new_track_1 is not None
assert new_track_2 is not None

with pl.edit():
    # TODO: We should reevaluate the type hierarchy here.
    # for now, we have to manually cast SpotifyTrack to SpotifyPlaylistTrack.
    # this will become more convenient, eventually.
    pl.tracks.append(SpotifyPlaylistTrack(new_track_1))
    pl.tracks.append(SpotifyPlaylistTrack(new_track_2))

pl.tracks
[SpotifyPlaylistTrack(artist='Origin Unknown', title='Valley of the Shadows'),
 SpotifyPlaylistTrack(artist='Break', title='If I Could')]

To reorder tracks in a playlist, you can change the order of the SpotifyPlaylist.tracks list within the context manager.

with pl.edit():
    pl.tracks.insert(0, pl.tracks.pop())

Delete a playlist¶

To remove the playlist from your spotify account, use the SpotifyPlaylist.delete method.

Note how this returns an instance of OfflinePlaylist, so that you can still work with the local in-memory version of the last online state.

offline_pl = pl.delete()
offline_pl
OfflinePlaylist(name='My New Playlist', tracks=2)

Even tho the playlist is deleted from your users library it still does exist on spotify. This is a design choice by spotify itself, which makes it impossible to truly delete a playlist. See here for more information.

As a consequence, you could — but really should not — keep working with the old playlist id. The lookup by name, for which we search in your library, will not work.

assert pl.id
assert library.get_playlist(id=pl.id)
assert not library.get_playlist(name=pl.name)

Our recommended way for recovery is to create a new playlist based on the track data kept in the offline_pl. We are working on helpers to persist them on disk, to make recovery easier.