python-lastfm/lastfm/track.py

416 lines
15 KiB
Python
Raw Normal View History

2008-07-10 22:25:05 +05:30
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
2008-07-10 22:25:05 +05:30
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
2008-07-10 22:25:05 +05:30
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, searchable, sharable, taggable
from lastfm.decorators import cached_property, top_property
2008-07-15 00:38:39 +05:30
@sharable
@taggable
@searchable
@cacheable
class Track(LastfmBase):
2008-07-10 22:25:05 +05:30
"""A class representing a track."""
2008-07-15 00:38:39 +05:30
def init(self,
2008-07-14 15:50:18 +05:30
api,
2008-07-10 22:25:05 +05:30
name = None,
mbid = None,
url = None,
duration = None,
2008-07-10 22:25:05 +05:30
streamable = None,
full_track = None,
2008-07-10 22:25:05 +05:30
artist = None,
album = None,
position = None,
2008-07-10 22:25:05 +05:30
image = None,
stats = None,
played_on = None,
loved_on = None,
wiki = None,
subject = None):
2008-07-16 18:36:42 +05:30
if not isinstance(api, Api):
raise InvalidParametersError("api reference must be supplied as an argument")
2008-12-30 19:21:04 +05:30
self._api = api
self._id = id
self._name = name
self._mbid = mbid
self._url = url
self._duration = duration
self._streamable = streamable
self._full_track = full_track
self._artist = artist
self._album = album
self._position = position
self._image = image
self._stats = stats and Stats(
subject = self,
match = stats.match,
playcount = stats.playcount,
rank = stats.rank,
listeners = stats.listeners,
)
2008-12-30 19:21:04 +05:30
self._played_on = played_on
self._loved_on = loved_on
self._wiki = wiki and Wiki(
subject = self,
published = wiki.published,
summary = wiki.summary,
content = wiki.content
)
self._subject = subject
2008-12-30 19:21:04 +05:30
@property
def id(self):
"""id of the track"""
2008-12-30 19:21:04 +05:30
return self._id
@property
def name(self):
"""name of the track"""
2008-12-30 19:21:04 +05:30
return self._name
2008-07-10 22:25:05 +05:30
@property
def mbid(self):
"""mbid of the track"""
2008-12-30 19:21:04 +05:30
return self._mbid
2008-07-10 22:25:05 +05:30
@property
def url(self):
"""url of the tracks's page"""
2008-12-30 19:21:04 +05:30
return self._url
@property
def duration(self):
"""duration of the tracks's page"""
2008-12-30 19:21:04 +05:30
return self._duration
2008-07-10 22:25:05 +05:30
@property
def streamable(self):
"""is the track streamable"""
2008-12-30 19:21:04 +05:30
if self._streamable is None:
self._fill_info()
2008-12-30 19:21:04 +05:30
return self._streamable
2008-07-10 22:25:05 +05:30
@property
def full_track(self):
"""is the full track streamable"""
2008-12-30 19:21:04 +05:30
if self._full_track is None:
self._fill_info()
2008-12-30 19:21:04 +05:30
return self._full_track
@property
def artist(self):
"""artist of the track"""
2008-12-30 19:21:04 +05:30
return self._artist
2008-07-10 22:25:05 +05:30
@property
def album(self):
"""artist of the track"""
2008-12-30 19:21:04 +05:30
if self._album is None:
self._fill_info()
2008-12-30 19:21:04 +05:30
return self._album
@property
def position(self):
"""position of the track"""
2008-12-30 19:21:04 +05:30
if self._position is None:
self._fill_info()
2008-12-30 19:21:04 +05:30
return self._position
@property
def image(self):
"""image of the track's album cover"""
2008-12-30 19:21:04 +05:30
return self._image
2008-07-10 22:25:05 +05:30
@property
def stats(self):
"""stats of the track"""
2008-12-30 19:21:04 +05:30
return self._stats
2008-08-18 21:42:46 +05:30
@property
2008-12-30 19:21:04 +05:30
def played_on(self):
2008-08-18 21:42:46 +05:30
"""datetime the track was last played"""
2008-12-30 19:21:04 +05:30
return self._played_on
2008-08-18 21:42:46 +05:30
@property
2008-12-30 19:21:04 +05:30
def loved_on(self):
2008-08-18 21:42:46 +05:30
"""datetime the track was marked 'loved'"""
2008-12-30 19:21:04 +05:30
return self._loved_on
@property
def wiki(self):
"""wiki of the track"""
2008-12-30 19:21:04 +05:30
if self._wiki == "na":
return None
2008-12-30 19:21:04 +05:30
if self._wiki is None:
self._fill_info()
2008-12-30 19:21:04 +05:30
return self._wiki
2008-08-18 21:42:46 +05:30
@cached_property
def similar(self):
"""tracks similar to this track"""
params = Track._check_params(
{'method': 'track.getSimilar'},
self.artist.name,
self.name,
self.mbid
)
2008-12-30 19:21:04 +05:30
data = self._api._fetch_data(params).find('similartracks')
return [
Track(
2008-12-30 19:21:04 +05:30
self._api,
subject = self,
name = t.findtext('name'),
artist = Artist(
2008-12-30 19:21:04 +05:30
self._api,
subject = self,
name = t.findtext('artist/name'),
mbid = t.findtext('artist/mbid'),
url = t.findtext('artist/url')
),
mbid = t.findtext('mbid'),
stats = Stats(
subject = t.findtext('name'),
match = float(t.findtext('match'))
),
streamable = (t.findtext('streamable') == '1'),
2008-12-30 19:21:04 +05:30
full_track = (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')
]
2008-08-18 21:42:46 +05:30
@top_property("similar")
def most_similar(self):
"""track most similar to this track"""
pass
2008-08-18 21:42:46 +05:30
@cached_property
def top_fans(self):
"""top fans of the track"""
params = Track._check_params(
{'method': 'track.getTopFans'},
self.artist.name,
self.name,
self.mbid
)
2008-12-30 19:21:04 +05:30
data = self._api._fetch_data(params).find('topfans')
return [
User(
2008-12-30 19:21:04 +05:30
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')
]
2008-08-18 21:42:46 +05:30
@top_property("top_fans")
def top_fan(self):
"""topmost fan of the track"""
pass
2008-08-18 21:42:46 +05:30
@cached_property
def top_tags(self):
"""top tags for the track"""
params = Track._check_params(
{'method': 'track.getTopTags'},
self.artist.name,
self.name,
self.mbid
)
2008-12-30 19:21:04 +05:30
data = self._api._fetch_data(params).find('toptags')
return [
Tag(
2008-12-30 19:21:04 +05:30
self._api,
subject = self,
name = t.findtext('name'),
url = t.findtext('url'),
stats = Stats(
subject = t.findtext('name'),
count = int(t.findtext('count')),
)
)
for t in data.findall('tag')
]
2008-08-18 21:42:46 +05:30
@top_property("top_tags")
def top_tag(self):
"""topmost tag for the track"""
pass
2008-12-30 19:21:04 +05:30
def love(self):
params = self._default_params({'method': 'track.love'})
2008-12-30 19:21:04 +05:30
self._api._post_data(params)
def ban(self):
params = self._default_params({'method': 'track.ban'})
2008-12-30 19:21:04 +05:30
self._api._post_data(params)
@staticmethod
def get_info(api,
artist = None,
track = None,
mbid = None):
data = Track._fetch_data(api, artist, track, mbid)
t = Track(
api,
name = data.findtext('name'),
artist = Artist(
api,
name = data.findtext('artist/name'),
),
)
t._fill_info()
return t
@classmethod
def get_all(cls, seed_track):
def gen():
for artist in Artist.get_all(seed_track.artist):
for track in artist.top_tracks:
yield track
return super(Track, cls).get_all(seed_track, ['name', 'artist'],
lambda api, hsh: gen())
2008-12-30 19:21:04 +05:30
def _default_params(self, extra_params = None):
2008-12-30 19:21:04 +05:30
if not (self.artist and self.name):
raise InvalidParametersError("artist and track have to be provided.")
params = {'artist': self.artist.name, 'track': self.name}
if extra_params is not None:
params.update(extra_params)
2008-12-30 19:21:04 +05:30
return params
2008-08-18 21:42:46 +05:30
2008-07-14 15:50:18 +05:30
@staticmethod
def _search_yield_func(api, track):
return Track(
api,
name = track.findtext('name'),
artist = Artist(
api,
name=track.findtext('artist')
),
url = track.findtext('url'),
stats = Stats(
subject=track.findtext('name'),
listeners=int(track.findtext('listeners'))
),
streamable = (track.findtext('streamable') == '1'),
2008-12-30 19:21:04 +05:30
full_track = (track.find('streamable').attrib['fulltrack'] == '1'),
image = dict([(i.get('size'), i.text) for i in track.findall('image')]),
)
2008-12-30 19:21:04 +05:30
@staticmethod
def _fetch_data(api,
artist = None,
track = None,
mbid = None):
params = Track._check_params({'method': 'track.getInfo'}, artist, track, mbid)
return api._fetch_data(params).find('track')
2008-12-30 19:21:04 +05:30
def _fill_info(self):
2008-12-30 19:21:04 +05:30
data = Track._fetch_data(self._api, self.artist.name, self.name)
self._id = int(data.findtext('id'))
self._mbid = data.findtext('mbid')
self._url = data.findtext('url')
self._duration = int(data.findtext('duration'))
2009-03-04 17:20:26 +05:30
self._streamable = (data.findtext('streamable') == '1')
self._full_track = (data.find('streamable').attrib['fulltrack'] == '1')
2008-12-30 19:21:04 +05:30
self._image = dict([(i.get('size'), i.text) for i in data.findall('image')])
self._stats = Stats(
subject = self,
listeners = int(data.findtext('listeners')),
playcount = int(data.findtext('playcount')),
)
2008-12-30 19:21:04 +05:30
self._artist = Artist(
self._api,
name = data.findtext('artist/name'),
mbid = data.findtext('artist/mbid'),
url = data.findtext('artist/url')
)
2009-03-04 17:20:26 +05:30
if data.find('album') is not None:
self._album = Album(
self._api,
artist = self._artist,
name = data.findtext('album/title'),
mbid = data.findtext('album/mbid'),
url = data.findtext('album/url'),
image = dict([(i.get('size'), i.text) for i in data.findall('album/image')])
)
self._position = data.find('album').attrib['position'].strip() \
and int(data.find('album').attrib['position'])
if data.find('wiki') is not None:
2008-12-30 19:21:04 +05:30
self._wiki = Wiki(
self,
published = datetime(*(time.strptime(
data.findtext('wiki/published').strip(),
'%a, %d %b %Y %H:%M:%S +0000'
)[0:6])),
summary = data.findtext('wiki/summary'),
content = data.findtext('wiki/content')
)
else:
2008-12-30 19:21:04 +05:30
self._wiki = 'na'
2008-08-18 21:42:46 +05:30
@staticmethod
def _check_params(params,
artist = None,
track = None,
mbid = None):
if not ((artist and track) or mbid):
raise InvalidParametersError("either (artist and track) or mbid has to be given as argument.")
if artist and track:
params.update({'artist': artist, 'track': track})
elif mbid:
params.update({'mbid': mbid})
return params
2008-07-15 00:38:39 +05:30
@staticmethod
2008-12-30 19:21:04 +05:30
def _hash_func(*args, **kwds):
2008-07-15 00:38:39 +05:30
try:
return hash("%s%s" % (kwds['name'], hash(kwds['artist'])))
except KeyError:
raise InvalidParametersError("name and artist have to be provided for hashing")
2008-08-18 21:42:46 +05:30
2008-07-15 00:38:39 +05:30
def __hash__(self):
2008-12-30 19:21:04 +05:30
return self.__class__._hash_func(name = self.name, artist = self.artist)
2008-08-18 21:42:46 +05:30
2008-07-15 00:38:39 +05:30
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
if (self.name and self.artist) and (other.name and other.artist):
return (self.name == other.name) and (self.artist == other.artist)
return super(Track, self).__eq__(other)
2008-08-18 21:42:46 +05:30
2008-07-15 00:38:39 +05:30
def __lt__(self, other):
return self.name < other.name
2008-08-18 21:42:46 +05:30
2008-07-15 00:38:39 +05:30
def __repr__(self):
2008-07-16 18:36:42 +05:30
return "<lastfm.Track: '%s' by %s>" % (self.name, self.artist.name)
import time
from datetime import datetime
from lastfm.api import Api
from lastfm.artist import Artist
from lastfm.album import Album
from lastfm.error import InvalidParametersError
from lastfm.stats import Stats
from lastfm.tag import Tag
from lastfm.user import User
from lastfm.wiki import Wiki