fixed #1, added an option to disable silent exception handling

This commit is contained in:
Amr Hassan 2008-08-21 08:44:30 +00:00
parent 4676e8ecd6
commit ec1304614e

111
pylast.py
View file

@ -22,7 +22,7 @@
# documentation at http://code.google.com/p/pylast/wiki/Documentation # documentation at http://code.google.com/p/pylast/wiki/Documentation
LIB_NAME = 'pyLast' LIB_NAME = 'pyLast'
LIB_VERSION = '0.2b' LIB_VERSION = '0.2b1'
API_SERVER = 'ws.audioscrobbler.com' API_SERVER = 'ws.audioscrobbler.com'
API_SUBDIR = '/2.0/' API_SUBDIR = '/2.0/'
@ -33,6 +33,8 @@ import urllib
import threading import threading
from xml.dom import minidom from xml.dom import minidom
USE_SILENT_EXCEPTIONS = True
STATUS_OK = 'ok' STATUS_OK = 'ok'
STATUS_FAILED = 'failed' STATUS_FAILED = 'failed'
STATUS_INVALID_SERVICE = 2 STATUS_INVALID_SERVICE = 2
@ -81,18 +83,18 @@ def _status2str(lastfm_status):
STATUS_OK: 'OK', STATUS_OK: 'OK',
STATUS_FAILED: 'Failed', STATUS_FAILED: 'Failed',
STATUS_INVALID_METHOD: 'Invalid Method - No method with that name in this package', STATUS_INVALID_METHOD: 'Invalid Method - No method with that name in this package',
STATUS_TOKEN_ERROR: 'There was an error granting the request token.', STATUS_TOKEN_ERROR: 'Token Error - There was an error granting the request token',
STATUS_INVALID_SERVICE: 'Invalid service - This service does not exist', STATUS_INVALID_SERVICE: 'Invalid Service - This service does not exist',
STATUS_AUTH_FAILED: 'Authentication Failed - You do not have permissions to access the service', STATUS_AUTH_FAILED: 'Authentication Failed - You do not have permissions to access the service',
STATUS_INVALID_FORMAT: "Invalid format - This service doesn't exist in that format", STATUS_INVALID_FORMAT: "Invalid Format - This service doesn't exist in that format",
STATUS_INVALID_PARAMS: 'Invalid parameters - Your request is missing a required parameter', STATUS_INVALID_PARAMS: 'Invalid Parameters - Your request is missing a required parameter',
STATUS_INVALID_RESOURCE: 'Invalid resource specified', STATUS_INVALID_RESOURCE: 'Invalid Resource Specified',
STATUS_INVALID_SK: 'Invalid session key - Please re-authenticate', STATUS_INVALID_SK: 'Invalid Session Key - Please re-authenticate',
STATUS_INVALID_API_KEY: 'Invalid API key - You must be granted a valid key by last.fm', STATUS_INVALID_API_KEY: 'Invalid API Key - You must be granted a valid key by last.fm',
STATUS_OFFLINE: 'Service Offline - This service is temporarily offline. Try again later.', STATUS_OFFLINE: 'Service Offline - This service is temporarily offline. Try again later.',
STATUS_SUBSCRIBERS_ONLY: 'Subscribers Only - This service is only available to paid last.fm subscribers', STATUS_SUBSCRIBERS_ONLY: 'Subscribers Only - This service is only available to paid last.fm subscribers',
STATUS_TOKEN_UNAUTHORIZED: 'This token has not been authorized', STATUS_TOKEN_UNAUTHORIZED: 'Unauthorized Token - This token has not been authorized',
STATUS_TOKEN_EXPIRED: 'This token has expired' STATUS_TOKEN_EXPIRED: 'Token Expired -This token has expired'
} }
return statuses[int(lastfm_status)] return statuses[int(lastfm_status)]
@ -141,9 +143,9 @@ class Asynchronizer(threading.Thread):
class Exceptionable(object): class Exceptionable(object):
"""An abstract class that adds support for error reporting.""" """An abstract class that adds support for error reporting."""
def __init__(self, parent = None, raising_exceptions = False): def __init__(self, parent = None):
self.__errors = [] self.__errors = []
self.__raising_exceptions = raising_exceptions self.__raising_exceptions = not USE_SILENT_EXCEPTIONS
#An Exceptionable parent to mirror all the errors to automatically. #An Exceptionable parent to mirror all the errors to automatically.
self._parent = parent self._parent = parent
@ -390,8 +392,9 @@ class Cacheable(object):
def __init__(self, user_set_data = False): def __init__(self, user_set_data = False):
# user_set_data identifies objects like Track that doesn't have # user_set_data (a temporary workaround, should be deprecated soon) identifies objects like
# a getInfo function, so the user sets the extra data from other feeds # Track that doesn't have a getInfo function,
# so the user sets the extra data from other feeds for now.
self._cached_info = None self._cached_info = None
self._user_set_data = user_set_data self._user_set_data = user_set_data
@ -399,9 +402,9 @@ class Cacheable(object):
def _getInfo(self): def _getInfo(self):
"""Abstract function, should be inherited""" """Abstract function, should be inherited"""
def _getCachedInfo(self): def _getCachedInfo(self, *key_names):
"""Returns the cached collection of info regarding this object """Returns the cached collection of info regarding this object
If not available in cache, it will be downloaded first If not available in cache, it will be downloaded first.
""" """
if self._user_set_data: if self._user_set_data:
@ -410,10 +413,17 @@ class Cacheable(object):
if not self._cached_info: if not self._cached_info:
self._cached_info = self._getInfo() self._cached_info = self._getInfo()
return self._cached_info if not self._cached_info:
return None
value_or_container = self._cached_info
for key in key_names:
value_or_container = value_or_container[key]
return value_or_container
def _setCachedInfo(self, info): def _setCachedInfo(self, info):
"""Set the info for objects that does not have a getInfo function""" """Set the info for objects that does not have a getInfo function (Temporary workaround, should be deprecated soon)"""
self._cached_info = info self._cached_info = info
@ -470,7 +480,7 @@ class Album(BaseObject, Cacheable):
def getReleaseDate(self): def getReleaseDate(self):
"""Retruns the release date of the album.""" """Retruns the release date of the album."""
return self._getCachedInfo()['release_date'] return self._getCachedInfo('release_date')
def getImage(self, size = IMAGE_LARGE): def getImage(self, size = IMAGE_LARGE):
"""Returns the associated image URL. """Returns the associated image URL.
@ -480,28 +490,28 @@ class Album(BaseObject, Cacheable):
o IMAGE_SMALL o IMAGE_SMALL
""" """
return self._getCachedInfo()['images'][size] return self._getCachedInfo('images', size)
def getID(self): def getID(self):
"""Returns the Last.fm ID. """ """Returns the Last.fm ID. """
return self._getCachedInfo()['id'] return self._getCachedInfo('id')
def getPlayCount(self): def getPlayCount(self):
"""Returns the number of plays on Last.fm.""" """Returns the number of plays on Last.fm."""
return self._getCachedInfo()['play_count'] return self._getCachedInfo('play_count')
def getListenerCount(self): def getListenerCount(self):
"""Returns the number of liteners on Last.fm.""" """Returns the number of liteners on Last.fm."""
return self._getCachedInfo()['listeners'] return self._getCachedInfo('listeners')
def getTopTags(self): def getTopTags(self):
"""Returns a list of the most-applied tags to this album. """ """Returns a list of the most-applied tags to this album. """
l = [] l = []
for tag in self._getCachedInfo()['top_tags']: for tag in self._getCachedInfo('top_tags'):
l.append(Tag(tag, *self.auth_data)) l.append(Tag(tag, *self.auth_data))
return l return l
@ -577,7 +587,7 @@ class Album(BaseObject, Cacheable):
def fetchPlaylist(self): def fetchPlaylist(self):
"""Returns the list of Tracks on this album. """ """Returns the list of Tracks on this album. """
uri = 'lastfm://playlist/album/%s' %self._getCachedInfo()['id'] uri = 'lastfm://playlist/album/%s' %self._getCachedInfo('id')
return Playlist(uri, *self.auth_data).fetch() return Playlist(uri, *self.auth_data).fetch()
@ -874,32 +884,32 @@ class Artist(BaseObject, Cacheable):
o IMAGE_SMALL o IMAGE_SMALL
""" """
return self._getCachedInfo()['images'][size] return self._getCachedInfo('images', size)
def getPlayCount(self): def getPlayCount(self):
"""Returns the number of plays on Last.fm. """ """Returns the number of plays on Last.fm. """
return self._getCachedInfo()['play_count'] return self._getCachedInfo('play_count')
def getListenerCount(self): def getListenerCount(self):
"""Returns the number of liteners on Last.fm. """ """Returns the number of liteners on Last.fm. """
return self._getCachedInfo()['listeners'] return self._getCachedInfo('listeners')
def getBioPublishedDate(self): def getBioPublishedDate(self):
"""Returns the date on which the artist's biography was published. """ """Returns the date on which the artist's biography was published. """
return self._getCachedInfo()['bio']['published'] return self._getCachedInfo('bio', 'published')
def getBioSummary(self): def getBioSummary(self):
"""Returns the summary of the artist's biography. """ """Returns the summary of the artist's biography. """
return self._getCachedInfo()['bio']['summary'] return self._getCachedInfo('bio', 'summary')
def getBioContent(self): def getBioContent(self):
"""Returns the content of the artist's biography. """ """Returns the content of the artist's biography. """
return self._getCachedInfo()['bio']['content'] return self._getCachedInfo('bio', 'content')
def addTags(self, *tags): def addTags(self, *tags):
"""Adds one or several tags. """Adds one or several tags.
@ -1207,17 +1217,17 @@ class Event(BaseObject, Cacheable):
def getTitle(self): def getTitle(self):
"""Returns the title of the event. """ """Returns the title of the event. """
return self._getCachedInfo()['title'] return self._getCachedInfo('title')
def getHeadliner(self): def getHeadliner(self):
"""Returns the headliner of the event. """ """Returns the headliner of the event. """
return self._getCachedInfo()['headliner'] return self._getCachedInfo('headliner')
def getArtists(self): def getArtists(self):
"""Returns a list of the participating Artists. """ """Returns a list of the participating Artists. """
names = self._getCachedInfo()['artists'] names = self._getCachedInfo('artists')
artists = [] artists = []
for name in names: for name in names:
@ -1228,43 +1238,43 @@ class Event(BaseObject, Cacheable):
def getVenueName(self): def getVenueName(self):
"""Returns the name of the venue where the event is held. """ """Returns the name of the venue where the event is held. """
return self._getCachedInfo()['venue']['name'] return self._getCachedInfo('venue', 'name')
def getCityName(self): def getCityName(self):
"""Returns the name of the city where the event is held. """ """Returns the name of the city where the event is held. """
return self._getCachedInfo()['venue']['city'] return self._getCachedInfo('venue', 'city')
def getCountryName(self): def getCountryName(self):
"""Returns the name of the country where the event is held. """ """Returns the name of the country where the event is held. """
return self._getCachedInfo()['venue']['country'] return self._getCachedInfo('venue', 'country')
def getPostalCode(self): def getPostalCode(self):
"""Returns the postal code of where the event is held. """ """Returns the postal code of where the event is held. """
return self._getCachedInfo()['venue']['postal_code'] return self._getCachedInfo('venue', 'postal_code')
def getStreetName(self): def getStreetName(self):
"""Returns the name of the street where the event is held. """ """Returns the name of the street where the event is held. """
return self._getCachedInfo()['venue']['street'] return self._getCachedInfo('venue', 'street')
def getGeoPoint(self): def getGeoPoint(self):
"""Returns a tuple of latitude and longitude values of where the event is held. """ """Returns a tuple of latitude and longitude values of where the event is held. """
i = self._getCachedInfo() i = (self._getCachedInfo('venue', 'geo', 'lat'), self._getCachedInfo('venue', 'geo', 'long'))
return (i['venue']['geo']['lat'], i['venue']['geo']['long']) return i
def getTimeZone(self): def getTimeZone(self):
"""Returns the timezone of where the event is held. """ """Returns the timezone of where the event is held. """
return self._getCachedInfo()['venue']['time_zone'] return self._getCachedInfo('venue', 'time_zone')
def getDescription(self): def getDescription(self):
"""Returns the description of the event. """ """Returns the description of the event. """
return self._getCachedInfo()['description'] return self._getCachedInfo('description')
def getImage(self, size = IMAGE_LARGE): def getImage(self, size = IMAGE_LARGE):
"""Returns the associated image URL. """Returns the associated image URL.
@ -1274,17 +1284,18 @@ class Event(BaseObject, Cacheable):
o IMAGE_SMALL o IMAGE_SMALL
""" """
return self._getCachedInfo()['images'][size]
return self._getCachedInfo('images', size)
def getAttendanceCount(self): def getAttendanceCount(self):
"""Returns the number of attending people. """ """Returns the number of attending people. """
return self._getCachedInfo()['attendance'] return self._getCachedInfo('attendance')
def getReviewCount(self): def getReviewCount(self):
"""Returns the number of available reviews for this event. """ """Returns the number of available reviews for this event. """
return self._getCachedInfo()['reviews'] return self._getCachedInfo('reviews')
def getURL(self, domain_name = DOMAIN_ENGLISH): def getURL(self, domain_name = DOMAIN_ENGLISH):
"""Returns the url of the event page on Last.fm. """Returns the url of the event page on Last.fm.
@ -1328,6 +1339,8 @@ class Event(BaseObject, Cacheable):
class Country(BaseObject): class Country(BaseObject):
# TODO geo.getEvents
def __init__(self, country_name, api_key, secret, session_key): def __init__(self, country_name, api_key, secret, session_key):
BaseObject.__init__(self, api_key, secret, session_key) BaseObject.__init__(self, api_key, secret, session_key)
@ -2027,6 +2040,8 @@ class User(BaseObject):
BaseObject.__init__(self, api_key, api_secret, session_key) BaseObject.__init__(self, api_key, api_secret, session_key)
self._user_name = user_name self._user_name = user_name
#TODO user.getInfo is available now
def _getParams(self): def _getParams(self):
return {'sk': self.session_key, 'user': self._user_name} return {'sk': self.session_key, 'user': self._user_name}
@ -2119,6 +2134,10 @@ class User(BaseObject):
def getPastEvents(self, limit = None): def getPastEvents(self, limit = None):
"""Retruns the past events of this user. """ """Retruns the past events of this user. """
# TODO
# http://www.last.fm/api/show?service=343
# use the page value
params = self._getParams() params = self._getParams()
if limit: if limit:
params['limit'] = limit params['limit'] = limit