Enable support for python 3.x
suds package is not 3.x compatible, so using suds-jurko only under 3.x. Using six support to get the rest of the code compiling and testing fine under 3.x Depends-On: If91a87ede96a82a2a0d181ee0d4fdc102dc0299d Change-Id: I78ee208756304b3038ce4fe66b120f6bbbc28738
This commit is contained in:
parent
4dc0ded767
commit
1ebbc4d2ac
@ -331,7 +331,7 @@ class VMwareAPISession(object):
|
||||
LOG.debug("Fault list: %s", excep.fault_list)
|
||||
fault = excep.fault_list[0]
|
||||
clazz = exceptions.get_fault_class(fault)
|
||||
raise clazz(unicode(excep), excep.details)
|
||||
raise clazz(six.text_type(excep), excep.details)
|
||||
raise
|
||||
|
||||
except exceptions.VimConnectionException:
|
||||
|
@ -42,6 +42,12 @@ DUPLICATE_NAME = 'DuplicateName'
|
||||
class VimException(Exception):
|
||||
"""The base exception class for all exceptions this library raises."""
|
||||
|
||||
if six.PY2:
|
||||
__str__ = lambda self: six.text_type(self).encode('utf8')
|
||||
__unicode__ = lambda self: self.description
|
||||
else:
|
||||
__str__ = lambda self: self.description
|
||||
|
||||
def __init__(self, message, cause=None):
|
||||
Exception.__init__(self)
|
||||
if isinstance(message, list):
|
||||
@ -52,16 +58,14 @@ class VimException(Exception):
|
||||
self.msg = message
|
||||
self.cause = cause
|
||||
|
||||
def __str__(self):
|
||||
return unicode(self).encode('utf8')
|
||||
|
||||
def __unicode__(self):
|
||||
@property
|
||||
def description(self):
|
||||
# NOTE(jecarey): self.msg and self.cause may be i18n objects
|
||||
# that do not support str or concatenation, but can be used
|
||||
# as replacement text.
|
||||
descr = unicode(self.msg)
|
||||
descr = six.text_type(self.msg)
|
||||
if self.cause:
|
||||
descr += '\nCause: ' + unicode(self.cause)
|
||||
descr += '\nCause: ' + six.text_type(self.cause)
|
||||
return descr
|
||||
|
||||
|
||||
@ -92,15 +96,21 @@ class VimFaultException(VimException):
|
||||
self.fault_list = fault_list
|
||||
self.details = details
|
||||
|
||||
def __unicode__(self):
|
||||
descr = VimException.__unicode__(self)
|
||||
if six.PY2:
|
||||
__unicode__ = lambda self: self.description
|
||||
else:
|
||||
__str__ = lambda self: self.description
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
descr = VimException.description.fget(self)
|
||||
if self.fault_list:
|
||||
# fault_list doesn't contain non-ASCII chars, we can use str()
|
||||
descr += '\nFaults: ' + str(self.fault_list)
|
||||
if self.details:
|
||||
# details may contain non-ASCII values
|
||||
details = '{%s}' % ', '.join(["'%s': '%s'" % (k, v)
|
||||
for k, v in self.details.iteritems()])
|
||||
details = '{%s}' % ', '.join(["'%s': '%s'" % (k, v) for k, v in
|
||||
six.iteritems(self.details)])
|
||||
descr += '\nDetails: ' + details
|
||||
return descr
|
||||
|
||||
|
@ -12,11 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import httplib
|
||||
import logging
|
||||
import posixpath
|
||||
import random
|
||||
|
||||
import six.moves.http_client as httplib
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from oslo.vmware._i18n import _
|
||||
|
@ -22,9 +22,9 @@ Refer http://goo.gl/GR2o6U for more details.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import urllib
|
||||
import urlparse
|
||||
|
||||
import six.moves.urllib.parse as urlparse
|
||||
import six.moves.urllib.request as urllib
|
||||
import suds.sax.element as element
|
||||
|
||||
from oslo.vmware._i18n import _LW
|
||||
|
@ -21,14 +21,13 @@ VMDK files in VMware servers. It also contains a class to read images from
|
||||
glance server.
|
||||
"""
|
||||
|
||||
import httplib
|
||||
import logging
|
||||
import socket
|
||||
import urllib
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
import netaddr
|
||||
import six.moves.http_client as httplib
|
||||
import six.moves.urllib.parse as urlparse
|
||||
import six.moves.urllib.request as urllib2
|
||||
|
||||
from oslo.utils import excutils
|
||||
from oslo.vmware._i18n import _, _LE, _LW
|
||||
@ -176,7 +175,7 @@ class FileWriteHandle(FileHandle):
|
||||
soap_url = self._get_soap_url(scheme, host, port)
|
||||
param_list = {'dcPath': data_center_name, 'dsName': datastore_name}
|
||||
self._url = '%s/folder/%s' % (soap_url, file_path)
|
||||
self._url = self._url + '?' + urllib.urlencode(param_list)
|
||||
self._url = self._url + '?' + urlparse.urlencode(param_list)
|
||||
|
||||
self.conn = self._create_connection(self._url,
|
||||
file_size,
|
||||
|
@ -17,14 +17,17 @@
|
||||
Common classes that provide access to vSphere services.
|
||||
"""
|
||||
|
||||
import httplib
|
||||
import logging
|
||||
import os
|
||||
|
||||
import netaddr
|
||||
import requests
|
||||
import six
|
||||
import six.moves.http_client as httplib
|
||||
import suds
|
||||
from suds import cache
|
||||
from suds import client
|
||||
from suds import plugin
|
||||
from suds import transport
|
||||
|
||||
from oslo.utils import timeutils
|
||||
@ -42,7 +45,7 @@ SERVICE_INSTANCE = 'ServiceInstance'
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ServiceMessagePlugin(suds.plugin.MessagePlugin):
|
||||
class ServiceMessagePlugin(plugin.MessagePlugin):
|
||||
"""Suds plug-in handling some special cases while calling VI SDK."""
|
||||
|
||||
def add_attribute_for_value(self, node):
|
||||
@ -149,7 +152,7 @@ class RequestsTransport(transport.Transport):
|
||||
return transport.Reply(resp.status_code, resp.headers, resp.content)
|
||||
|
||||
|
||||
class MemoryCache(suds.cache.ObjectCache):
|
||||
class MemoryCache(cache.ObjectCache):
|
||||
def __init__(self):
|
||||
self._cache = {}
|
||||
|
||||
@ -187,11 +190,11 @@ class Service(object):
|
||||
LOG.debug("Creating suds client with soap_url='%s' and wsdl_url='%s'",
|
||||
self.soap_url, self.wsdl_url)
|
||||
transport = RequestsTransport(cacert, insecure)
|
||||
self.client = suds.client.Client(self.wsdl_url,
|
||||
transport=transport,
|
||||
location=self.soap_url,
|
||||
plugins=[ServiceMessagePlugin()],
|
||||
cache=_CACHE)
|
||||
self.client = client.Client(self.wsdl_url,
|
||||
transport=transport,
|
||||
location=self.soap_url,
|
||||
plugins=[ServiceMessagePlugin()],
|
||||
cache=_CACHE)
|
||||
self._service_content = None
|
||||
|
||||
@staticmethod
|
||||
|
@ -17,7 +17,7 @@
|
||||
The VMware API utility module.
|
||||
"""
|
||||
|
||||
import suds
|
||||
from suds import sudsobject
|
||||
|
||||
from oslo.utils import timeutils
|
||||
|
||||
@ -29,7 +29,7 @@ def get_moref(value, type_):
|
||||
:param type_: type of the managed object
|
||||
:returns: managed object reference with given value and type
|
||||
"""
|
||||
moref = suds.sudsobject.Property(value)
|
||||
moref = sudsobject.Property(value)
|
||||
moref._type = type_
|
||||
return moref
|
||||
|
||||
|
23
requirements-py3.txt
Normal file
23
requirements-py3.txt
Normal file
@ -0,0 +1,23 @@
|
||||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
stevedore>=1.1.0 # Apache-2.0
|
||||
netaddr>=0.7.12
|
||||
|
||||
# for timeutils
|
||||
iso8601>=0.1.9
|
||||
|
||||
# for jsonutils
|
||||
six>=1.7.0
|
||||
|
||||
oslo.i18n>=1.0.0 # Apache-2.0
|
||||
oslo.utils>=1.0.0 # Apache-2.0
|
||||
Babel>=1.3
|
||||
|
||||
# for the routing notifier
|
||||
PyYAML>=3.1.0
|
||||
|
||||
suds-jurko>=0.6
|
||||
eventlet>=0.15.2
|
||||
requests>=2.2.0,!=2.4.0
|
@ -354,7 +354,7 @@ class DatastoreURLTestCase(base.TestCase):
|
||||
ds_url = datastore.DatastoreURL.urlparse(url)
|
||||
self.assertEqual(path, ds_url.path)
|
||||
|
||||
@mock.patch('httplib.HTTPSConnection')
|
||||
@mock.patch('six.moves.http_client.HTTPSConnection')
|
||||
def test_connect(self, mock_conn):
|
||||
dc_path = 'datacenter-1'
|
||||
ds_name = 'datastore-1'
|
||||
|
@ -20,6 +20,7 @@ Unit tests for session management and API invocation classes.
|
||||
|
||||
from eventlet import greenthread
|
||||
import mock
|
||||
import six
|
||||
import suds
|
||||
|
||||
from oslo.vmware import api
|
||||
@ -282,7 +283,7 @@ class VMwareAPISessionTest(base.TestCase):
|
||||
expected_str = "%s\nFaults: %s\nDetails: %s" % (fault_string,
|
||||
fault_list,
|
||||
details_str)
|
||||
self.assertEqual(expected_str, unicode(e))
|
||||
self.assertEqual(expected_str, six.text_type(e))
|
||||
self.assertEqual(details, e.details)
|
||||
|
||||
def test_invoke_api_with_empty_response(self):
|
||||
@ -482,7 +483,7 @@ class VMwareAPISessionTest(base.TestCase):
|
||||
'fake-task')
|
||||
|
||||
def test_poll_task_well_known_exceptions(self):
|
||||
for k, v in exceptions._fault_classes_registry.iteritems():
|
||||
for k, v in six.iteritems(exceptions._fault_classes_registry):
|
||||
self._poll_task_well_known_exceptions(k, v)
|
||||
|
||||
def test_poll_task_unknown_exception(self):
|
||||
@ -491,7 +492,7 @@ class VMwareAPISessionTest(base.TestCase):
|
||||
'RuntimeFault': exceptions.VMwareDriverException
|
||||
}
|
||||
|
||||
for k, v in _unknown_exceptions.iteritems():
|
||||
for k, v in six.iteritems(_unknown_exceptions):
|
||||
self._poll_task_well_known_exceptions(k, v)
|
||||
|
||||
def _create_subclass_exception(self):
|
||||
|
@ -18,10 +18,10 @@ Unit tests for PBM utility methods.
|
||||
"""
|
||||
|
||||
import os
|
||||
import urllib
|
||||
import urlparse
|
||||
|
||||
import mock
|
||||
import six.moves.urllib.parse as urlparse
|
||||
import six.moves.urllib.request as urllib
|
||||
|
||||
from oslo.vmware import pbm
|
||||
from tests import base
|
||||
@ -91,7 +91,7 @@ class PBMUtilityTest(base.TestCase):
|
||||
|
||||
session = mock.Mock()
|
||||
profile_id = pbm.get_profile_id_by_name(session,
|
||||
'profile-%s' % (i + 1))
|
||||
('profile-%s' % 11))
|
||||
self.assertFalse(profile_id)
|
||||
get_all_profiles.assert_called_once_with(session)
|
||||
|
||||
@ -139,7 +139,7 @@ class PBMUtilityTest(base.TestCase):
|
||||
datastores.append(self._create_datastore(value))
|
||||
|
||||
hubs = []
|
||||
hub_ids = ds_values[0:len(ds_values) / 2]
|
||||
hub_ids = ds_values[0:int(len(ds_values) / 2)]
|
||||
for hub_id in hub_ids:
|
||||
hub = mock.Mock()
|
||||
hub.hubId = hub_id
|
||||
|
@ -18,6 +18,7 @@ Unit tests for read and write handles for image transfer.
|
||||
"""
|
||||
|
||||
import mock
|
||||
import six
|
||||
|
||||
from oslo.vmware import exceptions
|
||||
from oslo.vmware import rw_handles
|
||||
@ -62,7 +63,7 @@ class FileWriteHandleTest(base.TestCase):
|
||||
vim_cookie.value = 'value'
|
||||
|
||||
self._conn = mock.Mock()
|
||||
patcher = mock.patch('httplib.HTTPConnection')
|
||||
patcher = mock.patch('six.moves.http_client.HTTPConnection')
|
||||
self.addCleanup(patcher.stop)
|
||||
HTTPConnectionMock = patcher.start()
|
||||
HTTPConnectionMock.return_value = self._conn
|
||||
@ -87,7 +88,7 @@ class VmdkWriteHandleTest(base.TestCase):
|
||||
def setUp(self):
|
||||
super(VmdkWriteHandleTest, self).setUp()
|
||||
self._conn = mock.Mock()
|
||||
patcher = mock.patch('httplib.HTTPConnection')
|
||||
patcher = mock.patch('six.moves.http_client.HTTPConnection')
|
||||
self.addCleanup(patcher.stop)
|
||||
HTTPConnectionMock = patcher.start()
|
||||
HTTPConnectionMock.return_value = self._conn
|
||||
@ -180,12 +181,14 @@ class VmdkReadHandleTest(base.TestCase):
|
||||
def setUp(self):
|
||||
super(VmdkReadHandleTest, self).setUp()
|
||||
|
||||
req_patcher = mock.patch('urllib2.Request')
|
||||
req_patcher = mock.patch(
|
||||
'six.moves.urllib.request.Request')
|
||||
self.addCleanup(req_patcher.stop)
|
||||
RequestMock = req_patcher.start()
|
||||
RequestMock.return_value = mock.Mock()
|
||||
|
||||
urlopen_patcher = mock.patch('urllib2.urlopen')
|
||||
urlopen_patcher = mock.patch(
|
||||
'six.moves.urllib.request.urlopen')
|
||||
self.addCleanup(urlopen_patcher.stop)
|
||||
urlopen_mock = urlopen_patcher.start()
|
||||
self._conn = mock.Mock()
|
||||
@ -281,7 +284,7 @@ class ImageReadHandleTest(base.TestCase):
|
||||
max_items = 10
|
||||
item = [1] * 10
|
||||
|
||||
class ImageReadIterator:
|
||||
class ImageReadIterator(six.Iterator):
|
||||
|
||||
def __init__(self):
|
||||
self.num_items = 0
|
||||
@ -289,12 +292,14 @@ class ImageReadHandleTest(base.TestCase):
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
def __next__(self):
|
||||
if (self.num_items < max_items):
|
||||
self.num_items += 1
|
||||
return item
|
||||
raise StopIteration
|
||||
|
||||
next = __next__
|
||||
|
||||
handle = rw_handles.ImageReadHandle(ImageReadIterator())
|
||||
for _ in range(0, max_items):
|
||||
self.assertEqual(item, handle.read(10))
|
||||
|
@ -13,10 +13,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import httplib
|
||||
|
||||
import mock
|
||||
import requests
|
||||
import six
|
||||
import six.moves.http_client as httplib
|
||||
import suds
|
||||
|
||||
from oslo.vmware import exceptions
|
||||
@ -408,24 +408,39 @@ class RequestsTransportTest(base.TestCase):
|
||||
self.assertEqual(mock.sentinel.headers, reply.headers)
|
||||
self.assertEqual(mock.sentinel.content, reply.message)
|
||||
|
||||
@mock.patch('__builtin__.open')
|
||||
@mock.patch('os.path.getsize')
|
||||
def test_send_with_local_file_url(self, get_size_mock, open_mock):
|
||||
def test_send_with_local_file_url(self, get_size_mock):
|
||||
transport = service.RequestsTransport()
|
||||
|
||||
url = 'file:///foo'
|
||||
request = requests.PreparedRequest()
|
||||
request.url = url
|
||||
|
||||
data = "Hello World"
|
||||
data = b"Hello World"
|
||||
get_size_mock.return_value = len(data)
|
||||
|
||||
def readinto_mock(buf):
|
||||
buf[0:] = data
|
||||
|
||||
open_mock.return_value = mock.MagicMock(name='file_handle', spec=file)
|
||||
file_handle = open_mock.return_value.__enter__.return_value
|
||||
file_handle.readinto.side_effect = readinto_mock
|
||||
if six.PY3:
|
||||
builtin_open = 'builtins.open'
|
||||
open_mock = mock.MagicMock(name='file_handle',
|
||||
spec=open)
|
||||
import _io
|
||||
file_spec = list(set(dir(_io.TextIOWrapper)).union(
|
||||
set(dir(_io.BytesIO))))
|
||||
else:
|
||||
builtin_open = '__builtin__.open'
|
||||
open_mock = mock.MagicMock(name='file_handle',
|
||||
spec=file)
|
||||
file_spec = file
|
||||
|
||||
resp = transport.session.send(request)
|
||||
self.assertEqual(data, resp.content)
|
||||
file_handle = mock.MagicMock(spec=file_spec)
|
||||
file_handle.write.return_value = None
|
||||
file_handle.__enter__.return_value = file_handle
|
||||
file_handle.readinto.side_effect = readinto_mock
|
||||
open_mock.return_value = file_handle
|
||||
|
||||
with mock.patch(builtin_open, open_mock, create=True):
|
||||
resp = transport.session.send(request)
|
||||
self.assertEqual(data, resp.content)
|
||||
|
11
tox.ini
11
tox.ini
@ -1,5 +1,5 @@
|
||||
[tox]
|
||||
envlist = py26,py27,py33,py34,pep8
|
||||
envlist = py26,py27,py33,py34,pypy,pep8
|
||||
|
||||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
@ -7,6 +7,14 @@ deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python setup.py testr --slowest --testr-args='{posargs}'
|
||||
|
||||
[testenv:py33]
|
||||
deps = -r{toxinidir}/requirements-py3.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
|
||||
[testenv:py34]
|
||||
deps = -r{toxinidir}/requirements-py3.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
|
||||
@ -31,3 +39,4 @@ exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,__in
|
||||
|
||||
[hacking]
|
||||
import_exceptions = oslo.vmware._i18n
|
||||
tests.base
|
||||
|
Loading…
x
Reference in New Issue
Block a user