Skip to content
Niko Gupta edited this page May 1, 2020 · 4 revisions

Welcome to the Spotifython wiki!

This project initially started as our final project for our api design class at CMU. We were tasked with redesigning and implementing an api that we felt was flawed. Our api of choice was (spotipy)[https://github.com/plamere/spotipy].

The main problem that we identified is the fact that Spotipy is essentially a transliteration of Spotify’s REST api endpoints. By creating a direct mapped wrapper to the REST api, Spotipy ends up not being very pythonic. As a result, client code that uses the library ends up sloppy and with lots of boilerplate code.

More specific examples include:

  • Library is flat and sprawling, making client code messy and not modularized. Every method exists in a single, bloated Spotipy class in client.py, despite Spotify having a natural separation of conceptual objects (i.e. track, artist, playlist, etc.).

  • Library returns the direct json object from Spotify. For one, this assumes that the user has a deep understanding of the data layout, or at least a constant reference to Spotify's endpoints and their returns. If the ODM changes (which it has before), client code using Spotipy will break. We feel it's unreasonable for a client to need to have both Spotipy's and Spotify's documentations open in order to use Spotipy; at that point they could just write their own wrapper.

  • Method naming reflects the bloated structure, and multiple function calls require a bevy of unclear inputs. For example:

user_playlist_remove_specific_occurrences_of_tracks(user, playlist_id, tracks, snapshot_id=None)
current_user_saved_tracks_contains(tracks=None)
user_playlist_change_details(user, playlist_id, name=None, public=None, collaborative=None, description=None)

The names of the functions are directly copied from the REST endpoints, such as /v1/me/tracks/contains for current_user_saved_tracks_contains. By creating logically objects such as Tracks and Users, the above function could become:

u = User(user_id)
t = Track(track_id)
u.has_saved(t)

You can find more examples of messy client code and how our library proposes fixing it here.

Clone this wiki locally