diff --git a/keystoneclient/apiclient/__init__.py b/keystoneclient/apiclient/__init__.py index 4930ae29b..6c594f40b 100644 --- a/keystoneclient/apiclient/__init__.py +++ b/keystoneclient/apiclient/__init__.py @@ -13,6 +13,16 @@ # License for the specific language governing permissions and limitations # under the License. +import warnings + +# NOTE(akurilin): Module 'keystoneclient.apiclient' contains only exceptions +# which are deprecated, so this module must also be deprecated which helps +# to report 'deprecated' status of exceptions for next kind of imports +# from keystoneclient.apiclient import exceptions + +warnings.warn("The 'keystoneclient.apiclient' module is deprecated since " + "v.0.7.1. Use 'keystoneclient.exceptions' instead of this " + "module.", DeprecationWarning) __all__ = [ 'exceptions', diff --git a/keystoneclient/apiclient/exceptions.py b/keystoneclient/apiclient/exceptions.py index affcf92fd..982820830 100644 --- a/keystoneclient/apiclient/exceptions.py +++ b/keystoneclient/apiclient/exceptions.py @@ -18,423 +18,16 @@ """ Exception definitions. + +Deprecated since v0.7.1. Use 'keystoneclient.exceptions' instead of +this module. """ -import itertools +import warnings +from keystoneclient.exceptions import * # noqa -class ClientException(Exception): - """The base exception class for all exceptions this library raises. - """ - pass - -class MissingArgs(ClientException): - """Supplied arguments are not sufficient for calling a function.""" - def __init__(self, missing): - self.missing = missing - msg = "Missing argument(s): %s" % ", ".join(missing) - super(MissingArgs, self).__init__(msg) - - -class ValidationError(ClientException): - """Error in validation on API client side.""" - pass - - -class UnsupportedVersion(ClientException): - """User is trying to use an unsupported version of the API.""" - pass - - -class CommandError(ClientException): - """Error in CLI tool.""" - pass - - -class AuthorizationFailure(ClientException): - """Cannot authorize API client.""" - pass - - -class AuthPluginOptionsMissing(AuthorizationFailure): - """Auth plugin misses some options.""" - def __init__(self, opt_names): - super(AuthPluginOptionsMissing, self).__init__( - "Authentication failed. Missing options: %s" % - ", ".join(opt_names)) - self.opt_names = opt_names - - -class AuthSystemNotFound(AuthorizationFailure): - """User has specified a AuthSystem that is not installed.""" - def __init__(self, auth_system): - super(AuthSystemNotFound, self).__init__( - "AuthSystemNotFound: %s" % repr(auth_system)) - self.auth_system = auth_system - - -class NoUniqueMatch(ClientException): - """Multiple entities found instead of one.""" - pass - - -class EndpointException(ClientException): - """Something is rotten in Service Catalog.""" - pass - - -class EndpointNotFound(EndpointException): - """Could not find requested endpoint in Service Catalog.""" - pass - - -class EmptyCatalog(EndpointNotFound): - """The service catalog is empty.""" - pass - - -class AmbiguousEndpoints(EndpointException): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - super(AmbiguousEndpoints, self).__init__( - "AmbiguousEndpoints: %s" % repr(endpoints)) - self.endpoints = endpoints - - -class HTTPError(ClientException): - """The base exception class for all HTTP exceptions. - """ - http_status = 0 - message = "HTTP Error" - - def __init__(self, message=None, details=None, - response=None, request_id=None, - url=None, method=None, http_status=None): - self.http_status = http_status or self.http_status - self.message = message or self.message - self.details = details - self.request_id = request_id - self.response = response - self.url = url - self.method = method - formatted_string = "%(message)s (HTTP %(status)s)" % { - "message": self.message, "status": self.http_status} - if request_id: - formatted_string += " (Request-ID: %s)" % request_id - super(HTTPError, self).__init__(formatted_string) - - -class HTTPClientError(HTTPError): - """Client-side HTTP error. - - Exception for cases in which the client seems to have erred. - """ - message = "HTTP Client Error" - - -class HTTPServerError(HTTPError): - """Server-side HTTP error. - - Exception for cases in which the server is aware that it has - erred or is incapable of performing the request. - """ - message = "HTTP Server Error" - - -class BadRequest(HTTPClientError): - """HTTP 400 - Bad Request. - - The request cannot be fulfilled due to bad syntax. - """ - http_status = 400 - message = "Bad Request" - - -class Unauthorized(HTTPClientError): - """HTTP 401 - Unauthorized. - - Similar to 403 Forbidden, but specifically for use when authentication - is required and has failed or has not yet been provided. - """ - http_status = 401 - message = "Unauthorized" - - -class PaymentRequired(HTTPClientError): - """HTTP 402 - Payment Required. - - Reserved for future use. - """ - http_status = 402 - message = "Payment Required" - - -class Forbidden(HTTPClientError): - """HTTP 403 - Forbidden. - - The request was a valid request, but the server is refusing to respond - to it. - """ - http_status = 403 - message = "Forbidden" - - -class NotFound(HTTPClientError): - """HTTP 404 - Not Found. - - The requested resource could not be found but may be available again - in the future. - """ - http_status = 404 - message = "Not Found" - - -class MethodNotAllowed(HTTPClientError): - """HTTP 405 - Method Not Allowed. - - A request was made of a resource using a request method not supported - by that resource. - """ - http_status = 405 - message = "Method Not Allowed" - - -class NotAcceptable(HTTPClientError): - """HTTP 406 - Not Acceptable. - - The requested resource is only capable of generating content not - acceptable according to the Accept headers sent in the request. - """ - http_status = 406 - message = "Not Acceptable" - - -class ProxyAuthenticationRequired(HTTPClientError): - """HTTP 407 - Proxy Authentication Required. - - The client must first authenticate itself with the proxy. - """ - http_status = 407 - message = "Proxy Authentication Required" - - -class RequestTimeout(HTTPClientError): - """HTTP 408 - Request Timeout. - - The server timed out waiting for the request. - """ - http_status = 408 - message = "Request Timeout" - - -class Conflict(HTTPClientError): - """HTTP 409 - Conflict. - - Indicates that the request could not be processed because of conflict - in the request, such as an edit conflict. - """ - http_status = 409 - message = "Conflict" - - -class Gone(HTTPClientError): - """HTTP 410 - Gone. - - Indicates that the resource requested is no longer available and will - not be available again. - """ - http_status = 410 - message = "Gone" - - -class LengthRequired(HTTPClientError): - """HTTP 411 - Length Required. - - The request did not specify the length of its content, which is - required by the requested resource. - """ - http_status = 411 - message = "Length Required" - - -class PreconditionFailed(HTTPClientError): - """HTTP 412 - Precondition Failed. - - The server does not meet one of the preconditions that the requester - put on the request. - """ - http_status = 412 - message = "Precondition Failed" - - -class RequestEntityTooLarge(HTTPClientError): - """HTTP 413 - Request Entity Too Large. - - The request is larger than the server is willing or able to process. - """ - http_status = 413 - message = "Request Entity Too Large" - - def __init__(self, *args, **kwargs): - try: - self.retry_after = int(kwargs.pop('retry_after')) - except (KeyError, ValueError): - self.retry_after = 0 - - super(RequestEntityTooLarge, self).__init__(*args, **kwargs) - - -class RequestUriTooLong(HTTPClientError): - """HTTP 414 - Request-URI Too Long. - - The URI provided was too long for the server to process. - """ - http_status = 414 - message = "Request-URI Too Long" - - -class UnsupportedMediaType(HTTPClientError): - """HTTP 415 - Unsupported Media Type. - - The request entity has a media type which the server or resource does - not support. - """ - http_status = 415 - message = "Unsupported Media Type" - - -class RequestedRangeNotSatisfiable(HTTPClientError): - """HTTP 416 - Requested Range Not Satisfiable. - - The client has asked for a portion of the file, but the server cannot - supply that portion. - """ - http_status = 416 - message = "Requested Range Not Satisfiable" - - -class ExpectationFailed(HTTPClientError): - """HTTP 417 - Expectation Failed. - - The server cannot meet the requirements of the Expect request-header field. - """ - http_status = 417 - message = "Expectation Failed" - - -class UnprocessableEntity(HTTPClientError): - """HTTP 422 - Unprocessable Entity. - - The request was well-formed but was unable to be followed due to semantic - errors. - """ - http_status = 422 - message = "Unprocessable Entity" - - -class InternalServerError(HTTPServerError): - """HTTP 500 - Internal Server Error. - - A generic error message, given when no more specific message is suitable. - """ - http_status = 500 - message = "Internal Server Error" - - -# NotImplemented is a python keyword. -class HTTPNotImplemented(HTTPServerError): - """HTTP 501 - Not Implemented. - - The server either does not recognize the request method, or it lacks - the ability to fulfill the request. - """ - http_status = 501 - message = "Not Implemented" - - -class BadGateway(HTTPServerError): - """HTTP 502 - Bad Gateway. - - The server was acting as a gateway or proxy and received an invalid - response from the upstream server. - """ - http_status = 502 - message = "Bad Gateway" - - -class ServiceUnavailable(HTTPServerError): - """HTTP 503 - Service Unavailable. - - The server is currently unavailable. - """ - http_status = 503 - message = "Service Unavailable" - - -class GatewayTimeout(HTTPServerError): - """HTTP 504 - Gateway Timeout. - - The server was acting as a gateway or proxy and did not receive a timely - response from the upstream server. - """ - http_status = 504 - message = "Gateway Timeout" - - -class HTTPVersionNotSupported(HTTPServerError): - """HTTP 505 - HTTPVersion Not Supported. - - The server does not support the HTTP protocol version used in the request. - """ - http_status = 505 - message = "HTTP Version Not Supported" - - -_code_map = dict( - (cls.http_status, cls) - for cls in itertools.chain(HTTPClientError.__subclasses__(), - HTTPServerError.__subclasses__())) - - -def from_response(response, method, url): - """Returns an instance of :class:`HTTPError` or subclass based on response. - - :param response: instance of `requests.Response` class - :param method: HTTP method used for request - :param url: URL used for request - """ - kwargs = { - "http_status": response.status_code, - "response": response, - "method": method, - "url": url, - "request_id": response.headers.get("x-compute-request-id"), - } - if "retry-after" in response.headers: - kwargs["retry_after"] = response.headers["retry-after"] - - content_type = response.headers.get("Content-Type", "") - if content_type.startswith("application/json"): - try: - body = response.json() - except ValueError: - pass - else: - if hasattr(body, "keys"): - error = body[list(body)[0]] - kwargs["message"] = error.get("message") - kwargs["details"] = error.get("details") - elif content_type.startswith("text/"): - kwargs["details"] = response.text - - try: - cls = _code_map[response.status_code] - except KeyError: - if 500 <= response.status_code < 600: - cls = HTTPServerError - elif 400 <= response.status_code < 500: - cls = HTTPClientError - else: - cls = HTTPError - return cls(**kwargs) +warnings.warn("The 'keystoneclient.apiclient.exceptions' module is deprecated " + "since v.0.7.1. Use 'keystoneclient.exceptions' instead of this " + "module.", DeprecationWarning) diff --git a/keystoneclient/exceptions.py b/keystoneclient/exceptions.py index c4620740e..c688facee 100644 --- a/keystoneclient/exceptions.py +++ b/keystoneclient/exceptions.py @@ -17,7 +17,14 @@ Exception definitions. """ #flake8: noqa -from keystoneclient.apiclient.exceptions import * +from keystoneclient.openstack.common.apiclient.exceptions import * + +# NOTE(akurilin): This alias should be left here to support backwards +# compatibility until we are sure that usage of these exceptions in +# projects is correct. +ConnectionError = ConnectionRefused +HTTPNotImplemented = HttpNotImplemented +Timeout = RequestTimeout class CertificateConfigError(Exception): @@ -29,18 +36,15 @@ class CertificateConfigError(Exception): super(CertificateConfigError, self).__init__(msg) -class ConnectionError(ClientException): - """Something went wrong trying to connect to a server""" +class EmptyCatalog(EndpointNotFound): + """The service catalog is empty.""" + pass -class SSLError(ConnectionError): +class SSLError(ConnectionRefused): """An SSL error occurred.""" -class Timeout(ClientException): - """The request timed out.""" - - class DiscoveryFailure(ClientException): """Discovery of client versions failed.""" diff --git a/keystoneclient/session.py b/keystoneclient/session.py index 6aa7df847..5e77805ec 100644 --- a/keystoneclient/session.py +++ b/keystoneclient/session.py @@ -265,10 +265,10 @@ class Session(object): raise exceptions.SSLError(msg) except requests.exceptions.Timeout: msg = 'Request to %s timed out' % url - raise exceptions.Timeout(msg) + raise exceptions.RequestTimeout(msg) except requests.exceptions.ConnectionError: msg = 'Unable to establish connection to %s' % url - raise exceptions.ConnectionError(msg) + raise exceptions.ConnectionRefused(msg) _logger.debug('RESP: [%s] %s\nRESP BODY: %s\n', resp.status_code, resp.headers, resp.text) diff --git a/keystoneclient/v3/contrib/trusts.py b/keystoneclient/v3/contrib/trusts.py index 4b9b49684..1dde538f7 100644 --- a/keystoneclient/v3/contrib/trusts.py +++ b/keystoneclient/v3/contrib/trusts.py @@ -68,7 +68,7 @@ class TrustManager(base.CrudManager): **kwargs) def update(self): - raise exceptions.HTTPNotImplemented("Update not supported for trusts") + raise exceptions.HttpNotImplemented("Update not supported for trusts") def list(self, trustee_user=None, trustor_user=None, **kwargs): """List Trusts."""