class ConnectionError(Exception): def __init__(self, response, content=None, message=None): self.response = response self.content = content self.message = message def __str__(self): message = "Failed." if hasattr(self.response, 'status_code'): message += " Response status: %s." % (self.response.status_code) if hasattr(self.response, 'reason'): message += " Response message: %s." % (self.response.reason) if hasattr(self.response, 'request'): message += " Request URL: %s." % self.response.request.url if self.content is not None: message += " Error message: " + str(self.content) return message class Redirection(ConnectionError): """3xx Redirection """ def __str__(self): message = super(Redirection, self).__str__() if self.response.get('Location'): message = "%s => %s" % (message, self.response.get('Location')) return message class MissingParam(TypeError): pass class MissingConfig(Exception): pass class ClientError(ConnectionError): """4xx Client Error """ pass class BadRequest(ClientError): """400 Bad Request """ pass class UnauthorizedAccess(ClientError): """401 Unauthorized """ pass class ForbiddenAccess(ClientError): """403 Forbidden """ pass class ResourceNotFound(ClientError): """404 Not Found """ pass class ResourceConflict(ClientError): """409 Conflict """ pass class ResourceGone(ClientError): """410 Gone """ pass class PreconditionFailed(ClientError): """412 Precondition Failed""" pass class RequestEntityTooLarge(ClientError): """413 Request Entity Too Large""" pass class ResourceInvalid(ClientError): """422 Invalid """ pass class ServerError(ConnectionError): """5xx Server Error """ pass class MethodNotAllowed(ClientError): """405 Method Not Allowed """ def allowed_methods(self): return self.response['Allow'] _exception_map = { 301: Redirection, 302: Redirection, 303: Redirection, 307: Redirection, 400: BadRequest, 401: UnauthorizedAccess, 403: ForbiddenAccess, 404: ResourceNotFound, 405: MethodNotAllowed, 409: ResourceConflict, 410: ResourceGone, 412: PreconditionFailed, 413: RequestEntityTooLarge, 422: ResourceInvalid, } def exception_for_status(status_code): """Returns the exception class for the given status code.""" try: return _exception_map[status_code] except KeyError: pass if 400 <= status_code <= 499: return ClientError elif 500 <= status_code <= 599: return ServerError return None