commit dfced54992d32a52ed8d658e12b6b3cf7c83595b Author: Paul Lamere Date: Sat Apr 5 09:12:01 2014 -0400 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..1571d2e --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Spotipy - a Python client for The Spotify API + +## Description + +Spotipy is a thin client library for the Spotify Web API . + + +## Installation +If you already have [Python](http://www.python.org/) and [pip](http://www.pip-installer.org/) on your system you can install +the library simply by running: + + pip install spotipy + +Or you can download the distribution, unpack it and install in the usual fashion: + + python setup.py install + + +## Dependencies + +- [Requests](https://github.com/kennethreitz/requests) - spotipy requires the requests package to be installed + +## Limitations +This version of the library does not support user authentication + + + +## Quick Start +To get started: + +- Install spotipy + +- Create a Spotify object + + sp = spotipy.Spotify() + +Call methods: + + tracks = sp.search(q='weezer', limit=20) + for i, t in enumerate(tracks['tracks']): + print ' ', i, t['name'] + +A full set of examples can be found in the [Spotipy examples directory](https://github.com/plamere/spotipy/tree/master/examples) + + +## Supported Methods + + - track - gets info for a single track + - tracks - gets info for multiple tracks + - album - gets info for a single album + - albums - gets info for a set of albums + - artist - gets info for an artist + - artists - gets info for a set of artists + - user - gets profile info for a user + - search - searches for artists, albums or tracks + +Refer to the [Spotify API documentation](https://developer.spotify.com/spotify-web-api/) for details on the methods and parameters. + +Methods that take item IDs (such as the track, album and artist methods) accept URN, URL or simple ID types. The following 3 ids are all acceptable IDs: + + - http://open.spotify.com/track/3HfB5hBU0dmBt8T0iCmH42 + - spotify:track:3HfB5hBU0dmBt8T0iCmH42 + - 3HfB5hBU0dmBt8T0iCmH42 + + + +## Reporting Issues + +If you have suggestions, bugs or other issues specific to this library, file them [here](https://github.com/plamere/spotipy/issues) or contact me +at [paul@echonest.com](mailto:paul@echonest.com). Or just send me a pull request. + +## Version + +- 1.0 - 04/05/2014 - Initial release + diff --git a/deploy b/deploy new file mode 100755 index 0000000..7daefcf --- /dev/null +++ b/deploy @@ -0,0 +1,2 @@ +python setup.py sdist upload + diff --git a/examples/show_artist.py b/examples/show_artist.py new file mode 100644 index 0000000..b07186a --- /dev/null +++ b/examples/show_artist.py @@ -0,0 +1,16 @@ +# shows artist info for a URN or URL + +import spotipy +import sys +import pprint + +if len(sys.argv) > 1: + urn = sys.argv[1] +else: + urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu' + + +sp = spotipy.Spotify() +artist = sp.artist(urn) +pprint.pprint(artist) + diff --git a/examples/show_track_info.py b/examples/show_track_info.py new file mode 100644 index 0000000..4a720ba --- /dev/null +++ b/examples/show_track_info.py @@ -0,0 +1,15 @@ +# shows track info for a URN or URL + +import spotipy +import sys +import pprint + +if len(sys.argv) > 1: + urn = sys.argv[1] +else: + urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ' + +sp = spotipy.Spotify() +track = sp.track(urn) +pprint.pprint(track) + diff --git a/examples/tracks.py b/examples/tracks.py new file mode 100644 index 0000000..10883c8 --- /dev/null +++ b/examples/tracks.py @@ -0,0 +1,12 @@ +# shows tracks for the given artist + +import spotipy +import sys +sp = spotipy.Spotify() + +if len(sys.argv) > 1: + artist_name = ' '.join(sys.argv[1:]) + tracks = sp.search(q=artist_name, limit=20) + for i, t in enumerate(tracks['tracks']): + print ' ', i, t['name'] + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..07bee83 --- /dev/null +++ b/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup + + +setup( + name='spotipy', + version='0.9', + description='simple client for The Spotify Web API', + author="@plamere", + author_email="paul@echonest.com", + url='http://github.com/plamere/spotipy', + install_requires=['requests>=1.0',], + py_modules=['spotipy'],) diff --git a/spotipy.py b/spotipy.py new file mode 100644 index 0000000..75d71e5 --- /dev/null +++ b/spotipy.py @@ -0,0 +1,110 @@ +import requests +import os +import time +import datetime +import json +import logging + +''' A simple and thin python library for the Spotify Web API +''' + +class SpotifyException(Exception): + def __init__(self, http_status, code, msg): + self.http_status = http_status + self.code = code + self.msg = msg + def __str__(self): + return u'http status: {0}, code:{1} - {2}'.format(self.http_status, self.code, self.msg) + +class Spotify(object): + def __init__(self): + self.prefix = 'https://api.spotify.com/v1/' + + def _internal_call(self, verb, method, params): + url = self.prefix + method + args = dict(params=params) + r = requests.request(verb, url, **args) + if r.status_code >= 400 and r.status_code < 500: + self._error(u'ERROR {0} {1}'.format(r.status_code, r.url)) + if r.status_code != 200: + raise SpotifyException(r.status_code, -1, u'the requested resource could not be found') + return r.json() + + + def get(self, method, args = None, **kwargs): + if args: + kwargs.update(args) + return self._internal_call('GET', method, kwargs) + + def _error(self, msg): + print('ERROR - ' + msg); + + def _warn(self, msg): + print('warning:' + msg); + + def track(self, track_id): + ''' returns a single track given the track's ID, URN or URL + ''' + + trid = self._get_id('track', track_id) + return self.get('tracks/' + trid) + + def tracks(self, tracks): + ''' returns a list of tracks given the track IDs, URNs, or URLs + ''' + + tlist = [self._get_id('track', t) for t in tracks] + return self.get('tracks/?ids=' + ','.join(tlist)) + + def artist(self, artist_id): + ''' returns a single artist given the artist's ID, URN or URL + ''' + + trid = self._get_id('artist', artist_id) + return self.get('artists/' + trid) + + def artists(self, artists): + ''' returns a list of artists given the artist IDs, URNs, or URLs + ''' + + tlist = [self._get_id('artist', a) for a in artists] + return self.get('artists/?ids=' + ','.join(tlist)) + + def album(self, album_id): + ''' returns a single album given the album's ID, URN or URL + ''' + + trid = self._get_id('album', album_id) + return self.get('albums/' + trid) + + def albums(self, albums): + ''' returns a list of albums given the album IDs, URNs, or URLs + ''' + + tlist = [self._get_id('album', a) for a in albums] + return self.get('albums/?ids=' + ','.join(tlist)) + + + def search(self, q, limit=10, offset=0, type='track'): + ''' searches for an item + ''' + return self.get('search', q=q, limit=limit, offset=offset, type=type) + + def user(self, user_id): + ''' Gets basic profile information about a Spotify User + ''' + return self.get('users/' + user_id) + + def _get_id(self, type, id): + fields = id.split(':') + if len(fields) == 3: + if type != fields[1]: + self._warn('expected id of type ' + type + ' but found type ' + fields[2] + " " + id) + return fields[2] + fields = id.split('/') + if len(fields) >= 3: + itype = fields[-2] + if type != itype: + self._warn('expected id of type ' + type + ' but found type ' + itype + " " + id) + return fields[-1] + return id diff --git a/tests/tests.py b/tests/tests.py new file mode 100644 index 0000000..664996c --- /dev/null +++ b/tests/tests.py @@ -0,0 +1,88 @@ +# -*- coding: latin-1 -*- +import spotipy +import unittest +import pprint + +import logging + +class TestSpotipy(unittest.TestCase): + + creep_urn = 'spotify:track:3HfB5hBU0dmBt8T0iCmH42' + creep_id = '3HfB5hBU0dmBt8T0iCmH42' + creep_url = 'http://open.spotify.com/track/3HfB5hBU0dmBt8T0iCmH42' + el_scorcho_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ' + pinkerton_urn = 'spotify:album:04xe676vyiTeYNXw15o9jT' + weezer_urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu' + pablo_honey_urn = 'spotify:album:6AZv3m27uyRxi8KyJSfUxL' + radiohead_urn = 'spotify:artist:4Z8W4fKeB5YxbusRsdQVPb' + + bad_id = 'BAD_ID' + + def setUp(self): + self.spotify = spotipy.Spotify() + + def test_artist_urn(self): + artist = self.spotify.artist(self.radiohead_urn) + self.assertTrue(artist['name'] == u'Radiohead') + + def test_artists(self): + results = self.spotify.artists([self.weezer_urn, self.radiohead_urn]) + self.assertTrue('artists' in results) + self.assertTrue(len(results['artists']) == 2) + + def test_album_urn(self): + album = self.spotify.album(self.pinkerton_urn) + self.assertTrue(album['name'] == u'Pinkerton') + + def test_albums(self): + results = self.spotify.albums([self.pinkerton_urn, self.pablo_honey_urn]) + self.assertTrue('albums' in results) + self.assertTrue(len(results['albums']) == 2) + + def test_track_urn(self): + track = self.spotify.track(self.creep_urn) + self.assertTrue(track['name'] == u'Creep') + + def test_track_id(self): + track = self.spotify.track(self.creep_id) + self.assertTrue(track['name'] == u'Creep') + + def test_track_url(self): + track = self.spotify.track(self.creep_url) + self.assertTrue(track['name'] == u'Creep') + + def test_tracks(self): + results = self.spotify.tracks([self.creep_url, self.el_scorcho_urn]) + self.assertTrue('tracks' in results) + self.assertTrue(len(results['tracks']) == 2) + + def test_artist_search(self): + results = self.spotify.search(q='weezer', type='artist') + self.assertTrue('artists' in results) + self.assertTrue(len(results['artists']) > 0) + self.assertTrue(results['artists'][0]['name'] == 'Weezer') + + def test_album_search(self): + results = self.spotify.search(q='weezer pinkerton', type='album') + self.assertTrue('albums' in results) + self.assertTrue(len(results['albums']) > 0) + self.assertTrue(results['albums'][0]['name'] == 'Pinkerton') + + def test_track_search(self): + results = self.spotify.search(q='el scorcho weezer', type='track') + self.assertTrue('tracks' in results) + self.assertTrue(len(results['tracks']) > 0) + self.assertTrue(results['tracks'][0]['name'] == 'El Scorcho') + + def test_user(self): + user = self.spotify.user(user_id='plamere') + self.assertTrue(user['username'] == 'plamere') + + def test_track_bad_id(self): + try: + track = self.spotify.track(self.bad_id) + self.assertTrue(False) + except spotipy.SpotifyException: + self.assertTrue(True) +if __name__ == '__main__': + unittest.main()