Package lastfm :: Module artist

[hide private]
[frames] | no frames]

# Source Code for Module lastfm.artist

      1  #!/usr/bin/env python
      2  """Module for calling Artist related last.fm web services API methods"""
      3
      4  __author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
      5  __version__ = "0.2"
      6  __license__ = "GNU Lesser General Public License"
      7
      8  from lastfm.base import LastfmBase
      9  from lastfm.mixins import Cacheable, Searchable, Sharable, Shoutable, Taggable
     10  from lastfm.lazylist import lazylist
     11  from lastfm.decorators import cached_property, top_property
     12
     13 -class Artist(LastfmBase, Cacheable, Sharable, Shoutable, Searchable, Taggable):
     14      """A class representing an artist."""
     15 -    def init(self,
     16                   api,
     17                   name = None,
     18                   mbid = None,
     19                   url = None,
     20                   image = None,
     21                   streamable = None,
     22                   stats = None,
     23                   similar = None,
     24                   top_tags = None,
     25                   bio = None,
     26                   subject = None):
     27          """
     28          Create an Artist object by providing all the data related to it.
     29
     30          @param api:             an instance of L{Api}
     31          @type api:              L{Api}
     32          @param name:            the artist name
     33          @type name:             L{str}
     34          @param mbid:            MBID of the artist
     35          @type mbid:             L{str}
     36          @param url:             URL of the artist on last.fm
     37          @type url:              L{str}
     38          @param image:           the images of the artist in various sizes
     39          @type image:            L{dict}
     40          @param streamable:      flag indicating if the artist is streamable from last.fm
     41          @type streamable:       L{bool}
     42          @param stats:           the artist statistics
     43          @type stats:            L{Stats}
     44          @param similar:         artists similar to the provided artist
     45          @type similar:          L{list} of L{Artist}
     46          @param top_tags:        top tags for the artist
     47          @type top_tags:         L{list} of L{Tag}
     48          @param bio:             biography of the artist
     49          @type bio:              L{Wiki}
     50          @param subject:         the subject to which this instance belongs to
     51          @type subject:          L{User} OR L{Artist} OR L{Tag} OR L{Track} OR L{WeeklyChart}
     52
     53          @raise InvalidParametersError: If an instance of L{Api} is not provided as the first
     54                                         parameter then an Exception is raised.
     55          """
     56          if not isinstance(api, Api):
     57              raise InvalidParametersError("api reference must be supplied as an argument")
     58          Sharable.init(self, api)
     59          Shoutable.init(self, api)
     60          Taggable.init(self, api)
     61
     62          self._api = api
     63          self._name = name
     64          self._mbid = mbid
     65          self._url = url
     66          self._image = image
     67          self._streamable = streamable
     68          self._stats = stats and Stats(
     69                               subject = self,
     70                               listeners = stats.listeners,
     71                               playcount = stats.playcount,
     72                               weight = stats.weight,
     73                               match = stats.match,
     74                               rank = stats.rank
     75                              )
     76          self._similar = similar
     77          self._top_tags = top_tags
     78          self._bio = bio and Wiki(
     79                           subject = self,
     80                           published = bio.published,
     81                           summary = bio.summary,
     82                           content = bio.content
     83                          )
     84          self._subject = subject
     85
     86      @property
     87 -    def name(self):
     88          """
     89          name of the artist
     90          @rtype: L{str}
     91          """
     92          return self._name
     93
     94      @property
     95 -    def mbid(self):
     96          """
     97          MBID of the artist
     98          @rtype: L{str}
     99          """
    100          if self._mbid is None:
    101              self._fill_info()
    102          return self._mbid
    103
    104      @property
    105 -    def url(self):
    106          """
    107          url of the artist's page
    108          @rtype: L{str}
    109          """
    110          if self._url is None:
    111              self._fill_info()
    112          return self._url
    113
    114      @property
    115 -    def image(self):
    116          """
    117          images of the artist
    118          @rtype: L{dict}
    119          """
    120          if self._image is None:
    121              self._fill_info()
    122          return self._image
    123
    124      @property
    125 -    def streamable(self):
    126          """
    127          is the artist streamable on last.fm
    128          @rtype: L{bool}
    129          """
    130          if self._streamable is None:
    131              self._fill_info()
    132          return self._streamable
    133
    134      @property
    135 -    def stats(self):
    136          """
    137          stats for the artist
    138          @rtype: L{Stats}
    139          """
    140          if self._stats is None:
    141              self._fill_info()
    142          return self._stats
    143
    144 -    def get_similar(self, limit = None):
    145          """
    146          Get the artists similar to this artist.
    147
    148          @param limit: the number of artists returned (optional)
    149          @type limit:  L{int}
    150
    151          @return:      artists similar to this artist
    152          @rtype:       L{list} of L{Artist}
    153          """
    154          params = self._default_params({'method': 'artist.getSimilar'})
    155          if limit is not None:
    156              params.update({'limit': limit})
    157          data = self._api._fetch_data(params).find('similarartists')
    158          self._similar = [
    159                            Artist(
    160                                   self._api,
    161                                   subject = self,
    162                                   name = a.findtext('name'),
    163                                   mbid = a.findtext('mbid'),
    164                                   stats = Stats(
    165                                                 subject = a.findtext('name'),
    166                                                 match = float(a.findtext('match')),
    167                                                 ),
    168                                   url = 'http://' + a.findtext('url'),
    169                                   image = {'large': a.findtext('image')}
    170                                   )
    171                            for a in data.findall('artist')
    172                            ]
    173          return self._similar[:]
    174
    175      @property
    176 -    def similar(self):
    177          """
    178          artists similar to this artist
    179          @rtype: L{list} of L{Artist}
    180          """
    181          if self._similar is None or len(self._similar) < 6:
    182              return self.get_similar()
    183          return self._similar[:]
    184
    185      @top_property("similar")
    186 -    def most_similar(self):
    187          """
    188          artist most similar to this artist
    189          @rtype: L{Artist}
    190          """
    191          pass
    192
    193      @property
    194 -    def top_tags(self):
    195          """
    196          top tags for the artist
    197          @rtype: L{list} of L{Tag}
    198          """
    199          if self._top_tags is None or len(self._top_tags) < 6:
    200              params = self._default_params({'method': 'artist.getTopTags'})
    201              data = self._api._fetch_data(params).find('toptags')
    202              self._top_tags = [
    203                                Tag(
    204                                    self._api,
    205                                    subject = self,
    206                                    name = t.findtext('name'),
    207                                    url = t.findtext('url')
    208                                    )
    209                                for t in data.findall('tag')
    210                                ]
    211          return self._top_tags[:]
    212
    213      @top_property("top_tags")
    214 -    def top_tag(self):
    215          """
    216          top tag for the artist
    217          @rtype: L{Tag}
    218          """
    219          pass
    220
    221      @property
    222 -    def bio(self):
    223          """
    224          biography of the artist
    225          @rtype: L{Wiki}
    226          """
    227          if self._bio is None:
    228              self._fill_info()
    229          return self._bio
    230
    231      @cached_property
    232 -    def events(self):
    233          """
    234          events for the artist
    235          @rtype: L{lazylist} of L{Event}
    236          """
    237          params = self._default_params({'method': 'artist.getEvents'})
    238          data = self._api._fetch_data(params).find('events')
    239
    240          return [
    241                  Event.create_from_data(self._api, e)
    242                  for e in data.findall('event')
    243                  ]
    244
    245      @cached_property
    246 -    def top_albums(self):
    247          """
    248          top albums of the artist
    249          @rtype: L{list} of L{Album}
    250          """
    251          params = self._default_params({'method': 'artist.getTopAlbums'})
    252          data = self._api._fetch_data(params).find('topalbums')
    253
    254          return [
    255                  Album(
    256                       self._api,
    257                       subject = self,
    258                       name = a.findtext('name'),
    259                       artist = self,
    260                       mbid = a.findtext('mbid'),
    261                       url = a.findtext('url'),
    262                       image = dict([(i.get('size'), i.text) for i in a.findall('image')]),
    263                       stats = Stats(
    264                                     subject = a.findtext('name'),
    265                                     playcount = int(a.findtext('playcount')),
    266                                     rank = int(a.attrib['rank'])
    267                                     )
    268                       )
    269                  for a in data.findall('album')
    270                  ]
    271
    272      @top_property("top_albums")
    273 -    def top_album(self):
    274          """
    275          top album of the artist
    276          @rtype: L{Album}
    277          """
    278          pass
    279
    280      @cached_property
    281 -    def top_fans(self):
    282          """
    283          top fans of the artist
    284          @rtype: L{list} of L{User}
    285          """
    286          params = self._default_params({'method': 'artist.getTopFans'})
    287          data = self._api._fetch_data(params).find('topfans')
    288          return [
    289                  User(
    290                       self._api,
    291                       subject = self,
    292                       name = u.findtext('name'),
    293                       url = u.findtext('url'),
    294                       image = dict([(i.get('size'), i.text) for i in u.findall('image')]),
    295                       stats = Stats(
    296                                     subject = u.findtext('name'),
    297                                     weight = int(u.findtext('weight'))
    298                                     )
    299                       )
    300                  for u in data.findall('user')
    301                  ]
    302
    303      @top_property("top_fans")
    304 -    def top_fan(self):
    305          """
    306          top fan of the artist
    307          @rtype: L{User}"""
    308          pass
    309
    310      @cached_property
    311 -    def top_tracks(self):
    312          """
    313          top tracks of the artist
    314          @rtype: L{list} of L{Track}
    315          """
    316          params = self._default_params({'method': 'artist.getTopTracks'})
    317          data = self._api._fetch_data(params).find('toptracks')
    318          return [
    319                  Track(
    320                        self._api,
    321                        subject = self,
    322                        name = t.findtext('name'),
    323                        artist = self,
    324                        mbid = t.findtext('mbid'),
    325                        stats = Stats(
    326                                      subject = t.findtext('name'),
    327                                      playcount = int(t.findtext('playcount')),
    328                                      rank = int(t.attrib['rank'])
    329                                      ),
    330                        streamable = (t.findtext('streamable') == '1'),
    331                        full_track = (t.find('streamable').attrib['fulltrack'] == '1'),
    332                        image = dict([(i.get('size'), i.text) for i in t.findall('image')]),
    333                        )
    334                  for t in data.findall('track')
    335                  ]
    336
    337      @top_property("top_tracks")
    338 -    def top_track(self):
    339          """
    340          topmost track of the artist
    341          @rtype: L{Track}
    342          """
    343          pass
    344
    345      @staticmethod
    346 -    def get_info(api, artist = None, mbid = None):
    347          """
    348          Get the data for the artist.
    349
    350          @param api:      an instance of L{Api}
    351          @type api:       L{Api}
    352          @param artist:   the name of the artist
    353          @type artist:    L{str}
    354          @param mbid:     MBID of the artist
    355          @type mbid:      L{str}
    356
    357          @return:         an Artist object corresponding the provided artist name
    358          @rtype:          L{Artist}
    359
    360          @raise lastfm.InvalidParametersError: Either artist or mbid parameter has to
    361                                                be provided. Otherwise exception is raised.
    362
    363          @note: Use the L{Api.get_artist} method instead of using this method directly.
    364          """
    365          data = Artist._fetch_data(api, artist, mbid)
    366
    367          a = Artist(api, name = data.findtext('name'))
    368          a._fill_info()
    369          return a
    370
    371 -    def _default_params(self, extra_params = {}):
    372          if not self.name:
    373              raise InvalidParametersError("artist has to be provided.")
    374          params = {'artist': self.name}
    375          params.update(extra_params)
    376          return params
    377
    378      @staticmethod
    379 -    def _fetch_data(api,
    380                  artist = None,
    381                  mbid = None):
    382          params = {'method': 'artist.getInfo'}
    383          if not (artist or mbid):
    384              raise InvalidParametersError("either artist or mbid has to be given as argument.")
    385          if artist:
    386              params.update({'artist': artist})
    387          elif mbid:
    388              params.update({'mbid': mbid})
    389          return api._fetch_data(params).find('artist')
    390
    391 -    def _fill_info(self):
    392          data = Artist._fetch_data(self._api, self.name)
    393          self._name = data.findtext('name')
    394          self._mbid = data.findtext('mbid')
    395          self._url = data.findtext('url')
    396          self._image = dict([(i.get('size'), i.text) for i in data.findall('image')])
    397          self._streamable = (data.findtext('streamable') == 1)
    398          if not self._stats:
    399              self._stats = Stats(
    400                               subject = self,
    401                               listeners = int(data.findtext('stats/listeners')),
    402                               playcount = int(data.findtext('stats/playcount'))
    403                               )
    404          self._similar = [
    405                            Artist(
    406                                   self._api,
    407                                   subject = self,
    408                                   name = a.findtext('name'),
    409                                   url = a.findtext('url'),
    410                                   image = dict([(i.get('size'), i.text) for i in a.findall('image')])
    411                                   )
    412                            for a in data.findall('similar/artist')
    413                            ]
    414          self._top_tags = [
    415                            Tag(
    416                                self._api,
    417                                subject = self,
    418                                name = t.findtext('name'),
    419                                url = t.findtext('url')
    420                                )
    421                            for t in data.findall('tags/tag')
    422                            ]
    423          self._bio = Wiki(
    424                           self,
    425                           published = data.findtext('bio/published').strip() and
    426                                          datetime(*(time.strptime(
    427                                                                data.findtext('bio/published').strip(),
    428                                                                '%a, %d %b %Y %H:%M:%S +0000'
    429                                                                )[0:6])),
    430                           summary = data.findtext('bio/summary'),
    431                           content = data.findtext('bio/content')
    432                           )
    433
    434      @staticmethod
    435 -    def _search_yield_func(api, artist):
    436          return Artist(
    437                        api,
    438                        name = artist.findtext('name'),
    439                        mbid = artist.findtext('mbid'),
    440                        url = artist.findtext('url'),
    441                        image = dict([(i.get('size'), i.text) for i in artist.findall('image')]),
    442                        streamable = (artist.findtext('streamable') == '1'),
    443                        )
    444      @staticmethod
    445 -    def _hash_func(*args, **kwds):
    446          try:
    447              return hash(kwds['name'].lower())
    448          except KeyError:
    449              try:
    450                  return hash(args[1].lower())
    451              except IndexError:
    452                  raise InvalidParametersError("name has to be provided for hashing")
    453
    454 -    def __hash__(self):
    455          return self.__class__._hash_func(name = self.name)
    456
    457 -    def __eq__(self, other):
    458          if self.mbid and other.mbid:
    459              return self.mbid == other.mbid
    460          if self.url and other.url:
    461              return self.url == other.url
    462          return self.name == other.name
    463
    464 -    def __lt__(self, other):
    465          return self.name < other.name
    466
    467 -    def __repr__(self):
    468          return "<lastfm.Artist: %s>" % self._name
    469
    470  from datetime import datetime
    471  import time
    472
    473  from lastfm.album import Album
    474  from lastfm.api import Api
    475  from lastfm.error import InvalidParametersError
    476  from lastfm.event import Event
    477  from lastfm.stats import Stats
    478  from lastfm.tag import Tag
    479  from lastfm.track import Track
    480  from lastfm.user import User
    481  from lastfm.wiki import Wiki
    482