implemented playlist related methods in album, tag and user modules. updated some methods to the latest API docs. The read-only part of API is complete.

This commit is contained in:
Abhinav Sarkar 2008-09-02 14:19:03 +00:00
parent a2320e6dd0
commit 27a1676c3b
7 changed files with 148 additions and 38 deletions

View File

@ -114,6 +114,10 @@ class Album(LastfmBase):
"""top tag for the album""" """top tag for the album"""
pass pass
@LastfmBase.cachedProperty
def playlist(self):
return Playlist.fetch(self.__api, "lastfm://playlist/album/%s" % self.id)
@staticmethod @staticmethod
def _fetchData(api, def _fetchData(api,
artist = None, artist = None,
@ -203,5 +207,6 @@ import time
from api import Api from api import Api
from artist import Artist from artist import Artist
from error import LastfmInvalidParametersError from error import LastfmInvalidParametersError
from playlist import Playlist
from stats import Stats from stats import Stats
from tag import Tag from tag import Tag

View File

@ -13,7 +13,7 @@ class Api(object):
SEARCH_XMLNS = "http://a9.com/-/spec/opensearch/1.1/" SEARCH_XMLNS = "http://a9.com/-/spec/opensearch/1.1/"
def __init__(self, def __init__(self,
apiKey = '23caa86333d2cb2055fa82129802780a', apiKey,
input_encoding=None, input_encoding=None,
request_headers=None, request_headers=None,
no_cache = False, no_cache = False,
@ -264,7 +264,6 @@ class Api(object):
def _fetchData(self, def _fetchData(self,
params, params,
parse = True,
no_cache = False): no_cache = False):
params.update({'api_key': self.__apiKey}) params.update({'api_key': self.__apiKey})
xml = self._fetchUrl(Api.API_ROOT_URL, params, no_cache = self._no_cache or no_cache) xml = self._fetchUrl(Api.API_ROOT_URL, params, no_cache = self._no_cache or no_cache)
@ -280,10 +279,7 @@ class Api(object):
raise errorMap[code](message, code) raise errorMap[code](message, code)
else: else:
raise LastfmError(message, code) raise LastfmError(message, code)
if parse: return data
return data
else:
return xml
def __repr__(self): def __repr__(self):
return "<lastfm.Api: %s>" % self.__apiKey return "<lastfm.Api: %s>" % self.__apiKey

View File

@ -12,10 +12,15 @@ class Geo(object):
@staticmethod @staticmethod
def getEvents(api, def getEvents(api,
location, location,
latitude = None,
longitude = None,
distance = None): distance = None):
params = {'method': 'geo.getevents', 'location': location} params = {'method': 'geo.getevents', 'location': location}
if distance is not None: if distance is not None:
params.update({'distance': distance}) params.update({'distance': distance})
if latitude is not None and longitude is not None:
params.update({'latitude': latitude, 'longitude': longitude})
@lazylist @lazylist
def gen(lst): def gen(lst):
@ -58,8 +63,11 @@ class Geo(object):
] ]
@staticmethod @staticmethod
def getTopTracks(api, country): def getTopTracks(api, country, location = None):
params = {'method': 'geo.gettoptracks', 'country': country} params = {'method': 'geo.gettoptracks', 'country': country}
if location is not None:
params.update({'location': location})
data = api._fetchData(params).find('toptracks') data = api._fetchData(params).find('toptracks')
return [ return [
Track( Track(
@ -135,7 +143,6 @@ class Location(LastfmBase):
def init(self, def init(self,
api, api,
name = None,
city = None, city = None,
country = None, country = None,
street = None, street = None,
@ -146,7 +153,6 @@ class Location(LastfmBase):
if not isinstance(api, Api): if not isinstance(api, Api):
raise LastfmInvalidParametersError("api reference must be supplied as an argument") raise LastfmInvalidParametersError("api reference must be supplied as an argument")
self.__api = api self.__api = api
self.__name = name
self.__city = city self.__city = city
self.__country = country self.__country = country
self.__street = street self.__street = street
@ -155,11 +161,6 @@ class Location(LastfmBase):
self.__longitude = longitude self.__longitude = longitude
self.__timezone = timezone self.__timezone = timezone
@property
def name(self):
"""name of the location"""
return self.__name
@property @property
def city(self): def city(self):
"""city in which the location is situated""" """city in which the location is situated"""
@ -194,10 +195,26 @@ class Location(LastfmBase):
def timezone(self): def timezone(self):
"""timezone in which the location is situated""" """timezone in which the location is situated"""
return self.__timezone return self.__timezone
@LastfmBase.cachedProperty
def topTracks(self):
"""top tracks of the location"""
if self.country is None or self.city is None:
raise LastfmInvalidParametersError("country and city of this location are required for calling this method")
return Geo.getTopTracks(self.__api, self.country.name, self.city)
@LastfmBase.topProperty("topTracks")
def topTrack(self):
"""top track of the location"""
pass
def getEvents(self, def getEvents(self,
distance = None): distance = None):
return Geo.getEvents(self.__api, self.name, distance) return Geo.getEvents(self.__api,
self.city,
self.latitude,
self.longitude,
distance)
@LastfmBase.cachedProperty @LastfmBase.cachedProperty
def events(self): def events(self):
@ -210,9 +227,9 @@ class Location(LastfmBase):
return hash("latlong%s%s" % (kwds['latitude'], kwds['longitude'])) return hash("latlong%s%s" % (kwds['latitude'], kwds['longitude']))
except KeyError: except KeyError:
try: try:
return hash("name%s" % kwds['name']) return hash("name%s" % kwds['city'])
except KeyError: except KeyError:
raise LastfmInvalidParametersError("either latitude and longitude or name has to be provided for hashing") raise LastfmInvalidParametersError("either latitude and longitude or city has to be provided for hashing")
def __hash__(self): def __hash__(self):
if not self.name: if not self.name:
@ -220,7 +237,7 @@ class Location(LastfmBase):
latitude = self.latitude, latitude = self.latitude,
longitude = self.longitude) longitude = self.longitude)
else: else:
return self.__class__.hashFunc(name = self.name) return self.__class__.hashFunc(name = self.city)
def __eq__(self, other): def __eq__(self, other):
return self.latitude == other.latitude and self.longitude == other.longitude return self.latitude == other.latitude and self.longitude == other.longitude
@ -232,10 +249,10 @@ class Location(LastfmBase):
return self.city < other.city return self.city < other.city
def __repr__(self): def __repr__(self):
if self.name is None: if self.city is None:
return "<lastfm.geo.Location: (%s, %s)>" % (self.latitude, self.longitude) return "<lastfm.geo.Location: (%s, %s)>" % (self.latitude, self.longitude)
else: else:
return "<lastfm.geo.Location: %s>" % self.name return "<lastfm.geo.Location: %s>" % self.city
class Country(LastfmBase): class Country(LastfmBase):
"""A class representing a country.""" """A class representing a country."""
@ -262,21 +279,24 @@ class Country(LastfmBase):
"""top artist of the country""" """top artist of the country"""
pass pass
def getTopTracks(self, location = None):
return Geo.getTopTracks(self.__api, self.name, location)
@LastfmBase.cachedProperty @LastfmBase.cachedProperty
def topTracks(self): def topTracks(self):
"""top tracks of the country""" """top tracks of the country"""
return Geo.getTopTracks(self.__api, self.name) return self.getTopTracks()
@LastfmBase.cachedProperty
def events(self):
"""events taking place at/around the location"""
return Geo.getEvents(self.__api, self.name)
@LastfmBase.topProperty("topTracks") @LastfmBase.topProperty("topTracks")
def topTrack(self): def topTrack(self):
"""top track of the country""" """top track of the country"""
pass pass
@LastfmBase.cachedProperty
def events(self):
"""events taking place at/around the location"""
return Geo.getEvents(self.__api, self.name)
@staticmethod @staticmethod
def hashFunc(*args, **kwds): def hashFunc(*args, **kwds):
try: try:

View File

@ -8,14 +8,18 @@ from base import LastfmBase
class Playlist(LastfmBase): class Playlist(LastfmBase):
"""A class representing an XPSF playlist.""" """A class representing an XPSF playlist."""
def init(self, xpsfData, url): def init(self, api, url):
self.__data = xpsfData self.__api = api
self.__data = None
self.__url = url self.__url = url
@property @LastfmBase.cachedProperty
def data(self): def data(self):
"""playlist's data""" """playlist's data"""
return self.__data params = {'method': 'playlist.fetch', 'playlistURL': self.__url}
tmp = StringIO.StringIO()
ElementTree.ElementTree(self.__api._fetchData(params)[0]).write(tmp)
return tmp.getvalue()
@property @property
def url(self): def url(self):
@ -24,8 +28,7 @@ class Playlist(LastfmBase):
@staticmethod @staticmethod
def fetch(api, url): def fetch(api, url):
params = {'method': 'playlist.fetch', 'playlistURL': url} return Playlist(api, url = url)
return Playlist(api._fetchData(params, parse = False), url = url)
@staticmethod @staticmethod
def hashFunc(*args, **kwds): def hashFunc(*args, **kwds):
@ -45,5 +48,18 @@ class Playlist(LastfmBase):
def __repr__(self): def __repr__(self):
return "<lastfm.Playlist: %s>" % self.url return "<lastfm.Playlist: %s>" % self.url
from error import LastfmInvalidParametersError import StringIO
import sys
from error import LastfmInvalidParametersError
if sys.version.startswith('2.5'):
import xml.etree.cElementTree as ElementTree
else:
try:
import cElementTree as ElementTree
except ImportError:
try:
import ElementTree
except ImportError:
raise LastfmError("Install ElementTree package for using python-lastfm")

View File

@ -163,6 +163,11 @@ class Tag(LastfmBase):
"""top track for the tag""" """top track for the tag"""
pass pass
@LastfmBase.cachedProperty
def playlist(self):
return Playlist.fetch(self.__api,
"lastfm://playlist/tag/%s/freetracks" % self.name)
@staticmethod @staticmethod
def getTopTags(api): def getTopTags(api):
params = {'method': 'tag.getTopTags'} params = {'method': 'tag.getTopTags'}
@ -240,5 +245,6 @@ from album import Album
from api import Api from api import Api
from artist import Artist from artist import Artist
from error import LastfmInvalidParametersError from error import LastfmInvalidParametersError
from playlist import Playlist
from stats import Stats from stats import Stats
from track import Track from track import Track

View File

@ -61,6 +61,6 @@ class Tasteometer(object):
def __repr__(self): def __repr__(self):
return "<lastfm.Tasteometer>" return "<lastfm.Tasteometer: %s%% match>" % (self.score*100)
from artist import Artist from artist import Artist

View File

@ -6,6 +6,7 @@ __license__ = "GNU Lesser General Public License"
from base import LastfmBase from base import LastfmBase
from lazylist import lazylist from lazylist import lazylist
import playlist
class User(LastfmBase): class User(LastfmBase):
"""A class representing an user.""" """A class representing an user."""
@ -141,10 +142,27 @@ class User(LastfmBase):
"""nearest neightbour of the user""" """nearest neightbour of the user"""
pass pass
@property @LastfmBase.cachedProperty
def playlists(self): def playlists(self):
"""playlists of the user""" """playlists of the user"""
pass params = {'method': 'user.getPlaylists', 'user': self.name}
data = self.__api._fetchData(params).find('playlists')
return [
User.Playlist(
self.__api,
id = int(p.findtext('id')),
title = p.findtext('title'),
date = datetime(*(
time.strptime(
p.findtext('date').strip(),
'%Y-%m-%dT%H:%M:%S'
)[0:6])
),
size = int(p.findtext('size')),
creator = self
)
for p in data.findall('playlist')
]
@LastfmBase.cachedProperty @LastfmBase.cachedProperty
def lovedTracks(self): def lovedTracks(self):
@ -451,6 +469,11 @@ class User(LastfmBase):
pass pass
return gen() return gen()
def compare(self, other, limit = None):
return Tasteometer.compare(self.__api,
'user', 'user',
self.name, other.name,
limit)
@property @property
def library(self): def library(self):
return self.__lirary return self.__lirary
@ -474,6 +497,49 @@ class User(LastfmBase):
def __repr__(self): def __repr__(self):
return "<lastfm.User: %s>" % self.name return "<lastfm.User: %s>" % self.name
class Playlist(playlist.Playlist):
"""A class representing a playlist belonging to the user."""
def init(self, api, id, title, date, size, creator):
super(User.Playlist, self).init(api, "lastfm://playlist/%s" % id)
self.__id = id
self.__title = title
self.__date = date
self.__size = size
self.__creator = creator
@property
def id(self):
return self.__id
@property
def title(self):
return self.__title
@property
def date(self):
return self.__date
@property
def size(self):
return self.__size
@property
def creator(self):
return self.__creator
@staticmethod
def hashFunc(*args, **kwds):
try:
return hash(kwds['id'])
except KeyError:
raise LastfmInvalidParametersError("id has to be provided for hashing")
def __hash__(self):
return self.__class__.hashFunc(id = self.id)
def __repr__(self):
return "<lastfm.User.Playlist: %s>" % self.title
class Library(object): class Library(object):
"""A class representing the music library of the user.""" """A class representing the music library of the user."""
def __init__(self, api, user): def __init__(self, api, user):
@ -649,5 +715,6 @@ from error import LastfmError, LastfmInvalidParametersError
from event import Event from event import Event
from stats import Stats from stats import Stats
from tag import Tag from tag import Tag
from tasteometer import Tasteometer
from track import Track from track import Track
from weeklychart import WeeklyChart, WeeklyAlbumChart, WeeklyArtistChart, WeeklyTrackChart from weeklychart import WeeklyChart, WeeklyAlbumChart, WeeklyArtistChart, WeeklyTrackChart