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:
parent
a2320e6dd0
commit
27a1676c3b
@ -114,6 +114,10 @@ class Album(LastfmBase):
|
||||
"""top tag for the album"""
|
||||
pass
|
||||
|
||||
@LastfmBase.cachedProperty
|
||||
def playlist(self):
|
||||
return Playlist.fetch(self.__api, "lastfm://playlist/album/%s" % self.id)
|
||||
|
||||
@staticmethod
|
||||
def _fetchData(api,
|
||||
artist = None,
|
||||
@ -203,5 +207,6 @@ import time
|
||||
from api import Api
|
||||
from artist import Artist
|
||||
from error import LastfmInvalidParametersError
|
||||
from playlist import Playlist
|
||||
from stats import Stats
|
||||
from tag import Tag
|
@ -13,7 +13,7 @@ class Api(object):
|
||||
SEARCH_XMLNS = "http://a9.com/-/spec/opensearch/1.1/"
|
||||
|
||||
def __init__(self,
|
||||
apiKey = '23caa86333d2cb2055fa82129802780a',
|
||||
apiKey,
|
||||
input_encoding=None,
|
||||
request_headers=None,
|
||||
no_cache = False,
|
||||
@ -264,7 +264,6 @@ class Api(object):
|
||||
|
||||
def _fetchData(self,
|
||||
params,
|
||||
parse = True,
|
||||
no_cache = False):
|
||||
params.update({'api_key': self.__apiKey})
|
||||
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)
|
||||
else:
|
||||
raise LastfmError(message, code)
|
||||
if parse:
|
||||
return data
|
||||
else:
|
||||
return xml
|
||||
return data
|
||||
|
||||
def __repr__(self):
|
||||
return "<lastfm.Api: %s>" % self.__apiKey
|
||||
|
60
src/geo.py
60
src/geo.py
@ -12,11 +12,16 @@ class Geo(object):
|
||||
@staticmethod
|
||||
def getEvents(api,
|
||||
location,
|
||||
latitude = None,
|
||||
longitude = None,
|
||||
distance = None):
|
||||
params = {'method': 'geo.getevents', 'location': location}
|
||||
if distance is not None:
|
||||
params.update({'distance': distance})
|
||||
|
||||
if latitude is not None and longitude is not None:
|
||||
params.update({'latitude': latitude, 'longitude': longitude})
|
||||
|
||||
@lazylist
|
||||
def gen(lst):
|
||||
data = api._fetchData(params).find('events')
|
||||
@ -58,8 +63,11 @@ class Geo(object):
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def getTopTracks(api, country):
|
||||
def getTopTracks(api, country, location = None):
|
||||
params = {'method': 'geo.gettoptracks', 'country': country}
|
||||
if location is not None:
|
||||
params.update({'location': location})
|
||||
|
||||
data = api._fetchData(params).find('toptracks')
|
||||
return [
|
||||
Track(
|
||||
@ -135,7 +143,6 @@ class Location(LastfmBase):
|
||||
|
||||
def init(self,
|
||||
api,
|
||||
name = None,
|
||||
city = None,
|
||||
country = None,
|
||||
street = None,
|
||||
@ -146,7 +153,6 @@ class Location(LastfmBase):
|
||||
if not isinstance(api, Api):
|
||||
raise LastfmInvalidParametersError("api reference must be supplied as an argument")
|
||||
self.__api = api
|
||||
self.__name = name
|
||||
self.__city = city
|
||||
self.__country = country
|
||||
self.__street = street
|
||||
@ -155,11 +161,6 @@ class Location(LastfmBase):
|
||||
self.__longitude = longitude
|
||||
self.__timezone = timezone
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""name of the location"""
|
||||
return self.__name
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
"""city in which the location is situated"""
|
||||
@ -195,9 +196,25 @@ class Location(LastfmBase):
|
||||
"""timezone in which the location is situated"""
|
||||
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,
|
||||
distance = None):
|
||||
return Geo.getEvents(self.__api, self.name, distance)
|
||||
return Geo.getEvents(self.__api,
|
||||
self.city,
|
||||
self.latitude,
|
||||
self.longitude,
|
||||
distance)
|
||||
|
||||
@LastfmBase.cachedProperty
|
||||
def events(self):
|
||||
@ -210,9 +227,9 @@ class Location(LastfmBase):
|
||||
return hash("latlong%s%s" % (kwds['latitude'], kwds['longitude']))
|
||||
except KeyError:
|
||||
try:
|
||||
return hash("name%s" % kwds['name'])
|
||||
return hash("name%s" % kwds['city'])
|
||||
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):
|
||||
if not self.name:
|
||||
@ -220,7 +237,7 @@ class Location(LastfmBase):
|
||||
latitude = self.latitude,
|
||||
longitude = self.longitude)
|
||||
else:
|
||||
return self.__class__.hashFunc(name = self.name)
|
||||
return self.__class__.hashFunc(name = self.city)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.latitude == other.latitude and self.longitude == other.longitude
|
||||
@ -232,10 +249,10 @@ class Location(LastfmBase):
|
||||
return self.city < other.city
|
||||
|
||||
def __repr__(self):
|
||||
if self.name is None:
|
||||
if self.city is None:
|
||||
return "<lastfm.geo.Location: (%s, %s)>" % (self.latitude, self.longitude)
|
||||
else:
|
||||
return "<lastfm.geo.Location: %s>" % self.name
|
||||
return "<lastfm.geo.Location: %s>" % self.city
|
||||
|
||||
class Country(LastfmBase):
|
||||
"""A class representing a country."""
|
||||
@ -262,21 +279,24 @@ class Country(LastfmBase):
|
||||
"""top artist of the country"""
|
||||
pass
|
||||
|
||||
def getTopTracks(self, location = None):
|
||||
return Geo.getTopTracks(self.__api, self.name, location)
|
||||
|
||||
@LastfmBase.cachedProperty
|
||||
def topTracks(self):
|
||||
"""top tracks of the country"""
|
||||
return Geo.getTopTracks(self.__api, self.name)
|
||||
|
||||
@LastfmBase.cachedProperty
|
||||
def events(self):
|
||||
"""events taking place at/around the location"""
|
||||
return Geo.getEvents(self.__api, self.name)
|
||||
return self.getTopTracks()
|
||||
|
||||
@LastfmBase.topProperty("topTracks")
|
||||
def topTrack(self):
|
||||
"""top track of the country"""
|
||||
pass
|
||||
|
||||
@LastfmBase.cachedProperty
|
||||
def events(self):
|
||||
"""events taking place at/around the location"""
|
||||
return Geo.getEvents(self.__api, self.name)
|
||||
|
||||
@staticmethod
|
||||
def hashFunc(*args, **kwds):
|
||||
try:
|
||||
|
@ -8,14 +8,18 @@ from base import LastfmBase
|
||||
|
||||
class Playlist(LastfmBase):
|
||||
"""A class representing an XPSF playlist."""
|
||||
def init(self, xpsfData, url):
|
||||
self.__data = xpsfData
|
||||
def init(self, api, url):
|
||||
self.__api = api
|
||||
self.__data = None
|
||||
self.__url = url
|
||||
|
||||
@property
|
||||
@LastfmBase.cachedProperty
|
||||
def data(self):
|
||||
"""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
|
||||
def url(self):
|
||||
@ -24,8 +28,7 @@ class Playlist(LastfmBase):
|
||||
|
||||
@staticmethod
|
||||
def fetch(api, url):
|
||||
params = {'method': 'playlist.fetch', 'playlistURL': url}
|
||||
return Playlist(api._fetchData(params, parse = False), url = url)
|
||||
return Playlist(api, url = url)
|
||||
|
||||
@staticmethod
|
||||
def hashFunc(*args, **kwds):
|
||||
@ -46,4 +49,17 @@ class Playlist(LastfmBase):
|
||||
def __repr__(self):
|
||||
return "<lastfm.Playlist: %s>" % self.url
|
||||
|
||||
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")
|
@ -163,6 +163,11 @@ class Tag(LastfmBase):
|
||||
"""top track for the tag"""
|
||||
pass
|
||||
|
||||
@LastfmBase.cachedProperty
|
||||
def playlist(self):
|
||||
return Playlist.fetch(self.__api,
|
||||
"lastfm://playlist/tag/%s/freetracks" % self.name)
|
||||
|
||||
@staticmethod
|
||||
def getTopTags(api):
|
||||
params = {'method': 'tag.getTopTags'}
|
||||
@ -240,5 +245,6 @@ from album import Album
|
||||
from api import Api
|
||||
from artist import Artist
|
||||
from error import LastfmInvalidParametersError
|
||||
from playlist import Playlist
|
||||
from stats import Stats
|
||||
from track import Track
|
@ -61,6 +61,6 @@ class Tasteometer(object):
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "<lastfm.Tasteometer>"
|
||||
return "<lastfm.Tasteometer: %s%% match>" % (self.score*100)
|
||||
|
||||
from artist import Artist
|
71
src/user.py
71
src/user.py
@ -6,6 +6,7 @@ __license__ = "GNU Lesser General Public License"
|
||||
|
||||
from base import LastfmBase
|
||||
from lazylist import lazylist
|
||||
import playlist
|
||||
|
||||
class User(LastfmBase):
|
||||
"""A class representing an user."""
|
||||
@ -141,10 +142,27 @@ class User(LastfmBase):
|
||||
"""nearest neightbour of the user"""
|
||||
pass
|
||||
|
||||
@property
|
||||
@LastfmBase.cachedProperty
|
||||
def playlists(self):
|
||||
"""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
|
||||
def lovedTracks(self):
|
||||
@ -451,6 +469,11 @@ class User(LastfmBase):
|
||||
pass
|
||||
return gen()
|
||||
|
||||
def compare(self, other, limit = None):
|
||||
return Tasteometer.compare(self.__api,
|
||||
'user', 'user',
|
||||
self.name, other.name,
|
||||
limit)
|
||||
@property
|
||||
def library(self):
|
||||
return self.__lirary
|
||||
@ -474,6 +497,49 @@ class User(LastfmBase):
|
||||
def __repr__(self):
|
||||
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):
|
||||
"""A class representing the music library of the user."""
|
||||
def __init__(self, api, user):
|
||||
@ -649,5 +715,6 @@ from error import LastfmError, LastfmInvalidParametersError
|
||||
from event import Event
|
||||
from stats import Stats
|
||||
from tag import Tag
|
||||
from tasteometer import Tasteometer
|
||||
from track import Track
|
||||
from weeklychart import WeeklyChart, WeeklyAlbumChart, WeeklyArtistChart, WeeklyTrackChart
|
Loading…
Reference in New Issue
Block a user