Removed usage of the py3kcompat module

Like mentioned in I8e0b49cdfbddcf2d44a601ad06be2e75897905fc the
py3kcompat module is deprecated and should not be used.

Updated module apiclient from oslo-incubator to use six instead of
py3kcompat.

Added six >= 1.6.0 as new requirement.

Change-Id: I2253e5a2701ad046f76a8539405baac2eac739f6
This commit is contained in:
Christian Berendt
2014-06-10 13:30:39 +02:00
parent a637d905ff
commit a13fc6932d
9 changed files with 85 additions and 113 deletions

View File

@@ -6,3 +6,4 @@ requests>=1.1
python-keystoneclient>=0.8.0 python-keystoneclient>=0.8.0
PyYAML>=3.1.0 PyYAML>=3.1.0
stevedore>=0.14 stevedore>=0.14
six>=1.6.0

View File

@@ -12,9 +12,10 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from six.moves.urllib import parse as urlparse
from solumclient.openstack.common.apiclient import base from solumclient.openstack.common.apiclient import base
from solumclient.openstack.common.apiclient import exceptions from solumclient.openstack.common.apiclient import exceptions
from solumclient.openstack.common.py3kcompat import urlutils
class ManagerMixin(): class ManagerMixin():
@@ -148,7 +149,7 @@ class CrudManager(ManagerMixin, base.CrudManager):
return self._list( return self._list(
'%(base_url)s%(query)s' % { '%(base_url)s%(query)s' % {
'base_url': self.build_url(base_url=base_url, **kwargs), 'base_url': self.build_url(base_url=base_url, **kwargs),
'query': '?%s' % urlutils.urlencode(kwargs) if kwargs else '', 'query': '?%s' % urlparse.urlencode(kwargs) if kwargs else '',
}) })
def get(self, **kwargs): def get(self, **kwargs):

View File

@@ -1,2 +1,17 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import six import six
six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox')) six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox'))

View File

@@ -213,8 +213,8 @@ class BaseAuthPlugin(object):
:type service_type: string :type service_type: string
:param endpoint_type: Type of endpoint. :param endpoint_type: Type of endpoint.
Possible values: public or publicURL, Possible values: public or publicURL,
internal or internalURL, internal or internalURL,
admin or adminURL admin or adminURL
:type endpoint_type: string :type endpoint_type: string
:returns: tuple of token and endpoint strings :returns: tuple of token and endpoint strings
:raises: EndpointException :raises: EndpointException

View File

@@ -30,6 +30,7 @@ import six
from six.moves.urllib import parse from six.moves.urllib import parse
from solumclient.openstack.common.apiclient import exceptions from solumclient.openstack.common.apiclient import exceptions
from solumclient.openstack.common.gettextutils import _
from solumclient.openstack.common import strutils from solumclient.openstack.common import strutils
@@ -74,8 +75,8 @@ class HookableMixin(object):
:param cls: class that registers hooks :param cls: class that registers hooks
:param hook_type: hook type, e.g., '__pre_parse_args__' :param hook_type: hook type, e.g., '__pre_parse_args__'
:param **args: args to be passed to every hook function :param args: args to be passed to every hook function
:param **kwargs: kwargs to be passed to every hook function :param kwargs: kwargs to be passed to every hook function
""" """
hook_funcs = cls._hooks_map.get(hook_type) or [] hook_funcs = cls._hooks_map.get(hook_type) or []
for hook_func in hook_funcs: for hook_func in hook_funcs:
@@ -219,7 +220,10 @@ class ManagerWithFind(BaseManager):
matches = self.findall(**kwargs) matches = self.findall(**kwargs)
num_matches = len(matches) num_matches = len(matches)
if num_matches == 0: if num_matches == 0:
msg = "No %s matching %s." % (self.resource_class.__name__, kwargs) msg = _("No %(name)s matching %(args)s.") % {
'name': self.resource_class.__name__,
'args': kwargs
}
raise exceptions.NotFound(msg) raise exceptions.NotFound(msg)
elif num_matches > 1: elif num_matches > 1:
raise exceptions.NoUniqueMatch() raise exceptions.NoUniqueMatch()
@@ -373,7 +377,10 @@ class CrudManager(BaseManager):
num = len(rl) num = len(rl)
if num == 0: if num == 0:
msg = "No %s matching %s." % (self.resource_class.__name__, kwargs) msg = _("No %(name)s matching %(args)s.") % {
'name': self.resource_class.__name__,
'args': kwargs
}
raise exceptions.NotFound(404, msg) raise exceptions.NotFound(404, msg)
elif num > 1: elif num > 1:
raise exceptions.NoUniqueMatch raise exceptions.NoUniqueMatch

View File

@@ -36,6 +36,7 @@ except ImportError:
import requests import requests
from solumclient.openstack.common.apiclient import exceptions from solumclient.openstack.common.apiclient import exceptions
from solumclient.openstack.common.gettextutils import _
from solumclient.openstack.common import importutils from solumclient.openstack.common import importutils
@@ -46,6 +47,7 @@ class HTTPClient(object):
"""This client handles sending HTTP requests to OpenStack servers. """This client handles sending HTTP requests to OpenStack servers.
Features: Features:
- share authentication information between several clients to different - share authentication information between several clients to different
services (e.g., for compute and image clients); services (e.g., for compute and image clients);
- reissue authentication request for expired tokens; - reissue authentication request for expired tokens;
@@ -151,7 +153,7 @@ class HTTPClient(object):
:param method: method of HTTP request :param method: method of HTTP request
:param url: URL of HTTP request :param url: URL of HTTP request
:param kwargs: any other parameter that can be passed to :param kwargs: any other parameter that can be passed to
' requests.Session.request (such as `headers`) or `json` requests.Session.request (such as `headers`) or `json`
that will be encoded as JSON and used as `data` argument that will be encoded as JSON and used as `data` argument
""" """
kwargs.setdefault("headers", kwargs.get("headers", {})) kwargs.setdefault("headers", kwargs.get("headers", {}))
@@ -206,7 +208,7 @@ class HTTPClient(object):
:param method: method of HTTP request :param method: method of HTTP request
:param url: URL of HTTP request :param url: URL of HTTP request
:param kwargs: any other parameter that can be passed to :param kwargs: any other parameter that can be passed to
' `HTTPClient.request` `HTTPClient.request`
""" """
filter_args = { filter_args = {
@@ -228,7 +230,7 @@ class HTTPClient(object):
**filter_args) **filter_args)
if not (token and endpoint): if not (token and endpoint):
raise exceptions.AuthorizationFailure( raise exceptions.AuthorizationFailure(
"Cannot find endpoint or token for request") _("Cannot find endpoint or token for request"))
old_token_endpoint = (token, endpoint) old_token_endpoint = (token, endpoint)
kwargs.setdefault("headers", {})["X-Auth-Token"] = token kwargs.setdefault("headers", {})["X-Auth-Token"] = token
@@ -351,8 +353,12 @@ class BaseClient(object):
try: try:
client_path = version_map[str(version)] client_path = version_map[str(version)]
except (KeyError, ValueError): except (KeyError, ValueError):
msg = "Invalid %s client version '%s'. must be one of: %s" % ( msg = _("Invalid %(api_name)s client version '%(version)s'. "
(api_name, version, ', '.join(version_map.keys()))) "Must be one of: %(version_map)s") % {
'api_name': api_name,
'version': version,
'version_map': ', '.join(version_map.keys())
}
raise exceptions.UnsupportedVersion(msg) raise exceptions.UnsupportedVersion(msg)
return importutils.import_class(client_path) return importutils.import_class(client_path)

View File

@@ -25,6 +25,8 @@ import sys
import six import six
from solumclient.openstack.common.gettextutils import _
class ClientException(Exception): class ClientException(Exception):
"""The base exception class for all exceptions this library raises. """The base exception class for all exceptions this library raises.
@@ -36,7 +38,7 @@ class MissingArgs(ClientException):
"""Supplied arguments are not sufficient for calling a function.""" """Supplied arguments are not sufficient for calling a function."""
def __init__(self, missing): def __init__(self, missing):
self.missing = missing self.missing = missing
msg = "Missing argument(s): %s" % ", ".join(missing) msg = _("Missing arguments: %s") % ", ".join(missing)
super(MissingArgs, self).__init__(msg) super(MissingArgs, self).__init__(msg)
@@ -69,7 +71,7 @@ class AuthPluginOptionsMissing(AuthorizationFailure):
"""Auth plugin misses some options.""" """Auth plugin misses some options."""
def __init__(self, opt_names): def __init__(self, opt_names):
super(AuthPluginOptionsMissing, self).__init__( super(AuthPluginOptionsMissing, self).__init__(
"Authentication failed. Missing options: %s" % _("Authentication failed. Missing options: %s") %
", ".join(opt_names)) ", ".join(opt_names))
self.opt_names = opt_names self.opt_names = opt_names
@@ -78,7 +80,7 @@ class AuthSystemNotFound(AuthorizationFailure):
"""User has specified a AuthSystem that is not installed.""" """User has specified a AuthSystem that is not installed."""
def __init__(self, auth_system): def __init__(self, auth_system):
super(AuthSystemNotFound, self).__init__( super(AuthSystemNotFound, self).__init__(
"AuthSystemNotFound: %s" % repr(auth_system)) _("AuthSystemNotFound: %s") % repr(auth_system))
self.auth_system = auth_system self.auth_system = auth_system
@@ -101,7 +103,7 @@ class AmbiguousEndpoints(EndpointException):
"""Found more than one matching endpoint in Service Catalog.""" """Found more than one matching endpoint in Service Catalog."""
def __init__(self, endpoints=None): def __init__(self, endpoints=None):
super(AmbiguousEndpoints, self).__init__( super(AmbiguousEndpoints, self).__init__(
"AmbiguousEndpoints: %s" % repr(endpoints)) _("AmbiguousEndpoints: %s") % repr(endpoints))
self.endpoints = endpoints self.endpoints = endpoints
@@ -109,7 +111,7 @@ class HttpError(ClientException):
"""The base exception class for all HTTP exceptions. """The base exception class for all HTTP exceptions.
""" """
http_status = 0 http_status = 0
message = "HTTP Error" message = _("HTTP Error")
def __init__(self, message=None, details=None, def __init__(self, message=None, details=None,
response=None, request_id=None, response=None, request_id=None,
@@ -129,7 +131,7 @@ class HttpError(ClientException):
class HTTPRedirection(HttpError): class HTTPRedirection(HttpError):
"""HTTP Redirection.""" """HTTP Redirection."""
message = "HTTP Redirection" message = _("HTTP Redirection")
class HTTPClientError(HttpError): class HTTPClientError(HttpError):
@@ -137,7 +139,7 @@ class HTTPClientError(HttpError):
Exception for cases in which the client seems to have erred. Exception for cases in which the client seems to have erred.
""" """
message = "HTTP Client Error" message = _("HTTP Client Error")
class HttpServerError(HttpError): class HttpServerError(HttpError):
@@ -146,7 +148,7 @@ class HttpServerError(HttpError):
Exception for cases in which the server is aware that it has Exception for cases in which the server is aware that it has
erred or is incapable of performing the request. erred or is incapable of performing the request.
""" """
message = "HTTP Server Error" message = _("HTTP Server Error")
class MultipleChoices(HTTPRedirection): class MultipleChoices(HTTPRedirection):
@@ -156,7 +158,7 @@ class MultipleChoices(HTTPRedirection):
""" """
http_status = 300 http_status = 300
message = "Multiple Choices" message = _("Multiple Choices")
class BadRequest(HTTPClientError): class BadRequest(HTTPClientError):
@@ -165,7 +167,7 @@ class BadRequest(HTTPClientError):
The request cannot be fulfilled due to bad syntax. The request cannot be fulfilled due to bad syntax.
""" """
http_status = 400 http_status = 400
message = "Bad Request" message = _("Bad Request")
class Unauthorized(HTTPClientError): class Unauthorized(HTTPClientError):
@@ -175,7 +177,7 @@ class Unauthorized(HTTPClientError):
is required and has failed or has not yet been provided. is required and has failed or has not yet been provided.
""" """
http_status = 401 http_status = 401
message = "Unauthorized" message = _("Unauthorized")
class PaymentRequired(HTTPClientError): class PaymentRequired(HTTPClientError):
@@ -184,7 +186,7 @@ class PaymentRequired(HTTPClientError):
Reserved for future use. Reserved for future use.
""" """
http_status = 402 http_status = 402
message = "Payment Required" message = _("Payment Required")
class Forbidden(HTTPClientError): class Forbidden(HTTPClientError):
@@ -194,7 +196,7 @@ class Forbidden(HTTPClientError):
to it. to it.
""" """
http_status = 403 http_status = 403
message = "Forbidden" message = _("Forbidden")
class NotFound(HTTPClientError): class NotFound(HTTPClientError):
@@ -204,7 +206,7 @@ class NotFound(HTTPClientError):
in the future. in the future.
""" """
http_status = 404 http_status = 404
message = "Not Found" message = _("Not Found")
class MethodNotAllowed(HTTPClientError): class MethodNotAllowed(HTTPClientError):
@@ -214,7 +216,7 @@ class MethodNotAllowed(HTTPClientError):
by that resource. by that resource.
""" """
http_status = 405 http_status = 405
message = "Method Not Allowed" message = _("Method Not Allowed")
class NotAcceptable(HTTPClientError): class NotAcceptable(HTTPClientError):
@@ -224,7 +226,7 @@ class NotAcceptable(HTTPClientError):
acceptable according to the Accept headers sent in the request. acceptable according to the Accept headers sent in the request.
""" """
http_status = 406 http_status = 406
message = "Not Acceptable" message = _("Not Acceptable")
class ProxyAuthenticationRequired(HTTPClientError): class ProxyAuthenticationRequired(HTTPClientError):
@@ -233,7 +235,7 @@ class ProxyAuthenticationRequired(HTTPClientError):
The client must first authenticate itself with the proxy. The client must first authenticate itself with the proxy.
""" """
http_status = 407 http_status = 407
message = "Proxy Authentication Required" message = _("Proxy Authentication Required")
class RequestTimeout(HTTPClientError): class RequestTimeout(HTTPClientError):
@@ -242,7 +244,7 @@ class RequestTimeout(HTTPClientError):
The server timed out waiting for the request. The server timed out waiting for the request.
""" """
http_status = 408 http_status = 408
message = "Request Timeout" message = _("Request Timeout")
class Conflict(HTTPClientError): class Conflict(HTTPClientError):
@@ -252,7 +254,7 @@ class Conflict(HTTPClientError):
in the request, such as an edit conflict. in the request, such as an edit conflict.
""" """
http_status = 409 http_status = 409
message = "Conflict" message = _("Conflict")
class Gone(HTTPClientError): class Gone(HTTPClientError):
@@ -262,7 +264,7 @@ class Gone(HTTPClientError):
not be available again. not be available again.
""" """
http_status = 410 http_status = 410
message = "Gone" message = _("Gone")
class LengthRequired(HTTPClientError): class LengthRequired(HTTPClientError):
@@ -272,7 +274,7 @@ class LengthRequired(HTTPClientError):
required by the requested resource. required by the requested resource.
""" """
http_status = 411 http_status = 411
message = "Length Required" message = _("Length Required")
class PreconditionFailed(HTTPClientError): class PreconditionFailed(HTTPClientError):
@@ -282,7 +284,7 @@ class PreconditionFailed(HTTPClientError):
put on the request. put on the request.
""" """
http_status = 412 http_status = 412
message = "Precondition Failed" message = _("Precondition Failed")
class RequestEntityTooLarge(HTTPClientError): class RequestEntityTooLarge(HTTPClientError):
@@ -291,7 +293,7 @@ class RequestEntityTooLarge(HTTPClientError):
The request is larger than the server is willing or able to process. The request is larger than the server is willing or able to process.
""" """
http_status = 413 http_status = 413
message = "Request Entity Too Large" message = _("Request Entity Too Large")
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
try: try:
@@ -308,7 +310,7 @@ class RequestUriTooLong(HTTPClientError):
The URI provided was too long for the server to process. The URI provided was too long for the server to process.
""" """
http_status = 414 http_status = 414
message = "Request-URI Too Long" message = _("Request-URI Too Long")
class UnsupportedMediaType(HTTPClientError): class UnsupportedMediaType(HTTPClientError):
@@ -318,7 +320,7 @@ class UnsupportedMediaType(HTTPClientError):
not support. not support.
""" """
http_status = 415 http_status = 415
message = "Unsupported Media Type" message = _("Unsupported Media Type")
class RequestedRangeNotSatisfiable(HTTPClientError): class RequestedRangeNotSatisfiable(HTTPClientError):
@@ -328,7 +330,7 @@ class RequestedRangeNotSatisfiable(HTTPClientError):
supply that portion. supply that portion.
""" """
http_status = 416 http_status = 416
message = "Requested Range Not Satisfiable" message = _("Requested Range Not Satisfiable")
class ExpectationFailed(HTTPClientError): class ExpectationFailed(HTTPClientError):
@@ -337,7 +339,7 @@ class ExpectationFailed(HTTPClientError):
The server cannot meet the requirements of the Expect request-header field. The server cannot meet the requirements of the Expect request-header field.
""" """
http_status = 417 http_status = 417
message = "Expectation Failed" message = _("Expectation Failed")
class UnprocessableEntity(HTTPClientError): class UnprocessableEntity(HTTPClientError):
@@ -347,7 +349,7 @@ class UnprocessableEntity(HTTPClientError):
errors. errors.
""" """
http_status = 422 http_status = 422
message = "Unprocessable Entity" message = _("Unprocessable Entity")
class InternalServerError(HttpServerError): class InternalServerError(HttpServerError):
@@ -356,7 +358,7 @@ class InternalServerError(HttpServerError):
A generic error message, given when no more specific message is suitable. A generic error message, given when no more specific message is suitable.
""" """
http_status = 500 http_status = 500
message = "Internal Server Error" message = _("Internal Server Error")
# NotImplemented is a python keyword. # NotImplemented is a python keyword.
@@ -367,7 +369,7 @@ class HttpNotImplemented(HttpServerError):
the ability to fulfill the request. the ability to fulfill the request.
""" """
http_status = 501 http_status = 501
message = "Not Implemented" message = _("Not Implemented")
class BadGateway(HttpServerError): class BadGateway(HttpServerError):
@@ -377,7 +379,7 @@ class BadGateway(HttpServerError):
response from the upstream server. response from the upstream server.
""" """
http_status = 502 http_status = 502
message = "Bad Gateway" message = _("Bad Gateway")
class ServiceUnavailable(HttpServerError): class ServiceUnavailable(HttpServerError):
@@ -386,7 +388,7 @@ class ServiceUnavailable(HttpServerError):
The server is currently unavailable. The server is currently unavailable.
""" """
http_status = 503 http_status = 503
message = "Service Unavailable" message = _("Service Unavailable")
class GatewayTimeout(HttpServerError): class GatewayTimeout(HttpServerError):
@@ -396,7 +398,7 @@ class GatewayTimeout(HttpServerError):
response from the upstream server. response from the upstream server.
""" """
http_status = 504 http_status = 504
message = "Gateway Timeout" message = _("Gateway Timeout")
class HttpVersionNotSupported(HttpServerError): class HttpVersionNotSupported(HttpServerError):
@@ -405,7 +407,7 @@ class HttpVersionNotSupported(HttpServerError):
The server does not support the HTTP protocol version used in the request. The server does not support the HTTP protocol version used in the request.
""" """
http_status = 505 http_status = 505
message = "HTTP Version Not Supported" message = _("HTTP Version Not Supported")
# _code_map contains all the classes that have http_status attribute. # _code_map contains all the classes that have http_status attribute.
@@ -423,12 +425,17 @@ def from_response(response, method, url):
:param method: HTTP method used for request :param method: HTTP method used for request
:param url: URL used for request :param url: URL used for request
""" """
req_id = response.headers.get("x-openstack-request-id")
#NOTE(hdd) true for older versions of nova and cinder
if not req_id:
req_id = response.headers.get("x-compute-request-id")
kwargs = { kwargs = {
"http_status": response.status_code, "http_status": response.status_code,
"response": response, "response": response,
"method": method, "method": method,
"url": url, "url": url,
"request_id": response.headers.get("x-compute-request-id"), "request_id": req_id,
} }
if "retry-after" in response.headers: if "retry-after" in response.headers:
kwargs["retry_after"] = response.headers["retry-after"] kwargs["retry_after"] = response.headers["retry-after"]

View File

@@ -1,65 +0,0 @@
#
# Copyright 2013 Canonical Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""
Python2/Python3 compatibility layer for OpenStack
"""
import six
if six.PY3:
# python3
import urllib.error
import urllib.parse
import urllib.request
urlencode = urllib.parse.urlencode
urljoin = urllib.parse.urljoin
quote = urllib.parse.quote
parse_qsl = urllib.parse.parse_qsl
unquote = urllib.parse.unquote
unquote_plus = urllib.parse.unquote_plus
urlparse = urllib.parse.urlparse
urlsplit = urllib.parse.urlsplit
urlunsplit = urllib.parse.urlunsplit
SplitResult = urllib.parse.SplitResult
urlopen = urllib.request.urlopen
URLError = urllib.error.URLError
pathname2url = urllib.request.pathname2url
else:
# python2
import urllib
import urllib2
import urlparse
urlencode = urllib.urlencode
quote = urllib.quote
unquote = urllib.unquote
unquote_plus = urllib.unquote_plus
parse = urlparse
parse_qsl = parse.parse_qsl
urljoin = parse.urljoin
urlparse = parse.urlparse
urlsplit = parse.urlsplit
urlunsplit = parse.urlunsplit
SplitResult = parse.SplitResult
urlopen = urllib2.urlopen
URLError = urllib2.URLError
pathname2url = urllib.pathname2url