420 lines
15 KiB
Python
420 lines
15 KiB
Python
#!/usr/bin/env python
|
|
|
|
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
|
|
__version__ = "0.1"
|
|
__license__ = "GNU Lesser General Public License"
|
|
|
|
from base import LastfmBase
|
|
from lazylist import lazylist
|
|
|
|
class Artist(LastfmBase):
|
|
"""A class representing an artist."""
|
|
def init(self,
|
|
api,
|
|
name = None,
|
|
mbid = None,
|
|
url = None,
|
|
image = None,
|
|
streamable = None,
|
|
stats = None,
|
|
similar = None,
|
|
topTags = None,
|
|
bio = None):
|
|
if not isinstance(api, Api):
|
|
raise LastfmInvalidParametersError("api reference must be supplied as an argument")
|
|
self.__api = api
|
|
self.__name = name
|
|
self.__mbid = mbid
|
|
self.__url = url
|
|
self.__image = image
|
|
self.__streamable = streamable
|
|
self.__stats = stats and Stats(
|
|
subject = self,
|
|
listeners = stats.listeners,
|
|
playcount = stats.playcount,
|
|
match = stats.match,
|
|
rank = stats.rank
|
|
)
|
|
self.__similar = similar
|
|
self.__topTags = topTags
|
|
self.__bio = bio and Artist.Bio(
|
|
artist = self,
|
|
published = bio.published,
|
|
summary = bio.summary,
|
|
content = bio.content
|
|
)
|
|
|
|
@property
|
|
def name(self):
|
|
"""name of the artist"""
|
|
return self.__name
|
|
|
|
@property
|
|
def mbid(self):
|
|
"""mbid of the artist"""
|
|
if self.__mbid is None:
|
|
self._fillInfo()
|
|
return self.__mbid
|
|
|
|
@property
|
|
def url(self):
|
|
"""url of the artist's page"""
|
|
if self.__url is None:
|
|
self._fillInfo()
|
|
return self.__url
|
|
|
|
@property
|
|
def image(self):
|
|
"""images of the artist"""
|
|
if self.__image is None:
|
|
self._fillInfo()
|
|
return self.__image
|
|
|
|
@property
|
|
def streamable(self):
|
|
"""is the artist streamable"""
|
|
if self.__streamable is None:
|
|
self._fillInfo()
|
|
return self.__streamable
|
|
|
|
@property
|
|
def stats(self):
|
|
"""stats for the artist"""
|
|
if self.__stats is None:
|
|
self._fillInfo()
|
|
return self.__stats
|
|
|
|
def getSimilar(self, limit = None):
|
|
params = {'method': 'artist.getsimilar', 'artist': self.__name}
|
|
if limit is not None:
|
|
params.update({'limit': limit})
|
|
data = self.__api._fetchData(params).find('similarartists')
|
|
self.__similar = [
|
|
Artist(
|
|
self.__api,
|
|
subject = self,
|
|
name = a.findtext('name'),
|
|
mbid = a.findtext('mbid'),
|
|
stats = Stats(
|
|
subject = a.findtext('name'),
|
|
match = float(a.findtext('match')),
|
|
),
|
|
url = 'http://' + a.findtext('url'),
|
|
image = {'large': a.findtext('image')}
|
|
)
|
|
for a in data.findall('artist')
|
|
]
|
|
return self.__similar
|
|
|
|
@property
|
|
def similar(self):
|
|
"""artists similar to this artist"""
|
|
if self.__similar is None or len(self.__similar) < 6:
|
|
return self.getSimilar()
|
|
return self.__similar
|
|
|
|
@LastfmBase.topProperty("similar")
|
|
def mostSimilar(self):
|
|
"""artist most similar to this artist"""
|
|
pass
|
|
|
|
@property
|
|
def topTags(self):
|
|
"""top tags for the artist"""
|
|
if self.__topTags is None or len(self.__topTags) < 6:
|
|
params = {
|
|
'method': 'artist.gettoptags',
|
|
'artist': self.__name
|
|
}
|
|
data = self.__api._fetchData(params).find('toptags')
|
|
self.__topTags = [
|
|
Tag(
|
|
self.__api,
|
|
subject = self,
|
|
name = t.findtext('name'),
|
|
url = t.findtext('url')
|
|
)
|
|
for t in data.findall('tag')
|
|
]
|
|
return self.__topTags
|
|
|
|
@LastfmBase.topProperty("topTags")
|
|
def topTag(self):
|
|
"""top tag for the artist"""
|
|
pass
|
|
|
|
@property
|
|
def bio(self):
|
|
"""biography of the artist"""
|
|
if self.__bio is None:
|
|
self._fillInfo()
|
|
return self.__bio
|
|
|
|
@LastfmBase.cachedProperty
|
|
def events(self):
|
|
"""events for the artist"""
|
|
params = {'method': 'artist.getevents', 'artist': self.name}
|
|
data = self.__api._fetchData(params).find('events')
|
|
|
|
return [
|
|
Event.createFromData(self.__api, e)
|
|
for e in data.findall('event')
|
|
]
|
|
|
|
@LastfmBase.cachedProperty
|
|
def topAlbums(self):
|
|
"""top albums of the artist"""
|
|
params = {'method': 'artist.gettopalbums', 'artist': self.name}
|
|
data = self.__api._fetchData(params).find('topalbums')
|
|
|
|
return [
|
|
Album(
|
|
self.__api,
|
|
subject = self,
|
|
name = a.findtext('name'),
|
|
artist = self,
|
|
mbid = a.findtext('mbid'),
|
|
url = a.findtext('url'),
|
|
image = dict([(i.get('size'), i.text) for i in a.findall('image')]),
|
|
stats = Stats(
|
|
subject = a.findtext('name'),
|
|
playcount = int(a.findtext('playcount')),
|
|
rank = int(a.attrib['rank'])
|
|
)
|
|
)
|
|
for a in data.findall('album')
|
|
]
|
|
|
|
@LastfmBase.topProperty("topAlbums")
|
|
def topAlbum(self):
|
|
"""top album of the artist"""
|
|
pass
|
|
|
|
@LastfmBase.cachedProperty
|
|
def topFans(self):
|
|
"""top fans of the artist"""
|
|
params = {'method': 'artist.gettopfans', 'artist': self.name}
|
|
data = self.__api._fetchData(params).find('topfans')
|
|
return [
|
|
User(
|
|
self.__api,
|
|
subject = self,
|
|
name = u.findtext('name'),
|
|
url = u.findtext('url'),
|
|
image = dict([(i.get('size'), i.text) for i in u.findall('image')]),
|
|
stats = Stats(
|
|
subject = u.findtext('name'),
|
|
weight = int(u.findtext('weight'))
|
|
)
|
|
)
|
|
for u in data.findall('user')
|
|
]
|
|
|
|
@LastfmBase.topProperty("topFans")
|
|
def topFan(self):
|
|
"""top fan of the artist"""
|
|
pass
|
|
|
|
@LastfmBase.cachedProperty
|
|
def topTracks(self):
|
|
"""top tracks of the artist"""
|
|
params = {'method': 'artist.gettoptracks', 'artist': self.name}
|
|
data = self.__api._fetchData(params).find('toptracks')
|
|
return [
|
|
Track(
|
|
self.__api,
|
|
subject = self,
|
|
name = t.findtext('name'),
|
|
artist = self,
|
|
mbid = t.findtext('mbid'),
|
|
stats = Stats(
|
|
subject = t.findtext('name'),
|
|
playcount = int(t.findtext('playcount')),
|
|
rank = int(t.attrib['rank'])
|
|
),
|
|
streamable = (t.findtext('streamable') == '1'),
|
|
fullTrack = (t.find('streamable').attrib['fulltrack'] == '1'),
|
|
image = dict([(i.get('size'), i.text) for i in t.findall('image')]),
|
|
)
|
|
for t in data.findall('track')
|
|
]
|
|
|
|
@LastfmBase.topProperty("topTracks")
|
|
def topTrack(self):
|
|
"""topmost fan of the artist"""
|
|
pass
|
|
|
|
@staticmethod
|
|
def search(api,
|
|
artist,
|
|
limit = None):
|
|
params = {'method': 'artist.search', 'artist': artist}
|
|
if limit:
|
|
params.update({'limit': limit})
|
|
|
|
@lazylist
|
|
def gen(lst):
|
|
data = api._fetchData(params).find('results')
|
|
totalPages = int(data.findtext("{%s}totalResults" % Api.SEARCH_XMLNS))/ \
|
|
int(data.findtext("{%s}itemsPerPage" % Api.SEARCH_XMLNS)) + 1
|
|
|
|
@lazylist
|
|
def gen2(lst, data):
|
|
for a in data.findall('artistmatches/artist'):
|
|
yield Artist(
|
|
api,
|
|
name = a.findtext('name'),
|
|
mbid = a.findtext('mbid'),
|
|
url = a.findtext('url'),
|
|
image = dict([(i.get('size'), i.text) for i in a.findall('image')]),
|
|
streamable = (a.findtext('streamable') == '1'),
|
|
)
|
|
|
|
for a in gen2(data):
|
|
yield a
|
|
|
|
for page in xrange(2, totalPages+1):
|
|
params.update({'page': page})
|
|
data = api._fetchData(params).find('results')
|
|
for a in gen2(data):
|
|
yield a
|
|
return gen()
|
|
|
|
@staticmethod
|
|
def _fetchData(api,
|
|
artist = None,
|
|
mbid = None):
|
|
params = {'method': 'artist.getinfo'}
|
|
if not (artist or mbid):
|
|
raise LastfmInvalidParametersError("either artist or mbid has to be given as argument.")
|
|
if artist:
|
|
params.update({'artist': artist})
|
|
elif mbid:
|
|
params.update({'mbid': mbid})
|
|
return api._fetchData(params).find('artist')
|
|
|
|
def _fillInfo(self):
|
|
data = Artist._fetchData(self.__api, self.name)
|
|
self.__name = data.findtext('name')
|
|
self.__mbid = data.findtext('mbid')
|
|
self.__url = data.findtext('url')
|
|
self.__image = dict([(i.get('size'), i.text) for i in data.findall('image')])
|
|
self.__streamable = (data.findtext('streamable') == 1)
|
|
self.__stats = Stats(
|
|
subject = self,
|
|
listeners = int(data.findtext('stats/listeners')),
|
|
playcount = int(data.findtext('stats/playcount'))
|
|
)
|
|
self.__similar = [
|
|
Artist(
|
|
self.__api,
|
|
subject = self,
|
|
name = a.findtext('name'),
|
|
url = a.findtext('url'),
|
|
image = dict([(i.get('size'), i.text) for i in a.findall('image')])
|
|
)
|
|
for a in data.findall('similar/artist')
|
|
]
|
|
self.__topTags = [
|
|
Tag(
|
|
self.__api,
|
|
subject = self,
|
|
name = t.findtext('name'),
|
|
url = t.findtext('url')
|
|
)
|
|
for t in data.findall('tags/tag')
|
|
]
|
|
self.__bio = Artist.Bio(
|
|
self,
|
|
published = datetime(*(time.strptime(
|
|
data.findtext('bio/published').strip(),
|
|
'%a, %d %b %Y %H:%M:%S +0000'
|
|
)[0:6])),
|
|
summary = data.findtext('bio/summary'),
|
|
content = data.findtext('bio/content')
|
|
)
|
|
|
|
@staticmethod
|
|
def getInfo(api,
|
|
artist = None,
|
|
mbid = None):
|
|
data = Artist._fetchData(api, artist, mbid)
|
|
|
|
a = Artist(api, name = data.findtext('name'))
|
|
if a.bio is None:
|
|
a._fillInfo()
|
|
return a
|
|
|
|
@staticmethod
|
|
def hashFunc(*args, **kwds):
|
|
try:
|
|
return hash(kwds['name'].lower())
|
|
except KeyError:
|
|
try:
|
|
return hash(args[1].lower())
|
|
except IndexError:
|
|
raise LastfmInvalidParametersError("name has to be provided for hashing")
|
|
|
|
def __hash__(self):
|
|
return self.__class__.hashFunc(name = self.name)
|
|
|
|
def __eq__(self, other):
|
|
if self.mbid and other.mbid:
|
|
return self.mbid == other.mbid
|
|
if self.url and other.url:
|
|
return self.url == other.url
|
|
return self.name == other.name
|
|
|
|
def __lt__(self, other):
|
|
return self.name < other.name
|
|
|
|
def __repr__(self):
|
|
return "<lastfm.Artist: %s>" % self.__name
|
|
|
|
class Bio(object):
|
|
"""A class representing the biography of an artist."""
|
|
def __init__(self,
|
|
artist,
|
|
published = None,
|
|
summary = None,
|
|
content = None):
|
|
self.__artist = artist
|
|
self.__published = published
|
|
self.__summary = summary
|
|
self.__content = content
|
|
|
|
@property
|
|
def artist(self):
|
|
"""artist for which the biography is"""
|
|
return self.__artist
|
|
|
|
@property
|
|
def published(self):
|
|
"""publication time of the biography"""
|
|
return self.__published
|
|
|
|
@property
|
|
def summary(self):
|
|
"""summary of the biography"""
|
|
return self.__summary
|
|
|
|
@property
|
|
def content(self):
|
|
"""content of the biography"""
|
|
return self.__content
|
|
|
|
def __repr__(self):
|
|
return "<lastfm.artist.Bio: for artist '%s'>" % self.__artist.name
|
|
|
|
from datetime import datetime
|
|
import time
|
|
|
|
from album import Album
|
|
from api import Api
|
|
from error import LastfmInvalidParametersError
|
|
from event import Event
|
|
from stats import Stats
|
|
from tag import Tag
|
|
from track import Track
|
|
from user import User
|