Package lastfm :: Module track

[hide private]
[frames] | no frames]

# Source Code for Module lastfm.track

      1  #!/usr/bin/env python
      2
      3  __author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
      4  __version__ = "0.2"
      5  __license__ = "GNU Lesser General Public License"
      6
      7  from lastfm.base import LastfmBase
      8  from lastfm.mixins import Cacheable, Searchable, Sharable, Taggable
      9  from lastfm.lazylist import lazylist
     10  from lastfm.decorators import cached_property, top_property
     11
     12 -class Track(LastfmBase, Cacheable, Sharable, Searchable, Taggable):
     13      """A class representing a track."""
     14 -    def init(self,
     15                   api,
     16                   name = None,
     17                   mbid = None,
     18                   url = None,
     19                   duration = None,
     20                   streamable = None,
     21                   full_track = None,
     22                   artist = None,
     23                   album = None,
     24                   position = None,
     25                   image = None,
     26                   stats = None,
     27                   played_on = None,
     28                   loved_on = None,
     29                   wiki = None,
     30                   subject = None):
     31          if not isinstance(api, Api):
     32              raise InvalidParametersError("api reference must be supplied as an argument")
     33          Taggable.init(self, api)
     34          Sharable.init(self, api)
     35          self._api = api
     36          self._id = id
     37          self._name = name
     38          self._mbid = mbid
     39          self._url = url
     40          self._duration = duration
     41          self._streamable = streamable
     42          self._full_track = full_track
     43          self._artist = artist
     44          self._album = album
     45          self._position = position
     46          self._image = image
     47          self._stats = stats and Stats(
     48                               subject = self,
     49                               match = stats.match,
     50                               playcount = stats.playcount,
     51                               rank = stats.rank,
     52                               listeners = stats.listeners,
     53                              )
     54          self._played_on = played_on
     55          self._loved_on = loved_on
     56          self._wiki = wiki and Wiki(
     57                           subject = self,
     58                           published = wiki.published,
     59                           summary = wiki.summary,
     60                           content = wiki.content
     61                          )
     62          self._subject = subject
     63
     64      @property
     65 -    def id(self):
     66          """id of the track"""
     67          return self._id
     68
     69      @property
     70 -    def name(self):
     71          """name of the track"""
     72          return self._name
     73
     74      @property
     75 -    def mbid(self):
     76          """mbid of the track"""
     77          return self._mbid
     78
     79      @property
     80 -    def url(self):
     81          """url of the tracks's page"""
     82          return self._url
     83
     84      @property
     85 -    def duration(self):
     86          """duration of the tracks's page"""
     87          return self._duration
     88
     89      @property
     90 -    def streamable(self):
     91          """is the track streamable"""
     92          if self._streamable is None:
     93              self._fill_info()
     94          return self._streamable
     95
     96      @property
     97 -    def full_track(self):
     98          """is the full track streamable"""
     99          if self._full_track is None:
    100              self._fill_info()
    101          return self._full_track
    102
    103      @property
    104 -    def artist(self):
    105          """artist of the track"""
    106          return self._artist
    107
    108      @property
    109 -    def album(self):
    110          """artist of the track"""
    111          if self._album is None:
    112              self._fill_info()
    113          return self._album
    114
    115      @property
    116 -    def position(self):
    117          """position of the track"""
    118          if self._position is None:
    119              self._fill_info()
    120          return self._position
    121
    122      @property
    123 -    def image(self):
    124          """image of the track's album cover"""
    125          return self._image
    126
    127      @property
    128 -    def stats(self):
    129          """stats of the track"""
    130          return self._stats
    131
    132      @property
    133 -    def played_on(self):
    134          """datetime the track was last played"""
    135          return self._played_on
    136
    137      @property
    138 -    def loved_on(self):
    139          """datetime the track was marked 'loved'"""
    140          return self._loved_on
    141
    142      @property
    143 -    def wiki(self):
    144          """wiki of the track"""
    145          if self._wiki == "na":
    146              return None
    147          if self._wiki is None:
    148              self._fill_info()
    149          return self._wiki
    150
    151      @cached_property
    152 -    def similar(self):
    153          """tracks similar to this track"""
    154          params = Track._check_params(
    155                                      {'method': 'track.getSimilar'},
    156                                      self.artist.name,
    157                                      self.name,
    158                                      self.mbid
    159                                      )
    160          data = self._api._fetch_data(params).find('similartracks')
    161          return [
    162                  Track(
    163                        self._api,
    164                        subject = self,
    165                        name = t.findtext('name'),
    166                        artist = Artist(
    167                                        self._api,
    168                                        subject = self,
    169                                        name = t.findtext('artist/name'),
    170                                        mbid = t.findtext('artist/mbid'),
    171                                        url = t.findtext('artist/url')
    172                                        ),
    173                        mbid = t.findtext('mbid'),
    174                        stats = Stats(
    175                                      subject = t.findtext('name'),
    176                                      match = float(t.findtext('match'))
    177                                      ),
    178                        streamable = (t.findtext('streamable') == '1'),
    179                        full_track = (t.find('streamable').attrib['fulltrack'] == '1'),
    180                        image = dict([(i.get('size'), i.text) for i in t.findall('image')]),
    181                        )
    182                  for t in data.findall('track')
    183                  ]
    184
    185      @top_property("similar")
    186 -    def most_similar(self):
    187          """track most similar to this track"""
    188          pass
    189
    190      @cached_property
    191 -    def top_fans(self):
    192          """top fans of the track"""
    193          params = Track._check_params(
    194                                      {'method': 'track.getTopFans'},
    195                                      self.artist.name,
    196                                      self.name,
    197                                      self.mbid
    198                                      )
    199          data = self._api._fetch_data(params).find('topfans')
    200          return [
    201                  User(
    202                       self._api,
    203                       subject = self,
    204                       name = u.findtext('name'),
    205                       url = u.findtext('url'),
    206                       image = dict([(i.get('size'), i.text) for i in u.findall('image')]),
    207                       stats = Stats(
    208                                     subject = u.findtext('name'),
    209                                     weight = int(u.findtext('weight'))
    210                                     )
    211                       )
    212                  for u in data.findall('user')
    213                  ]
    214
    215      @top_property("top_fans")
    216 -    def top_fan(self):
    217          """topmost fan of the track"""
    218          pass
    219
    220      @cached_property
    221 -    def top_tags(self):
    222          """top tags for the track"""
    223          params = Track._check_params(
    224                                      {'method': 'track.getTopTags'},
    225                                      self.artist.name,
    226                                      self.name,
    227                                      self.mbid
    228                                      )
    229          data = self._api._fetch_data(params).find('toptags')
    230          return [
    231                  Tag(
    232                      self._api,
    233                      subject = self,
    234                      name = t.findtext('name'),
    235                      url = t.findtext('url'),
    236                      stats = Stats(
    237                                    subject = t.findtext('name'),
    238                                    count = int(t.findtext('count')),
    239                                    )
    240                      )
    241                  for t in data.findall('tag')
    242                  ]
    243
    244      @top_property("top_tags")
    245 -    def top_tag(self):
    246          """topmost tag for the track"""
    247          pass
    248
    249 -    def love(self):
    250          params = self._default_params({'method': 'track.love'})
    251          self._api._post_data(params)
    252
    253 -    def ban(self):
    254          params = self._default_params({'method': 'track.ban'})
    255          self._api._post_data(params)
    256
    257      @staticmethod
    258 -    def get_info(api,
    259                  artist = None,
    260                  track = None,
    261                  mbid = None):
    262          data = Track._fetch_data(api, artist, track, mbid)
    263          t = Track(
    264                    api,
    265                    name = data.findtext('name'),
    266                    artist = Artist(
    267                                    api,
    268                                    name = data.findtext('artist/name'),
    269                                    ),
    270                    )
    271          t._fill_info()
    272          return t
    273
    274 -    def _default_params(self, extra_params = {}):
    275          if not (self.artist and self.name):
    276              raise InvalidParametersError("artist and track have to be provided.")
    277          params = {'artist': self.artist.name, 'track': self.name}
    278          params.update(extra_params)
    279          return params
    280
    281      @staticmethod
    282 -    def _search_yield_func(api, track):
    283          return Track(
    284                       api,
    285                       name = track.findtext('name'),
    286                       artist = Artist(
    287                                       api,
    288                                       name=track.findtext('artist')
    289                                       ),
    290                      url = track.findtext('url'),
    291                      stats = Stats(
    292                                    subject=track.findtext('name'),
    293                                    listeners=int(track.findtext('listeners'))
    294                                    ),
    295                      streamable = (track.findtext('streamable') == '1'),
    296                      full_track = (track.find('streamable').attrib['fulltrack'] == '1'),
    297                      image = dict([(i.get('size'), i.text) for i in track.findall('image')]),
    298                      )
    299
    300      @staticmethod
    301 -    def _fetch_data(api,
    302                  artist = None,
    303                  track = None,
    304                  mbid = None):
    305          params = Track._check_params({'method': 'track.getInfo'}, artist, track, mbid)
    306          return api._fetch_data(params).find('track')
    307
    308 -    def _fill_info(self):
    309          data = Track._fetch_data(self._api, self.artist.name, self.name)
    310          self._id = int(data.findtext('id'))
    311          self._mbid = data.findtext('mbid')
    312          self._url = data.findtext('url')
    313          self._duration = int(data.findtext('duration'))
    314          self._streamable = (data.findtext('streamable') == '1')
    315          self._full_track = (data.find('streamable').attrib['fulltrack'] == '1')
    316
    317          self._image = dict([(i.get('size'), i.text) for i in data.findall('image')])
    318          self._stats = Stats(
    319                         subject = self,
    320                         listeners = int(data.findtext('listeners')),
    321                         playcount = int(data.findtext('playcount')),
    322                         )
    323          self._artist = Artist(
    324                          self._api,
    325                          name = data.findtext('artist/name'),
    326                          mbid = data.findtext('artist/mbid'),
    327                          url = data.findtext('artist/url')
    328                          )
    329          if data.find('album') is not None:
    330              self._album = Album(
    331                                   self._api,
    332                                   artist = self._artist,
    333                                   name = data.findtext('album/title'),
    334                                   mbid = data.findtext('album/mbid'),
    335                                   url = data.findtext('album/url'),
    336                                   image = dict([(i.get('size'), i.text) for i in data.findall('album/image')])
    337                                   )
    338              self._position = data.find('album').attrib['position'].strip() \
    339                  and int(data.find('album').attrib['position'])
    340          if data.find('wiki') is not None:
    341              self._wiki = Wiki(
    342                           self,
    343                           published = datetime(*(time.strptime(
    344                                                                data.findtext('wiki/published').strip(),
    345                                                                '%a, %d %b %Y %H:%M:%S +0000'
    346                                                                )[0:6])),
    347                           summary = data.findtext('wiki/summary'),
    348                           content = data.findtext('wiki/content')
    349                           )
    350          else:
    351              self._wiki = 'na'
    352
    353      @staticmethod
    354 -    def _check_params(params,
    355                        artist = None,
    356                        track = None,
    357                        mbid = None):
    358          if not ((artist and track) or mbid):
    359              raise InvalidParametersError("either (artist and track) or mbid has to be given as argument.")
    360
    361          if artist and track:
    362              params.update({'artist': artist, 'track': track})
    363          elif mbid:
    364              params.update({'mbid': mbid})
    365          return params
    366
    367      @staticmethod
    368 -    def _hash_func(*args, **kwds):
    369          try:
    370              return hash("%s%s" % (kwds['name'], hash(kwds['artist'])))
    371          except KeyError:
    372              raise InvalidParametersError("name and artist have to be provided for hashing")
    373
    374 -    def __hash__(self):
    375          return self.__class__._hash_func(name = self.name, artist = self.artist)
    376
    377 -    def __eq__(self, other):
    378          if self.mbid and other.mbid:
    379              return self.mbid == other.mbid
    380          if self.url and other.url:
    381              return self.url == other.url
    382          if (self.name and self.artist) and (other.name and other.artist):
    383              return (self.name == other.name) and (self.artist == other.artist)
    384          return super(Track, self).__eq__(other)
    385
    386 -    def __lt__(self, other):
    387          return self.name < other.name
    388
    389 -    def __repr__(self):
    390          return "<lastfm.Track: '%s' by %s>" % (self.name, self.artist.name)
    391
    392  import time
    393  from datetime import datetime
    394
    395  from lastfm.api import Api
    396  from lastfm.artist import Artist
    397  from lastfm.album import Album
    398  from lastfm.error import InvalidParametersError
    399  from lastfm.stats import Stats
    400  from lastfm.tag import Tag
    401  from lastfm.user import User
    402  from lastfm.wiki import Wiki
    403