From 291ec6846a7d360b5d136d7822832950172afbe4 Mon Sep 17 00:00:00 2001 From: Abhinav Sarkar Date: Mon, 18 Aug 2008 13:19:41 +0000 Subject: [PATCH] arranged imports, refactored events methods (moved the code to Events.fromData method), made the call to register method in base.py threadsafe. --- src/__init__.py | 11 ++-- src/album.py | 6 +- src/api.py | 31 +++++++---- src/artist.py | 92 ++++++++++-------------------- src/base.py | 38 ++++++++----- src/event.py | 74 +++++++++++++++--------- src/filecache.py | 4 +- src/geo.py | 136 +++++++++++++++++---------------------------- src/registry.py | 8 +-- src/search.py | 35 +----------- src/tag.py | 8 +-- src/tasteometer.py | 6 +- src/track.py | 10 ++-- src/user.py | 80 +++++++++++++++----------- 14 files changed, 245 insertions(+), 294 deletions(-) diff --git a/src/__init__.py b/src/__init__.py index 62018db..9be1698 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -4,22 +4,21 @@ __author__ = "Abhinav Sarkar" __version__ = "0.1" __license__ = "GNU Lesser General Public License" +from album import Album +from api import Api +from artist import Artist from base import LastfmBase from error import LastfmError -from api import Api -from registry import Registry - -from album import Album -from artist import Artist from event import Event from geo import Location, Country from group import Group from playlist import Playlist +from registry import Registry +from search import SearchResult from tag import Tag from tasteometer import Tasteometer from track import Track from user import User -from search import SearchResult __all__ = ['LastfmError', 'Api', 'Album', 'Artist', 'Event', 'Location', 'Country', 'Group', 'Playlist', 'Tag', diff --git a/src/album.py b/src/album.py index 379137c..683740b 100644 --- a/src/album.py +++ b/src/album.py @@ -201,7 +201,7 @@ from datetime import datetime import time from api import Api -from error import LastfmError -from tag import Tag from artist import Artist -from stats import Stats \ No newline at end of file +from error import LastfmError +from stats import Stats +from tag import Tag \ No newline at end of file diff --git a/src/api.py b/src/api.py index 9c4d156..833db8c 100644 --- a/src/api.py +++ b/src/api.py @@ -177,10 +177,13 @@ class Api(object): limit = None): return Tasteometer.compare(self, type1, type2, value1, value2, limit) - def getTrack(self, name, artist = None): + def getTrack(self, track, artist): if isinstance(artist, Artist): artist = artist.name - return Track(self, name = name, artist = artist) + result = Track.search(self, track, artist) + if len(result.matches) == 0: + raise LastfmError("'%s' by %s: no such track found" % (track, artist)) + return result.matches[0] def searchTrack(self, track, @@ -260,22 +263,17 @@ class Api(object): def __repr__(self): return "" % self.__apiKey +import sys +import time import urllib import urllib2 import urlparse -import time -import sys -if sys.version.startswith('2.5'): - import xml.etree.cElementTree as ElementTree -else: - import cElementTree as ElementTree - -from error import LastfmError -from filecache import FileCache from album import Album from artist import Artist +from error import LastfmError from event import Event +from filecache import FileCache from geo import Location, Country from group import Group from playlist import Playlist @@ -283,3 +281,14 @@ from tag import Tag from tasteometer import Tasteometer from track import Track from user import User + +if sys.version.startswith('2.5'): + import xml.etree.cElementTree as ElementTree +else: + try: + import cElementTree as ElementTree + except ImportError: + try: + import ElementTree + except ImportError: + raise LastfmError("Install ElementTree package for using python-lastfm") \ No newline at end of file diff --git a/src/artist.py b/src/artist.py index a316512..61469ce 100644 --- a/src/artist.py +++ b/src/artist.py @@ -117,12 +117,12 @@ class Artist(LastfmBase): if self.__similar is None or len(self.__similar) < 6: return self.getSimilar() return self.__similar - + @property def mostSimilar(self): """artist most similar to this artist""" return (len(self.similar) and self.similar[0] or None) - + @property def topTags(self): """top tags for the artist""" @@ -141,7 +141,7 @@ class Artist(LastfmBase): for t in data.findall('tag') ] return self.__topTags - + @property def topTag(self): """top tag for the artist""" @@ -153,63 +153,27 @@ class Artist(LastfmBase): if self.__bio is None: self._fillInfo() return self.__bio - + @property def events(self): """events for the artist""" if self.__events is None: params = {'method': 'artist.getevents', 'artist': self.name} data = self.__api._fetchData(params).find('events') - + self.__events = [ - Event( - self.__api, - id = int(e.findtext('id')), - title = e.findtext('title'), - artists = [Artist(self.__api, name = a.text) for a in e.findall('artists/artist')], - headliner = Artist(self.__api, name = e.findtext('artists/headliner')), - venue = Venue( - name = e.findtext('venue/name'), - location = Location( - self.__api, - city = e.findtext('venue/location/city'), - country = Country( - self.__api, - name = e.findtext('venue/location/country') - ), - street = e.findtext('venue/location/street'), - postalCode = e.findtext('venue/location/postalcode'), - latitude = float(e.findtext( - 'venue/location/{%s}point/{%s}lat' % ((Location.xmlns,)*2) - )), - longitude = float(e.findtext( - 'venue/location/{%s}point/{%s}long' % ((Location.xmlns,)*2) - )), - timezone = e.findtext('venue/location/timezone') - ), - url = e.findtext('venue/url') - ), - startDate = e.findtext('startDate') and - datetime(*(time.strptime(e.findtext('startDate').strip(), '%a, %d %b %Y')[0:6])) or - None, - startTime = e.findtext('startTime') and - datetime(*(time.strptime(e.findtext('startTime').strip(), '%H:%M')[0:6])) or - None, - description = e.findtext('description'), - image = dict([(i.get('size'), i.text) for i in e.findall('image')]), - url = e.findtext('url') - ) - for e in data.findall('event') - ] + Event.createFromData(self.__api, e) + for e in data.findall('event') + ] return self.__events - + @property def topAlbums(self): """top albums of the artist""" if self.__topAlbums is None: params = {'method': 'artist.gettopalbums', 'artist': self.name} data = self.__api._fetchData(params).find('topalbums') - + self.__topAlbums = [ Album( self.__api, @@ -227,12 +191,12 @@ class Artist(LastfmBase): for a in data.findall('album') ] return self.__topAlbums - + @property def topAlbum(self): """top album of the artist""" return (len(self.topAlbums) and self.topAlbums[0] or None) - + @property def topFans(self): """top fans of the artist""" @@ -253,12 +217,12 @@ class Artist(LastfmBase): for u in data.findall('user') ] return self.__topFans - + @property def topFan(self): """top fan of the artist""" return (len(self.topFans) and self.topFans[0] or None) - + @property def topTracks(self): """top tracks of the artist""" @@ -283,11 +247,11 @@ class Artist(LastfmBase): for t in data.findall('track') ] return self.__topTracks - + @property def topTrack(self): return (len(self.topTracks) and self.topTracks[0] or None) - + @staticmethod def search(api, artist, @@ -318,7 +282,7 @@ class Artist(LastfmBase): for a in data.findall('artistmatches/artist') ] ) - + @staticmethod def _fetchData(api, artist = None, @@ -358,7 +322,7 @@ class Artist(LastfmBase): self.__api, name = t.findtext('name'), url = t.findtext('url') - ) + ) for t in data.findall('tags/tag') ] self.__bio = Bio( @@ -370,18 +334,18 @@ class Artist(LastfmBase): summary = data.findtext('bio/summary'), content = data.findtext('bio/content') ) - + @staticmethod def getInfo(api, artist = None, mbid = None): data = Artist._fetchData(api, artist, mbid) - + a = Artist(api, name = data.findtext('name')) if a.bio is None: a._fillInfo() return a - + @staticmethod def hashFunc(*args, **kwds): try: @@ -392,20 +356,20 @@ class Artist(LastfmBase): return hash(args[1].lower()) except IndexError: raise LastfmError("name has to be provided for hashing") - + def __hash__(self): return self.__class__.hashFunc(name = self.name) - + def __eq__(self, other): if self.mbid and other.mbid: return self.mbid == other.mbid if self.url and other.url: return self.url == other.url return self.name == other.name - + def __lt__(self, other): return self.name < other.name - + def __repr__(self): return "" % self.__name @@ -447,13 +411,13 @@ class Bio(object): from datetime import datetime import time -from api import Api from album import Album +from api import Api from error import LastfmError from event import Event from geo import Country, Location, Venue +from search import SearchResult +from stats import Stats from tag import Tag from track import Track from user import User -from search import SearchResult -from stats import Stats \ No newline at end of file diff --git a/src/base.py b/src/base.py index 5675e39..70cbe1c 100644 --- a/src/base.py +++ b/src/base.py @@ -4,24 +4,34 @@ __author__ = "Abhinav Sarkar" __version__ = "0.1" __license__ = "GNU Lesser General Public License" +try: + from threading import Lock +except ImportError: + from dummy_threading import Lock + class LastfmBase(object): """Base class for all the classes in this package""" - + registry = {} - + _lock = Lock() + def __new__(cls, *args, **kwds): if 'bypassRegistry' in kwds: del kwds['bypassRegistry'] inst = object.__new__(cls) inst.init(*args, **kwds) return inst - - key = cls.hashFunc(*args, **kwds) - inst, alreadyRegistered = LastfmBase.register(object.__new__(cls), key) - if not alreadyRegistered: - inst.init(*args, **kwds) - return inst - + + key = cls.hashFunc(*args, **kwds) + LastfmBase._lock.acquire() + try: + inst, alreadyRegistered = LastfmBase.register(object.__new__(cls), key) + if not alreadyRegistered: + inst.init(*args, **kwds) + finally: + LastfmBase._lock.release() + return inst + @staticmethod def register(ob, key): if not ob.__class__ in LastfmBase.registry: @@ -34,15 +44,15 @@ class LastfmBase(object): #print "not already registered: %s" % ob.__class__ LastfmBase.registry[ob.__class__][key] = ob return (ob, False) - + def __gt__(self, other): return not (self.__lt__(other) or self.__eq(other)) - + def __ne__(self, other): return not self.__eq__(other) - + def __ge__(self, other): return not self.__lt__(other) - + def __le__(self, other): - return not self.__gt__(other) \ No newline at end of file + return not self.__gt__(other) diff --git a/src/event.py b/src/event.py index 14bb170..12c8490 100644 --- a/src/event.py +++ b/src/event.py @@ -31,14 +31,13 @@ class Event(LastfmBase): self.__headliner = headliner self.__venue = venue self.__startDate = startDate - self.__startTime = startTime self.__description = description self.__image = image self.__url = url self.__stats = stats and Stats( subject = self, - attendance = self.attendance, - reviews = self.reviews + attendance = stats.attendance, + reviews = stats.reviews ) self.__tag = tag @@ -56,7 +55,7 @@ class Event(LastfmBase): def artists(self): """artists performing in the event""" return self.__artists - + @property def headliner(self): """headliner artist of the event""" @@ -72,11 +71,6 @@ class Event(LastfmBase): """start date of the event""" return self.__startDate - @property - def startTime(self): - """start time of the event""" - return self.__startTime - @property def description(self): """description of the event""" @@ -101,12 +95,47 @@ class Event(LastfmBase): def tag(self): """tags for the event""" return self.__tag - + @staticmethod def getInfo(api, event): params = {'method': 'event.getinfo', 'event': event} data = api._fetchData(params).find('event') - + return Event.createFromData(api, data) + + @staticmethod + def createFromData(api, data): + startDate = None + + if data.findtext('startTime') is not None: + startDate = datetime(*( + time.strptime( + "%s %s" % ( + data.findtext('startDate').strip(), + data.findtext('startTime').strip() + ), + '%a, %d %b %Y %H:%M' + )[0:6]) + ) + else: + try: + startDate = datetime(*( + time.strptime( + data.findtext('startDate').strip(), + '%a, %d %b %Y %H:%M:%S' + )[0:6]) + ) + except ValueError: + try: + startDate = datetime(*( + time.strptime( + data.findtext('startDate').strip(), + '%a, %d %b %Y' + )[0:6]) + ) + except ValueError: + pass + + return Event( api, id = int(data.findtext('id')), @@ -134,12 +163,7 @@ class Event(LastfmBase): ), url = data.findtext('venue/url') ), - startDate = data.findtext('startDate') and - datetime(*(time.strptime(data.findtext('startDate').strip(), '%a, %d %b %Y')[0:6])) or - None, - startTime = data.findtext('startTime') and - datetime(*(time.strptime(data.findtext('startTime').strip(), '%H:%M')[0:6])) or - None, + startDate = startDate, description = data.findtext('description'), image = dict([(i.get('size'), i.text) for i in data.findall('image')]), url = data.findtext('url'), @@ -150,31 +174,31 @@ class Event(LastfmBase): ), tag = data.findtext('tag') ) - + @staticmethod def hashFunc(*args, **kwds): try: return hash(kwds['id']) except KeyError: raise LastfmError("id has to be provided for hashing") - + def __hash__(self): return Event.hashFunc(id = self.id) - + def __eq__(self, other): return self.id == other.id - + def __lt__(self, other): return self.startDate < other.startDate - + def __repr__(self): return "" % (self.title, self.venue.name, self.startDate.strftime("%x")) - + from datetime import datetime import time from api import Api -from error import LastfmError from artist import Artist +from error import LastfmError from geo import Venue, Location, Country -from stats import Stats \ No newline at end of file +from stats import Stats diff --git a/src/filecache.py b/src/filecache.py index 38c1f83..a9e7037 100644 --- a/src/filecache.py +++ b/src/filecache.py @@ -4,9 +4,9 @@ __author__ = "Abhinav Sarkar" __version__ = "0.1" __license__ = "GNU Lesser General Public License" -import tempfile -import os import md5 +import os +import tempfile class _FileCacheError(Exception): '''Base exception class for FileCache related errors''' diff --git a/src/geo.py b/src/geo.py index 55dfd7f..00a9744 100644 --- a/src/geo.py +++ b/src/geo.py @@ -15,7 +15,7 @@ class Geo(object): page = None): params = {'method': 'geo.getevents', 'location': location} data = api._fetchData(params).find('events') - + return SearchResult( type = 'event', searchTerms = data.attrib['location'], @@ -23,47 +23,11 @@ class Geo(object): totalResults = int(data.attrib['total']), itemsPerPage = int(math.ceil(float(data.attrib['total']))/float(data.attrib['totalpages'])), matches = [ - Event( - api, - id = int(e.findtext('id')), - title = e.findtext('title'), - artists = [Artist(api, name = a.text) for a in e.findall('artists/artist')], - headliner = Artist(api, name = e.findtext('artists/headliner')), - venue = Venue( - name = e.findtext('venue/name'), - location = Location( - api, - city = e.findtext('venue/location/city'), - country = Country( - api, - name = e.findtext('venue/location/country') - ), - street = e.findtext('venue/location/street'), - postalCode = e.findtext('venue/location/postalcode'), - latitude = float(e.findtext( - 'venue/location/{%s}point/{%s}lat' % ((Location.xmlns,)*2) - )), - longitude = float(e.findtext( - 'venue/location/{%s}point/{%s}long' % ((Location.xmlns,)*2) - )), - timezone = e.findtext('venue/location/timezone') - ), - url = e.findtext('venue/url') - ), - startDate = e.findtext('startDate') and - datetime(*(time.strptime(e.findtext('startDate').strip(), '%a, %d %b %Y')[0:6])) or - None, - startTime = e.findtext('startTime') and - datetime(*(time.strptime(e.findtext('startTime').strip(), '%H:%M')[0:6])) or - None, - description = e.findtext('description'), - image = dict([(i.get('size'), i.text) for i in e.findall('image')]), - url = e.findtext('url') - ) - for e in data.findall('event') - ] + Event.createFromData(self.__api, e) + for e in data.findall('event') + ] ) - + @staticmethod def getTopArtists(api, country): params = {'method': 'geo.gettopartists', 'country': country} @@ -83,7 +47,7 @@ class Geo(object): ) for a in data.findall('artist') ] - + @staticmethod def getTopTracks(api, country): params = {'method': 'geo.gettoptracks', 'country': country} @@ -105,7 +69,7 @@ class Geo(object): playcount = int(t.findtext('playcount')) ), streamable = (t.findtext('streamable') == '1'), - fullTrack = (t.find('streamable').attrib['fulltrack'] == '1'), + fullTrack = (t.find('streamable').attrib['fulltrack'] == '1'), url = 'http://' + t.findtext('url'), image = {'large': t.findtext('image')} ) @@ -136,30 +100,30 @@ class Venue(LastfmBase): def url(self): """url of the event's page""" return self.__url - + @staticmethod def hashFunc(*args, **kwds): try: return hash(kwds['url']) except KeyError: raise LastfmError("url has to be provided for hashing") - + def __hash__(self): return self.__class__.hashFunc(url = self.url) - + def __eq__(self, other): return self.url == other.url - + def __lt__(self, other): return self.name < other.name - + def __repr__(self): return "" % (self.name, self.location.city) - + class Location(LastfmBase): """A class representing a location of an event""" xmlns = "http://www.w3.org/2003/01/geo/wgs84_pos#" - + def init(self, api, name = None, @@ -181,57 +145,57 @@ class Location(LastfmBase): self.__latitude = latitude self.__longitude = longitude self.__timezone = timezone - - @property + + @property def name(self): """name of the location""" return self.__name - @property + @property def city(self): """city in which the location is situated""" return self.__city - @property + @property def country(self): """country in which the location is situated""" return self.__country - @property + @property def street(self): """street in which the location is situated""" return self.__street - @property + @property def postalCode(self): """postal code of the location""" return self.__postalCode - @property + @property def latitude(self): """latitude of the location""" return self.__latitude - @property + @property def longitude(self): """longitude of the location""" return self.__longitude - @property + @property def timezone(self): """timezone in which the location is situated""" return self.__timezone - + def getEvents(self, distance = None, page = None): return Geo.getEvents(self.__api, self.name, distance, page).matches - - @property + + @property def events(self): """events taking place at/around the location""" return self.getEvents() - + @staticmethod def hashFunc(*args, **kwds): try: @@ -241,7 +205,7 @@ class Location(LastfmBase): return hash("name%s" % kwds['name']) except KeyError: raise LastfmError("either latitude and longitude or name has to be provided for hashing") - + def __hash__(self): if not self.name: return self.__class__.hashFunc( @@ -249,22 +213,22 @@ class Location(LastfmBase): longitude = self.longitude) else: return self.__class__.hashFunc(name = self.name) - + def __eq__(self, other): return self.latitude == other.latitude and self.longitude == other.longitude - + def __lt__(self, other): if self.country != other.country: return self.country < other.country else: return self.city < other.city - + def __repr__(self): if self.name is None: return "" % (self.latitude, self.longitude) else: return "" % self.name - + class Country(LastfmBase): """A class representing a country.""" def init(self, @@ -275,58 +239,58 @@ class Country(LastfmBase): self.__api = api self.__name = name - @property + @property def name(self): """name of the country""" return self.__name - - @property + + @property def topArtists(self): """top artists of the country""" return Geo.getTopArtists(self.__api, self.name) - - @property + + @property def topArtist(self): """top artist of the country""" return (len(self.topArtists) and self.topArtists[0] or None) - - @property + + @property def topTracks(self): """top tracks of the country""" return Geo.getTopTracks(self.__api, self.name) - + @property def topTrack(self): """top track of the country""" return (len(self.topTracks) and self.topTracks[0] or None) - + @staticmethod def hashFunc(*args, **kwds): try: return hash(kwds['name']) except KeyError: raise LastfmError("name has to be provided for hashing") - + def __hash__(self): return self.__class__.hashFunc(name = self.name) - + def __eq__(self, other): return self.name == other.name - + def __lt__(self, other): return self.name < other.name - + def __repr__(self): return "" % self.name - -import math + from datetime import datetime +import math import time from api import Api -from error import LastfmError from artist import Artist -from track import Track +from error import LastfmError from event import Event from search import SearchResult -from stats import Stats \ No newline at end of file +from stats import Stats +from track import Track diff --git a/src/registry.py b/src/registry.py index d6263ce..2697ae8 100644 --- a/src/registry.py +++ b/src/registry.py @@ -4,11 +4,10 @@ __author__ = "Abhinav Sarkar" __version__ = "0.1" __license__ = "GNU Lesser General Public License" -from base import LastfmBase -from error import LastfmError - from album import Album from artist import Artist +from base import LastfmBase +from error import LastfmError from event import Event from geo import Location, Country from group import Group @@ -16,12 +15,11 @@ from playlist import Playlist from tag import Tag from track import Track from user import User -from search import SearchResult class Registry(object): """The registry to contain all the entities""" keys = [Album, Artist, Event, Location, Country, Group, - Playlist, Tag, Track, User, SearchResult] + Playlist, Tag, Track, User] def get(self, name): if name not in Registry.keys: diff --git a/src/search.py b/src/search.py index fea9d7e..157da1b 100644 --- a/src/search.py +++ b/src/search.py @@ -4,12 +4,10 @@ __author__ = "Abhinav Sarkar" __version__ = "0.1" __license__ = "GNU Lesser General Public License" -from base import LastfmBase - -class SearchResult(LastfmBase): +class SearchResult(object): """A class to represent a search result""" xmlns = "http://a9.com/-/spec/opensearch/1.1/" - def init(self, + def __init__(self, type = None, searchTerms = None, startPage = None, @@ -63,34 +61,7 @@ class SearchResult(LastfmBase): @property def topMatch(self): return (len(self.matches) and self.matches[0] or None) - - @staticmethod - def hashFunc(*args, **kwds): - try: - return hash("%s%s%s" % (kwds['searchTerms'], kwds['type'], kwds['startPage'])) - except KeyError: - raise LastfmError("searchTerms, type and startPage have to be provided for hashing") - - def __hash__(self): - return self.__class__.hashFunc( - searchTerms = self.searchTerms, - type = self.type, - startPage = self.startPage - ) - - def __eq__(self, other): - return ( - self.searchTerms == other.searchTerms and - self.type == other.type and - self.startIndex == other.startIndex - ) - - def __lt__(self, other): - if self.searchTerms != other.searchTerms: - return self.searchTerms < other.searchTerms - else: - return self.startIndex < other.startIndex - + def __repr__(self): return "" % (self.type, self.searchTerms) diff --git a/src/tag.py b/src/tag.py index d826043..e73078a 100644 --- a/src/tag.py +++ b/src/tag.py @@ -230,10 +230,10 @@ class Tag(LastfmBase): def __repr__(self): return "" % self.name -from api import Api -from error import LastfmError from album import Album +from api import Api from artist import Artist -from track import Track +from error import LastfmError +from search import SearchResult from stats import Stats -from search import SearchResult \ No newline at end of file +from track import Track \ No newline at end of file diff --git a/src/tasteometer.py b/src/tasteometer.py index 8f284c5..07d8ae3 100644 --- a/src/tasteometer.py +++ b/src/tasteometer.py @@ -12,7 +12,7 @@ class Tasteometer(object): artists = None): self.__score = score self.__matches = matches - self.__artists = artists#set + self.__artists = artists @property def score(self): @@ -63,6 +63,4 @@ class Tasteometer(object): def __repr__(self): return "" -from artist import Artist -from error import LastfmError - \ No newline at end of file +from artist import Artist \ No newline at end of file diff --git a/src/track.py b/src/track.py index d095888..191280c 100644 --- a/src/track.py +++ b/src/track.py @@ -259,9 +259,9 @@ class Track(LastfmBase): return "" % (self.name, self.artist.name) from api import Api -from error import LastfmError -from user import User -from tag import Tag -from stats import Stats from artist import Artist -from search import SearchResult \ No newline at end of file +from error import LastfmError +from search import SearchResult +from stats import Stats +from tag import Tag +from user import User \ No newline at end of file diff --git a/src/user.py b/src/user.py index a12ba97..8ade710 100644 --- a/src/user.py +++ b/src/user.py @@ -25,6 +25,7 @@ class User(LastfmBase): match = stats.match, weight = stats.weight ) + self.__events = None @property def name(self): @@ -45,99 +46,111 @@ class User(LastfmBase): def stats(self): """stats for the user""" return self.__stats - + @property def events(self): + if self.__events is None: + params = {'method': 'user.getevents', 'user': self.name} + data = self.__api._fetchData(params).find('events') + + self.__events = [ + Event.createFromData(self.__api, e) + for e in data.findall('event') + ] + return self.__events + + @property + def pastEvents(self): pass - + def getFriends(self, recentTracks = False, limit = None): pass - + @property def friends(self): """friends of the user""" return self.getFriends() - + def getNeighbours(self, limit = None): pass - + @property def neighbours(self): """neightbours of the user""" return self.getNeighbours() - + @property def playlists(self): """playlists of the user""" pass - + def getRecentTracks(self, limit = None): pass - + @property def recentTracks(self): """recent tracks played by the user""" return self.getRecentTracks() - + @property def mostRecentTrack(self): """most recent track played by the user""" return (len(self.recentTracks) and self.recentTracks[0] or None) - + def getTopAlbums(self, period = None): pass - + @property def topAlbums(self): """top albums of the user""" return self.getTopAlbums() - + @property def topAlbum(self): """top album fo the user""" return (len(self.topAlbums) and self.topAlbums[0] or None) - + def getTopArtists(self, period = None): pass - + @property def topArtists(self): """top artists of the user""" return self.getTopArtists() - + @property def topArtist(self): """top artist of the user""" return (len(self.topArtists) and self.topArtists[0] or None) - + def getTopTracks(self, period = None): pass - + @property def topTracks(self): """top tracks of the user""" return self.getTopTracks() - + @property def topTrack(self): """top track of the user""" return (len(self.topTracks) and self.topTracks[0] or None) - + def getTopTags(self, limit = None): pass - + @property def topTags(self): """top tags of the user""" return self.getTopTags() - + @property def topTag(self): """top tag of the user""" return (len(self.topTags) and self.topTags[0] or None) - + @property def weeklyChartList(self): pass @@ -146,48 +159,49 @@ class User(LastfmBase): start = None, end = None): pass - + @property def recentWeeklyAlbumChart(self): return self.getWeeklyAlbumChart() - + def getWeeklyArtistChart(self, start = None, end = None): pass - + @property def recentWeeklyArtistChart(self): return self.getWeeklyArtistChart() - + def getWeeklyTrackChart(self, start = None, end = None): pass - + @property def recentWeeklyTrackChart(self): return self.getWeeklyTrackChart() - + @staticmethod def hashFunc(*args, **kwds): try: return hash(kwds['name']) except KeyError: raise LastfmError("name has to be provided for hashing") - + def __hash__(self): return self.__class__.hashFunc(name = self.name) - + def __eq__(self, other): return self.name == other.name - + def __lt__(self, other): return self.name < other.name - + def __repr__(self): return "" % self.name from api import Api from error import LastfmError -from stats import Stats \ No newline at end of file +from event import Event +from stats import Stats