PageRenderTime 439ms CodeModel.GetById 81ms app.highlight 214ms RepoModel.GetById 132ms app.codeStats 1ms

/src/pyechonest/pyechonest/artist.py

http://echo-nest-remix.googlecode.com/
Python | 1015 lines | 965 code | 3 blank | 47 comment | 1 complexity | ea5d8ec2dd9a41b96341c3183b882e8f MD5 | raw file
   1#!/usr/bin/env python
   2# encoding: utf-8
   3
   4"""
   5Copyright (c) 2010 The Echo Nest. All rights reserved.
   6Created by Tyler Williams on 2010-04-25.
   7
   8The Artist module loosely covers http://developer.echonest.com/docs/v4/artist.html
   9Refer to the official api documentation if you are unsure about something.
  10"""
  11import util
  12from proxies import ArtistProxy, ResultList
  13from song import Song
  14
  15
  16class Artist(ArtistProxy):
  17    """
  18    An Artist object
  19    
  20    Attributes: 
  21        id (str): Echo Nest Artist ID
  22        
  23        name (str): Artist Name
  24        
  25        audio (list): Artist audio
  26        
  27        biographies (list): Artist biographies
  28        
  29        blogs (list): Artist blogs
  30        
  31        familiarity (float): Artist familiarity
  32        
  33        hotttnesss (float): Artist hotttnesss
  34        
  35        images (list): Artist images
  36        
  37        news (list): Artist news
  38        
  39        reviews (list): Artist reviews
  40        
  41        similar (list): Similar Artists
  42        
  43        songs (list): A list of song objects
  44        
  45        terms (list): Terms for an artist
  46        
  47        urls (list): Artist urls
  48        
  49        video (list): Artist video
  50        
  51        years_active (list): A list of dictionaries containing start and stop years
  52        
  53    You create an artist object like this:
  54    
  55    >>> a = artist.Artist('ARH6W4X1187B99274F')
  56    >>> a = artist.Artist('the national')
  57    >>> a = artist.Artist('musicbrainz:artist:a74b1b7f-71a5-4011-9441-d0b5e4122711')
  58        
  59    """
  60
  61    def __init__(self, id, **kwargs):
  62        """
  63        Artist class
  64        
  65        Args:
  66            id (str): an artistw ID 
  67            
  68        Returns:
  69            An artist object
  70            
  71        Example:
  72        
  73        >>> a = artist.Artist('ARH6W4X1187B99274F', buckets=['hotttnesss'])
  74        >>> a.hotttnesss
  75        0.80098515900997658
  76        >>>
  77        
  78        """
  79        super(Artist, self).__init__(id, **kwargs)    
  80    
  81    def __repr__(self):
  82        return "<%s - %s>" % (self._object_type.encode('utf-8'), self.name.encode('utf-8'))
  83    
  84    def __str__(self):
  85        return self.name.encode('utf-8')
  86    
  87    def __cmp__(self, other):
  88        return cmp(self.id, other.id)
  89    
  90    def get_audio(self, results=15, start=0, cache=True):
  91        """Get a list of audio documents found on the web related to an artist
  92        
  93        Args:
  94        
  95        Kwargs:
  96            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
  97            
  98            results (int): An integer number of results to return
  99            
 100            start (int): An integer starting value for the result set
 101        
 102        Returns:
 103            A list of audio document dicts; list contains additional attributes 'start' and 'total'
 104        
 105        Example:
 106
 107        >>> a = artist.Artist('alphabeat')
 108        >>> a.get_audio()[0]
 109        {u'artist': u'Alphabeat',
 110         u'date': u'2010-04-28T01:40:45',
 111         u'id': u'70be4373fa57ac2eee8c7f30b0580899',
 112         u'length': 210.0,
 113         u'link': u'http://iamthecrime.com',
 114         u'release': u'The Beat Is...',
 115         u'title': u'DJ',
 116         u'url': u'http://iamthecrime.com/wp-content/uploads/2010/04/03_DJ_iatc.mp3'}
 117        >>> 
 118        """
 119        
 120        if cache and ('audio' in self.cache) and results==15 and start==0:
 121            return self.cache['audio']
 122        else:
 123            response = self.get_attribute('audio', results=results, start=start)
 124            if results==15 and start==0:
 125                self.cache['audio'] = ResultList(response['audio'], 0, response['total'])
 126            return ResultList(response['audio'], start, response['total'])
 127    
 128    audio = property(get_audio)
 129    
 130    def get_biographies(self, results=15, start=0, license=None, cache=True):
 131        """Get a list of artist biographies
 132        
 133        Args:
 134        
 135        Kwargs:
 136            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 137            
 138            results (int): An integer number of results to return
 139            
 140            start (int): An integer starting value for the result set
 141            
 142            license (str): A string specifying the desired license type
 143        
 144        Returns:
 145            A list of biography document dicts; list contains additional attributes 'start' and 'total'
 146            
 147        Example:
 148
 149        >>> a = artist.Artist('britney spears')
 150        >>> bio = a.get_biographies(results=1)[0]
 151        >>> bio['url']
 152        u'http://www.mtvmusic.com/spears_britney'
 153        >>> 
 154        """
 155        if cache and ('biographies' in self.cache) and results==15 and start==0 and license==None:
 156            return self.cache['biographies']
 157        else:
 158            response = self.get_attribute('biographies', results=results, start=start, license=license)
 159            if results==15 and start==0 and license==None:
 160                self.cache['biographies'] = ResultList(response['biographies'], 0, response['total'])
 161            return ResultList(response['biographies'], start, response['total'])
 162    
 163    biographies = property(get_biographies)    
 164    
 165    def get_blogs(self, results=15, start=0, cache=True, high_relevance=False):
 166        """Get a list of blog articles related to an artist
 167        
 168        Args:
 169            
 170        Kwargs:
 171            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 172            
 173            results (int): An integer number of results to return
 174            
 175            start (int): An ingteger starting value for the result set
 176        
 177        Returns:
 178            A list of blog document dicts; list contains additional attributes 'start' and 'total'
 179        
 180        Example:
 181        
 182        >>> a = artist.Artist('bob marley')
 183        >>> blogs = a.get_blogs(results=1,start=4)
 184        >>> blogs.total
 185        4068
 186        >>> blogs[0]['summary']
 187        But the Kenyans I know relate to music about the same way Americans do. They like their Congolese afropop, 
 188        and I've known some to be big fans of international acts like <span>Bob</span> <span>Marley</span> and Dolly Parton. 
 189        They rarely talk about music that's indigenous in the way a South African or Malian or Zimbabwean would, and it's 
 190        even rarer to actually hear such indigenous music. I do sometimes hear ceremonial chanting from the Maasai, but only 
 191        when they're dancing for tourists. If East Africa isn't the most musical part ... "
 192        >>> 
 193        """
 194
 195        if cache and ('blogs' in self.cache) and results==15 and start==0 and not high_relevance:
 196            return self.cache['blogs']
 197        else:
 198            high_relevance = 'true' if high_relevance else 'false'
 199            response = self.get_attribute('blogs', results=results, start=start, high_relevance=high_relevance)
 200            if results==15 and start==0:
 201                self.cache['blogs'] = ResultList(response['blogs'], 0, response['total'])
 202            return ResultList(response['blogs'], start, response['total'])
 203    
 204    blogs = property(get_blogs)
 205       
 206    def get_familiarity(self, cache=True):
 207        """Get our numerical estimation of how familiar an artist currently is to the world
 208        
 209        Args:
 210        
 211        Kwargs:
 212            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 213        
 214        Returns:
 215            A float representing familiarity.
 216        
 217        Example:
 218
 219        >>> a = artist.Artist('frank sinatra')
 220        >>> a.get_familiarity()
 221        0.65142555825947457
 222        >>> a.familiarity
 223        0.65142555825947457
 224        >>>
 225        """
 226        if not (cache and ('familiarity' in self.cache)):
 227            response = self.get_attribute('familiarity')
 228            self.cache['familiarity'] = response['artist']['familiarity']
 229        return self.cache['familiarity']
 230    
 231    familiarity = property(get_familiarity)    
 232
 233    def get_foreign_id(self, idspace='musicbrainz', cache=True):
 234        """Get the foreign id for this artist for a specific id space
 235        
 236        Args:
 237        
 238        Kwargs:
 239            idspace (str): A string indicating the idspace to fetch a foreign id for.
 240        
 241        Returns:
 242            A foreign ID string
 243        
 244        Example:
 245        
 246        >>> a = artist.Artist('fabulous')
 247        >>> a.get_foreign_id('7digital')
 248        u'7digital:artist:186042'
 249        >>> 
 250        """
 251        if not (cache and ('foreign_ids' in self.cache) and filter(lambda d: d.get('catalog') == idspace, self.cache['foreign_ids'])):
 252            response = self.get_attribute('profile', bucket=['id:'+idspace])
 253            foreign_ids = response['artist'].get("foreign_ids", [])
 254            self.cache['foreign_ids'] = self.cache.get('foreign_ids', []) + foreign_ids
 255        cval = filter(lambda d: d.get('catalog') == idspace, self.cache.get('foreign_ids'))
 256        return cval[0].get('foreign_id') if cval else None
 257    
 258    def get_hotttnesss(self, cache=True):
 259        """Get our numerical description of how hottt an artist currently is
 260        
 261        Args:
 262            
 263        Kwargs:
 264            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 265        
 266        Returns:
 267            float: the hotttnesss value
 268        
 269        Example:
 270        
 271        >>> a = artist.Artist('hannah montana')
 272        >>> a.get_hotttnesss()
 273        0.59906022155998995
 274        >>> a.hotttnesss
 275        0.59906022155998995
 276        >>>
 277        """
 278        if not (cache and ('hotttnesss' in self.cache)):
 279            response = self.get_attribute('hotttnesss')
 280            self.cache['hotttnesss'] = response['artist']['hotttnesss']
 281        return self.cache['hotttnesss']
 282    
 283    hotttnesss = property(get_hotttnesss)
 284    
 285    def get_images(self, results=15, start=0, license=None, cache=True):
 286        """Get a list of artist images
 287        
 288        Args:
 289            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 290            
 291            results (int): An integer number of results to return
 292            
 293            start (int): An integer starting value for the result set
 294            
 295            license (str): A string specifying the desired license type
 296        
 297        Returns:
 298            A list of image document dicts; list contains additional attributes 'start' and 'total'
 299        
 300        Example:
 301        
 302        >>> a = artist.Artist('Captain Beefheart')
 303        >>> images = a.get_images(results=1)
 304        >>> images.total
 305        49
 306        >>> images[0]['url']
 307        u'http://c4.ac-images.myspacecdn.com/images01/5/l_e1a329cdfdb16a848288edc6d578730f.jpg'
 308        >>> 
 309        """
 310        
 311        if cache and ('images' in self.cache) and results==15 and start==0 and license==None:
 312            return self.cache['images']
 313        else:
 314            response = self.get_attribute('images', results=results, start=start, license=license)
 315            if results==15 and start==0 and license==None:
 316                self.cache['images'] = ResultList(response['images'], 0, response['total'])
 317            return ResultList(response['images'], start, response['total'])
 318    
 319    images = property(get_images)    
 320    
 321    def get_news(self, results=15, start=0, cache=True, high_relevance=False):
 322        """Get a list of news articles found on the web related to an artist
 323        
 324        Args:
 325            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 326            
 327            results (int): An integer number of results to return
 328            
 329            start (int): An integer starting value for the result set
 330        
 331        Returns:
 332            A list of news document dicts; list contains additional attributes 'start' and 'total'
 333        
 334        Example:
 335        
 336        >>> a = artist.Artist('Henry Threadgill')
 337        >>> news = a.news
 338        >>> news.total
 339        41
 340        >>> news[0]['name']
 341        u'Jazz Journalists Association Announces 2010 Jazz Award Winners'
 342        >>> 
 343        """
 344        if cache and ('news' in self.cache) and results==15 and start==0 and not high_relevance:
 345            return self.cache['news']
 346        else:
 347            high_relevance = 'true' if high_relevance else 'false'
 348            response = self.get_attribute('news', results=results, start=start, high_relevance=high_relevance)
 349            if results==15 and start==0:
 350                self.cache['news'] = ResultList(response['news'], 0, response['total'])
 351            return ResultList(response['news'], start, response['total'])
 352    
 353    news = property(get_news)
 354    
 355    def get_reviews(self, results=15, start=0, cache=True):
 356        """Get reviews related to an artist's work
 357        
 358        Args:
 359            
 360        Kwargs:
 361            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 362            
 363            results (int): An integer number of results to return
 364            
 365            start (int): An integer starting value for the result set
 366        
 367        Returns:
 368            A list of review document dicts; list contains additional attributes 'start' and 'total'
 369        
 370        Example:
 371        
 372        >>> a = artist.Artist('Ennio Morricone')
 373        >>> reviews = a.reviews
 374        >>> reviews.total
 375        17
 376        >>> reviews[0]['release']
 377        u'For A Few Dollars More'
 378        >>> 
 379        """
 380        if cache and ('reviews' in self.cache) and results==15 and start==0:
 381            return self.cache['reviews']
 382        else:
 383            response = self.get_attribute('reviews', results=results, start=start)
 384            if results==15 and start==0:
 385                self.cache['reviews'] = ResultList(response['reviews'], 0, response['total'])
 386            return ResultList(response['reviews'], start, response['total'])
 387    
 388    reviews = property(get_reviews)
 389    
 390    def get_similar(self, results=15, start=0, buckets=None, limit=False, cache=True, max_familiarity=None, min_familiarity=None, \
 391                    max_hotttnesss=None, min_hotttnesss=None, min_results=None, reverse=False, artist_start_year_before=None, \
 392                    artist_start_year_after=None,artist_end_year_before=None,artist_end_year_after=None):
 393        """Return similar artists to this one
 394        
 395        Args:
 396        
 397        Kwargs:
 398            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 399            
 400            results (int): An integer number of results to return
 401            
 402            start (int): An integer starting value for the result set
 403            
 404            max_familiarity (float): A float specifying the max familiarity of artists to search for
 405            
 406            min_familiarity (float): A float specifying the min familiarity of artists to search for
 407            
 408            max_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 409            
 410            min_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 411            
 412            reverse (bool): A boolean indicating whether or not to return dissimilar artists (wrecommender). Defaults to False.
 413        
 414        Returns:
 415            A list of similar Artist objects
 416        
 417        Example:
 418        
 419        >>> a = artist.Artist('Sleater Kinney')
 420        >>> similars = a.similar[:5]
 421        >>> similars
 422        [<artist - Bikini Kill>, <artist - Pretty Girls Make Graves>, <artist - Huggy Bear>, <artist - Bratmobile>, <artist - Team Dresch>]
 423        >>> 
 424        """
 425        buckets = buckets or []
 426        kwargs = {}
 427        if max_familiarity:
 428            kwargs['max_familiarity'] = max_familiarity
 429        if min_familiarity:
 430            kwargs['min_familiarity'] = min_familiarity
 431        if max_hotttnesss:
 432            kwargs['max_hotttnesss'] = max_hotttnesss
 433        if min_hotttnesss:
 434            kwargs['min_hotttnesss'] = min_hotttnesss
 435        if min_results:
 436            kwargs['min_results'] = min_results
 437        if buckets:
 438            kwargs['bucket'] = buckets
 439        if limit:
 440            kwargs['limit'] = 'true'
 441        if reverse:
 442            kwargs['reverse'] = 'true'
 443        if artist_start_year_before:
 444            kwargs['artist_start_year_before'] = artist_start_year_before
 445        if artist_start_year_after:
 446            kwargs['artist_start_year_after'] = artist_start_year_after
 447        if artist_end_year_before:
 448            kwargs['artist_end_year_before'] = artist_end_year_before
 449        if artist_end_year_after:
 450            kwargs['artist_end_year_after'] = artist_end_year_after
 451        
 452        
 453        if cache and ('similar' in self.cache) and results==15 and start==0 and (not kwargs):
 454            return [Artist(**util.fix(a)) for a in self.cache['similar']]
 455        else:
 456            response = self.get_attribute('similar', results=results, start=start, **kwargs)
 457            if results==15 and start==0 and (not kwargs):
 458                self.cache['similar'] = response['artists']
 459            return [Artist(**util.fix(a)) for a in response['artists']]
 460    
 461    similar = property(get_similar)    
 462    
 463    def get_songs(self, cache=True, results=15, start=0):
 464        """Get the songs associated with an artist
 465        
 466        Args:
 467        
 468        Kwargs:
 469            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 470            
 471            results (int): An integer number of results to return
 472            
 473            start (int): An integer starting value for the result set
 474            
 475        Results:
 476            A list of Song objects; list contains additional attributes 'start' and 'total'
 477        
 478        Example:
 479
 480        >>> a = artist.Artist('Strokes')
 481        >>> a.get_songs(results=5)
 482        [<song - Fear Of Sleep>, <song - Red Light>, <song - Ize Of The World>, <song - Evening Sun>, <song - Juicebox>]
 483        >>> 
 484        """
 485        
 486        if cache and ('songs' in self.cache) and results==15 and start==0:
 487            if not isinstance(self.cache['songs'][0], Song):
 488                song_objects = []
 489                for s in self.cache["songs"]:
 490                    song_objects.append(Song(id=s['id'], 
 491                                             title=s['title'],
 492                                             artist_name=self.name,
 493                                             artist_id=self.id))
 494                self.cache['songs'] = song_objects
 495            return self.cache['songs']
 496        else:
 497            response = self.get_attribute('songs', results=results, start=start)
 498            for s in response['songs']:
 499                s.update({'artist_id':self.id, 'artist_name':self.name})
 500            songs = [Song(**util.fix(s)) for s in response['songs']]
 501            if results==15 and start==0:
 502                self.cache['songs'] = ResultList(songs, 0, response['total'])
 503            return ResultList(songs, start, response['total'])
 504    
 505    songs = property(get_songs)
 506
 507    def get_terms(self, sort='weight', cache=True):
 508        """Get the terms associated with an artist
 509        
 510        Args:
 511        
 512        Kwargs:
 513            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 514            
 515            sort (str): A string specifying the desired sorting type (weight or frequency)
 516            
 517        Results:
 518            A list of term document dicts
 519            
 520        Example:
 521
 522        >>> a = artist.Artist('tom petty')
 523        >>> a.terms
 524        [{u'frequency': 1.0, u'name': u'heartland rock', u'weight': 1.0},
 525         {u'frequency': 0.88569401860168606,
 526          u'name': u'jam band',
 527          u'weight': 0.9116501862732439},
 528         {u'frequency': 0.9656145118557401,
 529          u'name': u'pop rock',
 530          u'weight': 0.89777934440040685},
 531         {u'frequency': 0.8414744288140491,
 532          u'name': u'southern rock',
 533          u'weight': 0.8698567153186606},
 534         {u'frequency': 0.9656145118557401,
 535          u'name': u'hard rock',
 536          u'weight': 0.85738022655218893},
 537         {u'frequency': 0.88569401860168606,
 538          u'name': u'singer-songwriter',
 539          u'weight': 0.77427243392312772},
 540         {u'frequency': 0.88569401860168606,
 541          u'name': u'rock',
 542          u'weight': 0.71158718989399083},
 543         {u'frequency': 0.60874110500110956,
 544          u'name': u'album rock',
 545          u'weight': 0.69758668733499629},
 546         {u'frequency': 0.74350792060935744,
 547          u'name': u'psychedelic',
 548          u'weight': 0.68457367494207944},
 549         {u'frequency': 0.77213698386292873,
 550          u'name': u'pop',
 551          u'weight': 0.65039556639337293},
 552         {u'frequency': 0.41747136183050298,
 553          u'name': u'bar band',
 554          u'weight': 0.54974975024767025}]
 555        >>> 
 556
 557        """
 558        if cache and ('terms' in self.cache) and sort=='weight':
 559            return self.cache['terms']
 560        else:
 561            response = self.get_attribute('terms', sort=sort)
 562            if sort=='weight':
 563                self.cache['terms'] = response['terms']
 564            return response['terms']
 565    
 566    terms = property(get_terms)
 567    
 568    def get_urls(self, cache=True):
 569        """Get the urls for an artist
 570        
 571        Args:
 572        
 573        Kwargs:
 574            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 575            
 576        Results:
 577            A url document dict
 578            
 579        Example:
 580
 581        >>> a = artist.Artist('the unicorns')
 582        >>> a.get_urls()
 583        {u'amazon_url': u'http://www.amazon.com/gp/search?ie=UTF8&keywords=The Unicorns&tag=httpechonecom-20&index=music',
 584         u'aolmusic_url': u'http://music.aol.com/artist/the-unicorns',
 585         u'itunes_url': u'http://itunes.com/TheUnicorns',
 586         u'lastfm_url': u'http://www.last.fm/music/The+Unicorns',
 587         u'mb_url': u'http://musicbrainz.org/artist/603c5f9f-492a-4f21-9d6f-1642a5dbea2d.html',
 588         u'myspace_url': u'http://www.myspace.com/iwasbornunicorn'}
 589        >>> 
 590
 591        """
 592        if not (cache and ('urls' in self.cache)):
 593            response = self.get_attribute('urls')
 594            self.cache['urls'] = response['urls']
 595        return self.cache['urls']
 596    
 597    urls = property(get_urls)    
 598    
 599    def get_video(self, results=15, start=0, cache=True):
 600        """Get a list of video documents found on the web related to an artist
 601        
 602        Args:
 603        
 604        Kwargs:
 605            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 606            
 607            results (int): An integer number of results to return
 608            
 609            start (int): An integer starting value for the result set
 610        
 611        Returns:
 612            A list of video document dicts; list contains additional attributes 'start' and 'total'
 613            
 614        Example:
 615
 616        >>> a = artist.Artist('the vapors')
 617        >>> a.get_video(results=1, start=2)
 618        [{u'date_found': u'2009-12-28T08:27:48',
 619          u'id': u'd02f9e6dc7904f70402d4676516286b9',
 620          u'image_url': u'http://i1.ytimg.com/vi/p6c0wOFL3Us/default.jpg',
 621          u'site': u'youtube',
 622          u'title': u'The Vapors-Turning Japanese (rectangular white vinyl promo)',
 623          u'url': u'http://youtube.com/watch?v=p6c0wOFL3Us'}]
 624        >>> 
 625
 626        """
 627        if cache and ('video' in self.cache) and results==15 and start==0:
 628            return self.cache['video']
 629        else:
 630            response = self.get_attribute('video', results=results, start=start)
 631            if results==15 and start==0:
 632                self.cache['video'] = ResultList(response['video'], 0, response['total'])
 633            return ResultList(response['video'], start, response['total'])
 634    
 635    video = property(get_video)
 636
 637    def get_years_active(self, cache=True):
 638        """Get a list of years active dictionaries for an artist
 639        
 640        Args:
 641        
 642        Kwargs:
 643            cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True.
 644        
 645        Returns:
 646            A list of years active dictionaries; list contains additional attributes 'start' and 'total'
 647            
 648        Example:
 649
 650        >>> a = artist.Artist('yelle')
 651        >>> a.get_years_active()
 652        [{ start: 2005 }]
 653        >>> 
 654
 655        """
 656        if cache and ('years_active' in self.cache):
 657            return self.cache['years_active']
 658        else:
 659            response = self.get_attribute('profile', bucket=['years_active'])
 660            self.cache['years_active'] = response['artist']['years_active']
 661            return response['artist']['years_active']
 662    
 663    years_active = property(get_years_active)
 664    
 665    def get_doc_counts(self, cache=True):
 666        """
 667        Get the number of related documents of various types for the artist.
 668        The types include audio, biographies, blogs, images, news, reviews, songs, videos.
 669        
 670        Note that these documents can be retrieved by calling artist.<document type>, for example,
 671        artist.biographies.
 672        
 673        Args:
 674        
 675        Kwargs:
 676            cache (bool): A boolean indicating whether or not the cached value should be used (if available).
 677            Defaults to True.
 678        
 679        Returns:
 680            A dictionary with one key for each document type, mapped to an integer count of documents.
 681        
 682        Example:
 683        
 684        >>> a = artist.Artist("The Kinks")
 685
 686        >>> a.get_doc_counts()
 687        {u'audio': 194,
 688         u'biographies': 9,
 689         u'blogs': 379,
 690         u'images': 177,
 691         u'news': 84,
 692         u'reviews': 110,
 693         u'songs': 499,
 694         u'videos': 340}
 695         >>>
 696        """
 697        if not cache or not ('doc_counts' in self.cache):
 698            response = self.get_attribute("profile", bucket='doc_counts')
 699            self.cache['doc_counts'] = response['artist']['doc_counts']
 700        return self.cache['doc_counts']
 701    
 702    doc_counts = property(get_doc_counts)
 703
 704def search(name=None, description=None, style=None, mood=None, start=0, \
 705            results=15, buckets=None, limit=False, \
 706            fuzzy_match=False, sort=None, max_familiarity=None, min_familiarity=None, \
 707            max_hotttnesss=None, min_hotttnesss=None, test_new_things=None, rank_type=None, \
 708            artist_start_year_after=None, artist_start_year_before=None,artist_end_year_after=None,artist_end_year_before=None):
 709    """Search for artists by name, description, or constraint.
 710    
 711    Args:
 712    
 713    Kwargs:
 714        name (str): the name of an artist
 715        
 716        description (str): A string describing the artist
 717        
 718        style (str): A string describing the style/genre of the artist
 719        
 720        mood (str): A string describing the mood of the artist
 721        
 722        start (int): An integer starting value for the result set
 723
 724        results (int): An integer number of results to return
 725        
 726        buckets (list): A list of strings specifying which buckets to retrieve
 727        
 728        limit (bool): A boolean indicating whether or not to limit the results to one of the id spaces specified in buckets
 729        
 730        fuzzy_match (bool): A boolean indicating whether or not to search for similar sounding matches (only works with name)
 731        
 732        max_familiarity (float): A float specifying the max familiarity of artists to search for
 733        
 734        min_familiarity (float): A float specifying the min familiarity of artists to search for
 735        
 736        max_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 737        
 738        min_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 739        
 740        artist_start_year_before (int): Returned artists will have started recording music before this year.
 741        
 742        artist_start_year_after (int): Returned artists will have started recording music after this year.
 743        
 744        artist_end_year_before (int): Returned artists will have stopped recording music before this year.
 745        
 746        artist_end_year_after (int): Returned artists will have stopped recording music after this year.
 747        
 748        rank_type (str): A string denoting the desired ranking for description searches, either 'relevance' or 'familiarity'
 749
 750    Returns:
 751        A list of Artist objects
 752    
 753    Example:
 754    
 755    >>> results = artist.search(name='t-pain')
 756    >>> results
 757    [<artist - T-Pain>, <artist - T-Pain & Lil Wayne>, <artist - T Pain & 2 Pistols>, <artist - Roscoe Dash & T-Pain>, <artist - Tony Moxberg & T-Pain>, <artist - Flo-Rida (feat. T-Pain)>, <artist - Shortyo/Too Short/T-Pain>]
 758    >>> 
 759
 760    """
 761    limit = str(limit).lower()
 762    fuzzy_match = str(fuzzy_match).lower()
 763    kwargs = locals()
 764    kwargs['bucket'] = buckets or []
 765    del kwargs['buckets']
 766    """Search for artists"""
 767    result = util.callm("%s/%s" % ('artist', 'search'), kwargs)
 768    return [Artist(**util.fix(a_dict)) for a_dict in result['response']['artists']]
 769
 770def top_hottt(start=0, results=15, buckets = None, limit=False):
 771    """Get the top hotttest artists, according to The Echo Nest
 772    
 773    Args:
 774    
 775    Kwargs:
 776        results (int): An integer number of results to return
 777        
 778        start (int): An integer starting value for the result set
 779        
 780        buckets (list): A list of strings specifying which buckets to retrieve
 781        
 782        limit (bool): A boolean indicating whether or not to limit the results to one of the id spaces specified in buckets
 783        
 784    Returns:
 785        A list of hottt Artist objects
 786
 787    Example:
 788
 789    >>> hot_stuff = artist.top_hottt()
 790    >>> hot_stuff
 791    [<artist - Deerhunter>, <artist - Sufjan Stevens>, <artist - Belle and Sebastian>, <artist - Glee Cast>, <artist - Linkin Park>, <artist - Neil Young>, <artist - Jimmy Eat World>, <artist - Kanye West>, <artist - Katy Perry>, <artist - Bruno Mars>, <artist - Lady Gaga>, <artist - Rihanna>, <artist - Lil Wayne>, <artist - Jason Mraz>, <artist - Green Day>]
 792    >>> 
 793
 794    """
 795    buckets = buckets or []
 796    kwargs = {}
 797    if start:
 798        kwargs['start'] = start
 799    if results:
 800        kwargs['results'] = results
 801    if buckets:
 802        kwargs['bucket'] = buckets
 803    if limit:
 804        kwargs['limit'] = 'true'
 805    
 806    """Get top hottt artists"""
 807    result = util.callm("%s/%s" % ('artist', 'top_hottt'), kwargs)
 808    return [Artist(**util.fix(a_dict)) for a_dict in result['response']['artists']]    
 809
 810
 811def top_terms(results=15):
 812    """Get a list of the top overall terms
 813        
 814    Args:
 815    
 816    Kwargs:
 817        results (int): An integer number of results to return
 818        
 819    Returns:
 820        A list of term document dicts
 821    
 822    Example:
 823    
 824    >>> terms = artist.top_terms(results=5)
 825    >>> terms
 826    [{u'frequency': 1.0, u'name': u'rock'},
 827     {u'frequency': 0.99054710039307992, u'name': u'electronic'},
 828     {u'frequency': 0.96131624654034398, u'name': u'hip hop'},
 829     {u'frequency': 0.94358477322411127, u'name': u'jazz'},
 830     {u'frequency': 0.94023302416455468, u'name': u'pop rock'}]
 831    >>> 
 832    """
 833    
 834    kwargs = {}
 835    if results:
 836        kwargs['results'] = results
 837    
 838    """Get top terms"""
 839    result = util.callm("%s/%s" % ('artist', 'top_terms'), kwargs)
 840    return result['response']['terms']
 841
 842def list_terms(type):
 843    """Get a list of best terms to use with search
 844    
 845    Args:
 846    
 847    Kwargs:
 848        type (str): the type of term to return, either 'mood' or 'style'
 849    
 850    Example:
 851    
 852    >>> best_terms = artist.list_terms('mood')
 853    >>> best_terms
 854    [{u'name': u'aggressive'},
 855     {u'name': u'ambient'},
 856     {u'name': u'angry'},
 857     {u'name': u'angst-ridden'},
 858     {u'name': u'bouncy'},
 859     {u'name': u'calming'},
 860     {u'name': u'carefree'}, etc.]
 861    """
 862    
 863    kwargs = {'type': type}
 864    result = util.callm("%s/%s" % ('artist', 'list_terms'), kwargs)
 865    return result['response']['terms']
 866
 867def similar(names=None, ids=None, start=0, results=15, buckets=None, limit=False, max_familiarity=None, min_familiarity=None,
 868            max_hotttnesss=None, min_hotttnesss=None, seed_catalog=None,artist_start_year_before=None, \
 869            artist_start_year_after=None,artist_end_year_before=None,artist_end_year_after=None):
 870    """Return similar artists to this one
 871    
 872    Args:
 873    
 874    Kwargs:
 875        ids (str/list): An artist id or list of ids
 876        
 877        names (str/list): An artist name or list of names
 878        
 879        results (int): An integer number of results to return
 880        
 881        buckets (list): A list of strings specifying which buckets to retrieve
 882        
 883        limit (bool): A boolean indicating whether or not to limit the results to one of the id spaces specified in buckets
 884        
 885        start (int): An integer starting value for the result set
 886        
 887        max_familiarity (float): A float specifying the max familiarity of artists to search for
 888        
 889        min_familiarity (float): A float specifying the min familiarity of artists to search for
 890        
 891        max_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 892        
 893        min_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 894        
 895        seed_catalog (str): A string specifying the catalog similar artists are restricted to
 896    
 897    Returns:
 898        A list of similar Artist objects
 899    
 900    Example:
 901
 902    >>> some_dudes = [artist.Artist('weezer'), artist.Artist('radiohead')]
 903    >>> some_dudes
 904    [<artist - Weezer>, <artist - Radiohead>]
 905    >>> sims = artist.similar(ids=[art.id for art in some_dudes], results=5)
 906    >>> sims
 907    [<artist - The Smashing Pumpkins>, <artist - Biffy Clyro>, <artist - Death Cab for Cutie>, <artist - Jimmy Eat World>, <artist - Nerf Herder>]
 908    >>> 
 909
 910    """
 911    
 912    buckets = buckets or []
 913    kwargs = {}
 914
 915    if ids:
 916        if not isinstance(ids, list):
 917            ids = [ids]
 918        kwargs['id'] = ids
 919    if names:
 920        if not isinstance(names, list):
 921            names = [names]
 922        kwargs['name'] = names
 923    if max_familiarity is not None:
 924        kwargs['max_familiarity'] = max_familiarity
 925    if min_familiarity is not None:
 926        kwargs['min_familiarity'] = min_familiarity
 927    if max_hotttnesss is not None:
 928        kwargs['max_hotttnesss'] = max_hotttnesss
 929    if min_hotttnesss is not None:
 930        kwargs['min_hotttnesss'] = min_hotttnesss
 931    if seed_catalog is not None:
 932        kwargs['seed_catalog'] = seed_catalog
 933    if start:
 934        kwargs['start'] = start
 935    if results:
 936        kwargs['results'] = results
 937    if buckets:
 938        kwargs['bucket'] = buckets
 939    if limit:
 940        kwargs['limit'] = 'true'
 941    if artist_start_year_before:
 942        kwargs['artist_start_year_before'] = artist_start_year_before
 943    if artist_start_year_after:
 944        kwargs['artist_start_year_after'] = artist_start_year_after
 945    if artist_end_year_before:
 946        kwargs['artist_end_year_before'] = artist_end_year_before
 947    if artist_end_year_after:
 948        kwargs['artist_end_year_after'] = artist_end_year_after
 949
 950
 951    result = util.callm("%s/%s" % ('artist', 'similar'), kwargs)
 952    return [Artist(**util.fix(a_dict)) for a_dict in result['response']['artists']]
 953
 954def extract(text='', start=0, results=15, buckets=None, limit=False, max_familiarity=None, min_familiarity=None,
 955                max_hotttnesss=None, min_hotttnesss=None):
 956    """Extract artist names from a block of text.
 957    
 958    Args:
 959    
 960    Kwargs:
 961        text (str): The text to extract artists from
 962    
 963        start (int): An integer starting value for the result set
 964    
 965        results (int): An integer number of results to return
 966    
 967        buckets (list): A list of strings specifying which buckets to retrieve
 968    
 969        limit (bool): A boolean indicating whether or not to limit the results to one of the id spaces specified in buckets
 970    
 971        max_familiarity (float): A float specifying the max familiarity of artists to search for
 972    
 973        min_familiarity (float): A float specifying the min familiarity of artists to search for
 974    
 975        max_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 976    
 977        min_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 978    
 979    Returns:
 980        A list of Artist objects
 981    
 982    Example:
 983    
 984    >>> results = artist.extract(text='i saw beyonce at burger king, she was eatin, she was eatin')
 985    >>> results
 986
 987    >>> 
 988    
 989    """
 990
 991    buckets = buckets or []
 992    kwargs = {}
 993    
 994    kwargs['text'] = text
 995    
 996    if max_familiarity is not None:
 997        kwargs['max_familiarity'] = max_familiarity
 998    if min_familiarity is not None:
 999        kwargs['min_familiarity'] = min_familiarity
1000    if max_hotttnesss is not None:
1001        kwargs['max_hotttnesss'] = max_hotttnesss
1002    if min_hotttnesss is not None:
1003        kwargs['min_hotttnesss'] = min_hotttnesss
1004    if start:
1005        kwargs['start'] = start
1006    if results:
1007        kwargs['results'] = results
1008    if buckets:
1009        kwargs['bucket'] = buckets
1010    if limit:
1011        kwargs['limit'] = 'true'
1012    
1013    result = util.callm("%s/%s" % ('artist', 'extract'), kwargs)
1014    
1015    return [Artist(**util.fix(a_dict)) for a_dict in result['response']['artists']]