diff --git a/src/album.py b/src/album.py index 4688ccd..d0b606f 100644 --- a/src/album.py +++ b/src/album.py @@ -5,8 +5,9 @@ __version__ = "0.2" __license__ = "GNU Lesser General Public License" from base import LastfmBase +from taggable import Taggable -class Album(LastfmBase): +class Album(Taggable, LastfmBase): """A class representing an album.""" def init(self, api, @@ -21,6 +22,7 @@ class Album(LastfmBase): topTags = None): if not isinstance(api, Api): raise LastfmInvalidParametersError("api reference must be supplied as an argument") + super(self.__class__, self).init(api) self.__api = api self.__name = name self.__artist = artist @@ -118,6 +120,14 @@ class Album(LastfmBase): def playlist(self): return Playlist.fetch(self.__api, "lastfm://playlist/album/%s" % self.id) + def _defaultParams(self, extraParams = None): + if not (self.artist and self.name): + raise LastfmInvalidParametersError("artist and album have to be provided.") + params = {'artist': self.artist.name, 'album': self.name} + if extraParams is not None: + params.update(extraParams) + return params + @staticmethod def _fetchData(api, artist = None, diff --git a/src/artist.py b/src/artist.py index 1199e14..5a75f15 100644 --- a/src/artist.py +++ b/src/artist.py @@ -5,9 +5,10 @@ __version__ = "0.2" __license__ = "GNU Lesser General Public License" from base import LastfmBase +from taggable import Taggable from lazylist import lazylist -class Artist(LastfmBase): +class Artist(Taggable, LastfmBase): """A class representing an artist.""" def init(self, api, @@ -22,6 +23,7 @@ class Artist(LastfmBase): bio = None): if not isinstance(api, Api): raise LastfmInvalidParametersError("api reference must be supplied as an argument") + super(self.__class__, self).init(api) self.__api = api self.__name = name self.__mbid = mbid @@ -84,8 +86,16 @@ class Artist(LastfmBase): self._fillInfo() return self.__stats + def _defaultParams(self, extraParams = None): + if not self.name: + raise LastfmInvalidParametersError("artist has to be provided.") + params = {'artist': self.name} + if extraParams is not None: + params.update(extraParams) + return params + def getSimilar(self, limit = None): - params = {'method': 'artist.getSimilar', 'artist': self.__name} + params = self._defaultParams({'method': 'artist.getSimilar'}) if limit is not None: params.update({'limit': limit}) data = self.__api._fetchData(params).find('similarartists') @@ -122,10 +132,7 @@ class Artist(LastfmBase): def topTags(self): """top tags for the artist""" if self.__topTags is None or len(self.__topTags) < 6: - params = { - 'method': 'artist.getTopTags', - 'artist': self.__name - } + params = self._defaultParams({'method': 'artist.getTopTags'}) data = self.__api._fetchData(params).find('toptags') self.__topTags = [ Tag( @@ -153,7 +160,7 @@ class Artist(LastfmBase): @LastfmBase.cachedProperty def events(self): """events for the artist""" - params = {'method': 'artist.getEvents', 'artist': self.name} + params = self._defaultParams({'method': 'artist.getEvents'}) data = self.__api._fetchData(params).find('events') return [ @@ -164,7 +171,7 @@ class Artist(LastfmBase): @LastfmBase.cachedProperty def topAlbums(self): """top albums of the artist""" - params = {'method': 'artist.getTopAlbums', 'artist': self.name} + params = self._defaultParams({'method': 'artist.getTopAlbums'}) data = self.__api._fetchData(params).find('topalbums') return [ @@ -193,7 +200,7 @@ class Artist(LastfmBase): @LastfmBase.cachedProperty def topFans(self): """top fans of the artist""" - params = {'method': 'artist.getTopFans', 'artist': self.name} + params = self._defaultParams({'method': 'artist.getTopFans'}) data = self.__api._fetchData(params).find('topfans') return [ User( @@ -218,7 +225,7 @@ class Artist(LastfmBase): @LastfmBase.cachedProperty def topTracks(self): """top tracks of the artist""" - params = {'method': 'artist.getTopTracks', 'artist': self.name} + params = self._defaultParams({'method': 'artist.getTopTracks'}) data = self.__api._fetchData(params).find('toptracks') return [ Track( diff --git a/src/taggable.py b/src/taggable.py new file mode 100644 index 0000000..65de3fa --- /dev/null +++ b/src/taggable.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +__author__ = "Abhinav Sarkar " +__version__ = "0.2" +__license__ = "GNU Lesser General Public License" + +from base import LastfmBase +from safelist import SafeList + +class Taggable(object): + def init(self, api): + self.__api = api + + @LastfmBase.cachedProperty + def tags(self): + from tag import Tag + + params = self._defaultParams({'method': '%s.getTags' % self.__class__.__name__.lower()}) + data = self.__api._fetchData(params, sign = True, session = True, no_cache = True).find('tags') + return SafeList([ + Tag( + self.__api, + name = t.findtext('name'), + url = t.findtext('url') + ) + for t in data.findall('tag') + ], + self.addTags, self.removeTag) + + def addTags(self, tags): + from tag import Tag + while(len(tags) > 10): + section = tags[0:9] + tags = tags[9:] + self.addTags(section) + + if len(tags) == 0: return + + tagnames = [] + for tag in tags: + if isinstance(tag, Tag): + tagnames.append(tag.name) + elif isinstance(tag, str): + tagnames.append(tag) + + params = self._defaultParams({ + 'method': '%s.addTags' % self.__class__.__name__.lower(), + 'tags': ",".join(tagnames) + }) + self.__api._postData(params) + self.__tags = None + + def removeTag(self, tag): + from tag import Tag + if isinstance(tag, Tag): + tag = tag.name + + params = self._defaultParams({ + 'method': '%s.removeTag' % self.__class__.__name__.lower(), + 'tag': tag + }) + self.__api._postData(params) + self.__tags = None \ No newline at end of file diff --git a/src/track.py b/src/track.py index 0f08d43..b926ea2 100644 --- a/src/track.py +++ b/src/track.py @@ -5,9 +5,10 @@ __version__ = "0.2" __license__ = "GNU Lesser General Public License" from base import LastfmBase +from taggable import Taggable from lazylist import lazylist -class Track(LastfmBase): +class Track(LastfmBase, Taggable): """A class representing a track.""" def init(self, api, @@ -27,6 +28,7 @@ class Track(LastfmBase): wiki = None): if not isinstance(api, Api): raise LastfmInvalidParametersError("api reference must be supplied as an argument") + super(self.__class__, self).init(api) self.__api = api self.__id = id self.__name = name @@ -141,25 +143,19 @@ class Track(LastfmBase): if self.__wiki is None: self._fillInfo() return self.__wiki - - def __checkParams(self, - params, - artist = None, - track = None, - mbid = None): - if not ((artist and track) or mbid): - raise LastfmInvalidParametersError("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}) + + def _defaultParams(self, extraParams = None): + if not (self.artist and self.name): + raise LastfmInvalidParametersError("artist and track have to be provided.") + params = {'artist': self.artist.name, 'track': self.name} + if extraParams is not None: + params.update(extraParams) return params @LastfmBase.cachedProperty def similar(self): """tracks similar to this track""" - params = self.__checkParams( + params = Track._checkParams( {'method': 'track.getSimilar'}, self.artist.name, self.name, @@ -198,7 +194,7 @@ class Track(LastfmBase): @LastfmBase.cachedProperty def topFans(self): """top fans of the track""" - params = self.__checkParams( + params = Track._checkParams( {'method': 'track.getTopFans'}, self.artist.name, self.name, @@ -228,7 +224,7 @@ class Track(LastfmBase): @LastfmBase.cachedProperty def topTags(self): """top tags for the track""" - params = self.__checkParams( + params = Track._checkParams( {'method': 'track.getTopTags'}, self.artist.name, self.name, @@ -254,73 +250,16 @@ class Track(LastfmBase): """topmost tag for the track""" pass - @LastfmBase.cachedProperty - def tags(self): - if not (self.artist and self.name): - raise LastfmInvalidParametersError("artist and track name have to be provided.") - params = {'method': 'track.getTags', 'artist': self.artist.name, 'track': self.name} - data = self.__api._fetchData(params, sign = True, session = True, no_cache = True).find('tags') - return SafeList([ - Tag( - self.__api, - name = t.findtext('name'), - url = t.findtext('url') - ) - for t in data.findall('tag') - ], - self.addTags, self.removeTag) - - def addTags(self, tags): - while(len(tags) > 10): - section = tags[0:9] - tags = tags[9:] - self.addTags(section) - - if len(tags) == 0: return - - tagnames = [] - for tag in tags: - if isinstance(tag, Tag): - tagnames.append(tag.name) - elif isinstance(tag, str): - tagnames.append(tag) - - params = { - 'method': 'track.addTags', - 'artist': self.artist.name, - 'track': self.name, - 'tags': ",".join(tagnames) - } - - self.__api._postData(params) - self.__tags = None - - def removeTag(self, tag): - if isinstance(tag, Tag): - tag = tag.name - params = { - 'method': 'track.removeTag', - 'artist': self.artist.name, - 'track': self.name, - 'tag': tag - } - self.__api._postData(params) - self.__tags = None - def love(self): - params = {'method': 'track.love', 'artist': self.artist.name, 'track': self.name} + params = self._defaultParams({'method': 'track.love'}) self.__api._postData(params) def ban(self): - params = {'method': 'track.ban', 'artist': self.artist.name, 'track': self.name} + params = self._defaultParams({'method': 'track.ban'}) self.__api._postData(params) def share(self, recipient, message = None): - params = { - 'method': 'track.share', - 'artist': self.artist.name, - 'track': self.name - } + params = self._defaultParams({'method': 'track.share'}) if message is not None: params['message'] = message @@ -382,13 +321,7 @@ class Track(LastfmBase): artist = None, track = None, mbid = None): - params = {'method': 'track.getInfo'} - if not ((artist and track) or mbid): - raise LastfmInvalidParametersError("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}) + params = Track._checkParams({'method': 'track.getInfo'}, artist, track, mbid) return api._fetchData(params).find('track') def _fillInfo(self): @@ -451,6 +384,20 @@ class Track(LastfmBase): t._fillInfo() return t + @staticmethod + def _checkParams(params, + artist = None, + track = None, + mbid = None): + if not ((artist and track) or mbid): + raise LastfmInvalidParametersError("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 + @staticmethod def hashFunc(*args, **kwds): try: @@ -483,7 +430,6 @@ from api import Api from artist import Artist from album import Album from error import LastfmInvalidParametersError -from safelist import SafeList from stats import Stats from tag import Tag from user import User