Fix Py3 compatibility issues

* Replace of urllib by six urlparse
* Convert dict keys into list to be able to retrieve the first element
* Use integer division for integers
* Use int instead of long in XML serialization/deserialization under Py3

Co-author: Cyril Roelandt <cyril.roelandt@enovance.com>

Change-Id: Ia79c831310775bf1c3dbec06010f8949c3a73887
This commit is contained in:
Ilya Shakhat
2014-07-28 14:02:57 +04:00
parent a6685047e1
commit 9bf8b71e33
13 changed files with 33 additions and 30 deletions

View File

@@ -30,6 +30,9 @@ from neutronclient.openstack.common import jsonutils
LOG = logging.getLogger(__name__)
if six.PY3:
long = int
class ActionDispatcher(object):
"""Maps method name to local methods through action name."""
@@ -59,7 +62,7 @@ class JSONDictSerializer(DictSerializer):
def default(self, data):
def sanitizer(obj):
return unicode(obj)
return six.text_type(obj, 'utf8')
return jsonutils.dumps(data, default=sanitizer)
@@ -100,7 +103,7 @@ class XMLDictSerializer(DictSerializer):
links = data.pop(link_keys[0], None)
has_atom = True
root_key = (len(data) == 1 and
data.keys()[0] or constants.VIRTUAL_ROOT_KEY)
list(data.keys())[0] or constants.VIRTUAL_ROOT_KEY)
root_value = data.get(root_key, data)
doc = etree.Element("_temp_root")
used_prefixes = []
@@ -195,10 +198,7 @@ class XMLDictSerializer(DictSerializer):
LOG.debug("Data %(data)s type is %(type)s",
{'data': data,
'type': type(data)})
if isinstance(data, str):
result.text = unicode(data, 'utf-8')
else:
result.text = unicode(data)
result.text = six.text_type(data)
return result
def _create_link_nodes(self, xml_doc, links):

View File

@@ -21,6 +21,8 @@ import logging
import os
import sys
import six
from neutronclient.common import _
from neutronclient.common import exceptions
from neutronclient.openstack.common import strutils
@@ -134,8 +136,8 @@ def http_log_req(_logger, args, kwargs):
if 'body' in kwargs and kwargs['body']:
string_parts.append(" -d '%s'" % (kwargs['body']))
string_parts = safe_encode_list(string_parts)
_logger.debug("\nREQ: %s\n", "".join(string_parts))
req = strutils.safe_encode("".join(string_parts))
_logger.debug("\nREQ: %s\n", req)
def http_log_resp(_logger, resp, body):
@@ -148,13 +150,13 @@ def http_log_resp(_logger, resp, body):
def _safe_encode_without_obj(data):
if isinstance(data, basestring):
if isinstance(data, six.string_types):
return strutils.safe_encode(data)
return data
def safe_encode_list(data):
return map(_safe_encode_without_obj, data)
return list(map(_safe_encode_without_obj, data))
def safe_encode_dict(data):
@@ -166,4 +168,4 @@ def safe_encode_dict(data):
return (k, safe_encode_dict(v))
return (k, _safe_encode_without_obj(v))
return dict(map(_encode_item, data.items()))
return dict(list(map(_encode_item, data.items())))

View File

@@ -19,7 +19,6 @@
from __future__ import print_function
import argparse
import string
from neutronclient.neutron import v2_0 as neutronv20
from neutronclient.openstack.common.gettextutils import _
@@ -71,7 +70,7 @@ class CreateFirewallPolicy(neutronv20.CreateCommand):
help=_('Create a shared policy.'),
default=argparse.SUPPRESS)
parser.add_argument(
'--firewall-rules', type=string.split,
'--firewall-rules', type=str.split,
help=_('Ordered list of whitespace-delimited firewall rule '
'names or IDs; e.g., --firewall-rules \"rule1 rule2\"'))
parser.add_argument(

View File

@@ -68,7 +68,7 @@ class ListNetwork(neutronV20.ListCommand):
subnet_count = len(subnet_ids)
max_size = ((self.subnet_id_filter_len * subnet_count) -
uri_len_exc.excess)
chunk_size = max_size / self.subnet_id_filter_len
chunk_size = max_size // self.subnet_id_filter_len
subnets = []
for i in range(0, subnet_count, chunk_size):
subnets.extend(

View File

@@ -154,7 +154,7 @@ class ListSecurityGroupRule(neutronV20.ListCommand):
sec_group_count = len(sec_group_ids)
max_size = ((sec_group_id_filter_len * sec_group_count) -
uri_len_exc.excess)
chunk_size = max_size / sec_group_id_filter_len
chunk_size = max_size // sec_group_id_filter_len
secgroups = []
for i in range(0, sec_group_count, chunk_size):
secgroups.extend(

View File

@@ -666,10 +666,10 @@ class NeutronShell(app.App):
self.initialize_app(remainder)
except Exception as err:
if self.options.verbose_level >= self.DEBUG_LEVEL:
self.log.exception(unicode(err))
self.log.exception(err)
raise
else:
self.log.error(unicode(err))
self.log.error(err)
return 1
if self.interactive_mode:
_argv = [sys.argv[0]]
@@ -923,12 +923,12 @@ class NeutronShell(app.App):
def main(argv=sys.argv[1:]):
try:
return NeutronShell(NEUTRON_API_VERSION).run(map(strutils.safe_decode,
argv))
return NeutronShell(NEUTRON_API_VERSION).run(
list(map(strutils.safe_decode, argv)))
except exc.NeutronClientException:
return 1
except Exception as e:
print(unicode(e))
print(e)
return 1

View File

@@ -21,6 +21,7 @@ import fixtures
import httpretty
from mox3 import mox
import requests
import six
import testtools
from keystoneclient.auth.identity import v2 as ks_v2_auth
@@ -468,12 +469,14 @@ class CLITestAuthKeystone(testtools.TestCase):
utils.http_log_req(mox.IgnoreArg(), mox.IgnoreArg(), mox.Func(
verify_no_credentials))
self.client.request(
mox.IsA(str), mox.IsA(str), body=mox.Func(verify_credentials),
mox.IsA(six.string_types), mox.IsA(six.string_types),
body=mox.Func(verify_credentials),
headers=mox.IgnoreArg()
).AndReturn((res200, json.dumps(KS_TOKEN_RESULT)))
utils.http_log_req(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg())
self.client.request(
mox.IsA(str), mox.IsA(str), headers=mox.IsA(dict)
mox.IsA(six.string_types), mox.IsA(six.string_types),
headers=mox.IsA(dict)
).AndReturn((res200, ''))
self.mox.ReplayAll()

View File

@@ -599,7 +599,7 @@ class ClientV2TestJson(CLITestV20Base):
self.client.format = self.format
self.mox.StubOutWithMock(self.client.httpclient, "request")
params = {'test': 'value'}
expect_query = urllib.urlencode(params)
expect_query = six.moves.urllib.parse.urlencode(params)
self.client.httpclient.auth_token = 'token'
self.client.httpclient.request(

View File

@@ -52,5 +52,5 @@ class CLITestV20Agent(test_cli20.CLITestV20Base):
self.assertEqual(1, len(returned_agents))
ag = returned_agents[0]
self.assertEqual(1, len(ag))
self.assertEqual("alive", ag.keys()[0])
self.assertEqual(smile, ag.values()[0])
self.assertIn("alive", ag.keys())
self.assertIn(smile, ag.values())

View File

@@ -286,7 +286,7 @@ class CLITestV20NetworkJSON(test_cli20.CLITestV20Base):
self.assertEqual(1, len(returned_networks))
net = returned_networks[0]
self.assertEqual(1, len(net))
self.assertEqual("id", net.keys()[0])
self.assertIn("id", net.keys())
def test_list_nets_with_default_column(self):
cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None)

View File

@@ -173,7 +173,7 @@ class CLITestV20PacketFilterJSON(test_cli20.CLITestV20Base):
self._test_update_resource,
resource, cmd, 'myid', ['myid'], {})
self.assertEqual('Must specify new values to update packet_filter',
unicode(exc))
str(exc))
def test_delete_packetfilter(self):
"""Delete packetfilter: myid."""

View File

@@ -234,7 +234,7 @@ class CLITestV20SecurityGroupsJSON(test_cli20.CLITestV20Base):
sec_group_count = len(sec_group_ids)
max_size = ((sec_group_id_filter_len * sec_group_count) - excess)
chunk_size = max_size / sec_group_id_filter_len
chunk_size = max_size // sec_group_id_filter_len
for i in range(0, sec_group_count, chunk_size):
search_opts['id'] = sec_group_ids[i: i + chunk_size]

View File

@@ -16,7 +16,6 @@
import logging
import time
import urllib
import requests
import six.moves.urllib.parse as urlparse
@@ -1228,7 +1227,7 @@ class Client(object):
action = self.action_prefix + action
if type(params) is dict and params:
params = utils.safe_encode_dict(params)
action += '?' + urllib.urlencode(params, doseq=1)
action += '?' + urlparse.urlencode(params, doseq=1)
# Ensure client always has correct uri - do not guesstimate anything
self.httpclient.authenticate_and_fetch_endpoint_url()
self._check_uri_length(action)