Source code for gravatar

import base64
import collections
import hashlib
from   xmlrpclib import Fault, ServerProxy

API_ENDPOINT = 'https://secure.gravatar.com/xmlrpc'

[docs]def hash_email(email): """ :param string email: email address :returns: the hash of ``email``, suitable for embedding in a URL to retrieve its assigned image, e.g., ``http://gravatar.com/avatar/<hash>`` """ return hashlib.md5(email.strip().lower()).hexdigest()
def _check_email_success(response): for email, success in response.iteritems(): if not success: raise InvalidEmailError(email)
[docs]class Rating: """ Image rating. ====== ===== Member Value ====== ===== G 0 PG 1 R 2 X 3 ====== ===== """ G = 0 PG = 1 R = 2 X = 3
class GravatarError(Exception): pass class SecureError(GravatarError): pass class InternalError(GravatarError): pass class AuthenticationError(GravatarError): pass class ParameterMissingError(GravatarError): pass class ParameterIncorrectError(GravatarError): pass class MiscError(GravatarError): pass class UnknownError(GravatarError): pass class InvalidEmailError(GravatarError): pass class InvalidUrlError(GravatarError): pass class InvalidDataError(GravatarError): pass class InvalidImageIdError(GravatarError): pass
[docs]class Image(collections.namedtuple('Image', ['id', 'url', 'rating'])): """ Represents an image in a user account. :var id: unique ID used to refer to this image :type id: `string` :var url: unique URL to retrieve this image, even if it is unassigned :type url: `string` :var rating: rating for the image :type rating: `int` (see :class:`Rating`) """ pass
[docs]class User(object): """ Represents a user account. """ def __init__(self, email, password=None, apikey=None): """ At least one of ``password`` and ``apikey`` must be specified. :param string email: an email address belonging to the account :param string password: password for the account :param string apikey: API key for your application """ self._server = ServerProxy(API_ENDPOINT+'?user='+hash_email(email)) if password is None and apikey is None: raise ValueError("Must specify either 'password' or 'apikey' parameter") self.password = password self.apikey = apikey
[docs] def exists(self, *emails): """ :param emails: email addresses to check :type emails: vararg list of `string` :returns: dictionary where each key is an email address from the passed-in list and each value is a boolean of whether that email address belongs to a Gravatar account and has an image assigned to it. :rtype: {`string`: `boolean`} """ hashes = dict([(hash_email(email), email) for email in emails]) return dict([(hashes[hash], found==1) for hash, found in self._call('exists', hashes=hashes.keys()).iteritems()])
[docs] def emails(self): """ :returns: dictionary where each key is an email address belonging to the user account and each value is the :class:`Image` assigned to it, or ``None`` if no image is assigned :rtype: {`string`: :class:`Image`} """ return dict([(email, Image(id=userimage['userimage'], url=userimage['userimage_url'], rating=userimage['rating']) if len(userimage['userimage']) > 0 else None) for email, userimage in self._call('addresses').iteritems()])
[docs] def images(self): """ :returns: images belonging to the user account :rtype: list of :class:`Image` """ return [Image(id=id, url=url, rating=int(rating)) for id, (rating, url) in self._call('userimages').iteritems()]
[docs] def saveData(self, data, rating): """ Save the data as a new image in the user account. :param string data: binary image data to save :param rating: rating for the new image :type rating: `int` (see :class:`Rating`) :returns: ID of new image :rtype: `string` """ id = self._call('saveData', data=base64.b64encode(data), rating=rating) if not id: raise InvalidDataError() return id
[docs] def saveUrl(self, url, rating): """ Read the image pointed to by the URL and save it as a new image in the user account. :param string url: URL pointing to an image to save :param rating: rating for the new image :type rating: `int` (see :class:`Rating`) :returns: ID of new image :rtype: `string` """ id = self._call('saveUrl', url=url, rating=rating) if not id: raise InvalidURLError(url) return id
[docs] def useImage(self, id, *emails): """ Assign the image identified by an ID to every email address passed in. :param string id: ID of image to assign :param emails: email addresses to assign the image to :type emails: vararg list of `string` """ _check_email_success(self._call('useUserimage', userimage=id, addresses=emails))
[docs] def removeImage(self, *emails): """ For every email address passed in, unassign its image. :param emails: email addresses to be unassigned :type emails: vararg list of `string` """ _check_email_success(self._call('removeImage', addresses=emails))
[docs] def deleteImage(self, id): """ Delete the image from the user account, and unassign it from any email addresses. :param string id: ID of image to delete """ if not self._call('deleteUserimage', userimage=id): raise InvalidImageIdError(id)
[docs] def test(self): """ :returns: the server's number of seconds since the current epoch. :rtype: `int` """ return self._call('test')['response']
def _call(self, method, **kwargs): if self.password is not None: kwargs['password'] = self.password if self.apikey is not None: kwargs['apikey'] = self.apikey try: return getattr(self._server.grav, method)(kwargs) except Fault as fault: raise { -7: SecureError, -8: InternalError, -9: AuthenticationError, -10: ParameterMissingError, -11: ParameterIncorrectError, -100: MiscError, }.get(fault.faultCode, UnknownError)(fault.faultString)