diff --git a/pyechonest/genre.py b/pyechonest/genre.py new file mode 100644 index 0000000..b2c02dd --- /dev/null +++ b/pyechonest/genre.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import util +from proxies import GenreProxy +from proxies import ResultList + +class Genre(GenreProxy): + """ + A Genre object + + Attributes: + name (str): genre name + + """ + def __init__(self, name, buckets=None, **kwargs): + """ + Genre class + + Args: + name (str): a genre name + + Kwargs: + buckets (list): A list of strings specifying which buckets to retrieve + + Returns: + A Genre object + + Example: + + >>> g = genre.Genre('jazz', buckets=['description']) + >>> g.artists[0] + {u'id': u'ARIOZCU1187FB3A3DC', u'name': u'John Coltrane'} + >>> + """ + buckets = buckets or [] + super(Genre, self).__init__(name, buckets, **kwargs) + + def __repr__(self): + return "<{} - {}>".format(self._object_type.encode('utf-8'), self.name.encode('utf-8')) + + def __str__(self): + return self.name.encode('utf-8') + + def __cmp__(self, other): + return cmp(self.name, other.name) + + def get_artists(self, results=15, cache=True): + """Get a list of top artists for the genre + + Args: + + Kwargs: + cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True. + + results (int): An integer number of results to return. + + Returns: + A list of artist dicts + + Example: + >>> g = genre.Genre('jazz') + >>> g.artists[0] + {u'id': u'ARIOZCU1187FB3A3DC', u'name': u'John Coltrane'} + >>> + """ + + if cache and ('artists' in self.cache) and results==15: + return self.cache['artists'] + else: + response = self.get_attribute('artists', results=results) + if results==15: + self.cache['artists'] = ResultList(response['artists']) + return ResultList(response['artists']) + + artists = property(get_artists) + + def get_profile(self, cache=True, **kwargs): + """Get basic information about a genre + + Args: + name (str): The name of a genre + + Kwargs: + cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True. + + Returns: + A list of genre dicts + + Example: + >>> g = genre.Genre('jazz', buckets=['description','urls']) + >>> g.profile + {u'name': u'jazz', u'urls': {u'wikipedia_url': u'http://en.wikipedia.org/wiki/Jazz'}, u'description': u'Jazz is known for its use of blue notes, call-and-response, improvisation, polyrhythms, and syncopation. Jazz emerged in the early 20th century in the southern US, among African American musicians who layered European structures and harmony over African musical traditions. '} + >>> + """ + kwargs['name'] = self.name + + if self.buckets: + kwargs['bucket'] = self.buckets + + result = util.callm("%s/%s" % ('genre', 'profile'), kwargs) + return result['response']['genres'][0] + + profile = property(get_profile) + + def get_similar(self, results=15, start=0, cache=True, **kwargs): + """Return similar genres to this one + + Args: + + Kwargs: + cache (bool): A boolean indicating whether or not the cached value should be used (if available). Defaults to True. + + results (int): An integer number of results to return + + start (int): An integer starting value for the result set + + reverse (bool): A boolean indicating whether or not to return dissimilar artists (wrecommender). Defaults to False. + + Returns: + A list of similar Genre objects + + Example: + >>> g = genre.Genre('jazz') + >>> similar = g.similar[:5] + >>> similar + [, , , , ] + >>> + """ + if self.buckets: + kwargs['bucket'] = self.buckets + + if cache and ('similar' in self.cache) and results==15 and start==0 and (not kwargs): + return [Genre(**util.fix(g)) for g in self.cache['similar']] + else: + response = self.get_attribute('similar', results=results, start=start, **kwargs) + if results==15 and start==0 and (not kwargs): + self.cache['similar'] = response['genres'] + return [Genre(**util.fix(g)) for g in response['genres']] + + similar = property(get_similar) + +def list(results=15, buckets=None): + """Get a list of all of the available genres + + Args: + + Kwargs: + results (int): An integer number of results to return + + buckets (list): A list of strings specifying which buckets to retrieve + + Returns: + A list of Genre objects + + Example: + >>> results = genre.list(5) + >>> results + [, , , , ] + >>> + """ + kwargs = locals() + kwargs['bucket'] = buckets or [] + del kwargs['buckets'] + result = util.callm("%s/%s" % ('genre', 'list'), kwargs) + return [Genre(**util.fix(g_dict)) for g_dict in result['response']['genres']] + +def search(results=15, start=0, buckets=None, name=None): + """Search for genres by name + + Args: + + Kwargs: + name (str): the name of a genre + + start (int): An integer starting value for the result set + + results (int): An integer number of results to return + + buckets (list): A list of strings specifying which buckets to retrieve + + Returns: + A list of Genre objects + + Example: + >>> results = genre.search(results=5, name='rock') + >>> results + [, , , , ] + >>> + """ + kwargs = locals() + kwargs['bucket'] = buckets or [] + del kwargs['buckets'] + """Search for genres""" + result = util.callm("%s/%s" % ('genre', 'search'), kwargs) + return [Genre(**util.fix(g_dict)) for g_dict in result['response']['genres']] diff --git a/pyechonest/proxies.py b/pyechonest/proxies.py index 967f10e..b34cf44 100644 --- a/pyechonest/proxies.py +++ b/pyechonest/proxies.py @@ -172,4 +172,25 @@ def __init__(self, identifier, md5, properties): self.analysis_url = None self._object_type = 'track' self.__dict__.update(properties) - + + +class GenreProxy(GenericProxy): + def __init__(self, name, buckets = None, **kwargs): + super(GenreProxy, self).__init__() + self.buckets = buckets or [] + self.id = name + self._object_type = 'genre' + kwargs = dict((str(k), v) for (k,v) in kwargs.iteritems()) + core_attrs = ['name'] + if not all(ca in kwargs for ca in core_attrs): + profile = self.get_attribute('profile', **{'name':self.id, 'bucket':buckets}) + kwargs.update(profile.get('genres')[0]) + [self.__dict__.update({ca:kwargs.pop(ca)}) for ca in core_attrs+['id'] if ca in kwargs] + self.cache.update(kwargs) + + def get_attribute(self, *args, **kwargs): + if util.short_regex.match(self.id) or util.long_regex.match(self.id) or util.foreign_regex.match(self.id): + kwargs['id'] = self.id + else: + kwargs['name'] = self.id + return super(GenreProxy, self).get_attribute(*args, **kwargs) diff --git a/pyechonest/util.py b/pyechonest/util.py index 7198ae8..09353b3 100644 --- a/pyechonest/util.py +++ b/pyechonest/util.py @@ -31,6 +31,7 @@ ('SO', 'song'), ('RE', 'release'), ('TR', 'track'), + ('GE', 'genre'), ('PE', 'person'), ('DE', 'device'), ('LI', 'listener'),