From ad65824806dd7c9239f2cc123be17242413fa209 Mon Sep 17 00:00:00 2001
From: Victor Stinner <vstinner@redhat.com>
Date: Wed, 7 Oct 2015 18:12:48 +0200
Subject: [PATCH] Port API to Python 3

* test_make_flat_dict(): only use one dictionary key. On Python 3,
  the hash function is now randomized by default and so dictionary
  keys are returned in a random order.
* Replace "not cmp(a, b) == 0" with "a != b"
* test_common: replace range(n) with list(range(n)) to get a list on
  Python 3. On Python 3, range() now returns an iterator.
* Replace dict.items()[0] with list(dict.items()[0]). On Python 3,
  dict.items() now returns a view which is not indexable.
* VolumeTypesController.index(): replace dict.values() with
  list(dict.values()) to get a list on Python 3.
* test_xmlutil: use byte strings for XML
* test_extensions: use byte strings for HTTP body
* Add the following tests to tests-py3.txt:

  - cinder.tests.unit.api.test_common
  - cinder.tests.unit.api.test_extensions
  - cinder.tests.unit.api.test_versions
  - cinder.tests.unit.api.test_xmlutil

Partial-Implements: blueprint cinder-python3
Change-Id: I40c28f6b6a1cf72ce13774755153c8691b4d621b
---
 cinder/api/contrib/types_extra_specs.py  |  2 +-
 cinder/api/v1/types.py                   |  3 ++-
 cinder/api/xmlutil.py                    |  2 +-
 cinder/tests/unit/api/test_common.py     | 12 ++++++------
 cinder/tests/unit/api/test_extensions.py |  6 +++---
 cinder/tests/unit/api/test_xmlutil.py    | 18 ++++++++----------
 tests-py3.txt                            |  4 ++++
 7 files changed, 25 insertions(+), 22 deletions(-)

diff --git a/cinder/api/contrib/types_extra_specs.py b/cinder/api/contrib/types_extra_specs.py
index 4a3b19b5a..26bc1faed 100644
--- a/cinder/api/contrib/types_extra_specs.py
+++ b/cinder/api/contrib/types_extra_specs.py
@@ -42,7 +42,7 @@ class VolumeTypeExtraSpecTemplate(xmlutil.TemplateBuilder):
 
         def extraspec_sel(obj, do_raise=False):
             # Have to extract the key and value for later use...
-            key, value = obj.items()[0]
+            key, value = list(obj.items())[0]
             return dict(key=key, value=value)
 
         root = xmlutil.TemplateElement(tagname, selector=extraspec_sel)
diff --git a/cinder/api/v1/types.py b/cinder/api/v1/types.py
index 99f77c4c7..b28cb017d 100644
--- a/cinder/api/v1/types.py
+++ b/cinder/api/v1/types.py
@@ -56,7 +56,8 @@ class VolumeTypesController(wsgi.Controller):
     def index(self, req):
         """Returns the list of volume types."""
         context = req.environ['cinder.context']
-        vol_types = volume_types.get_all_types(context).values()
+        vol_types = volume_types.get_all_types(context)
+        vol_types = list(vol_types.values())
         req.cache_resource(vol_types, name='types')
         return self._view_builder.index(req, vol_types)
 
diff --git a/cinder/api/xmlutil.py b/cinder/api/xmlutil.py
index 831242c84..7fb851a0c 100644
--- a/cinder/api/xmlutil.py
+++ b/cinder/api/xmlutil.py
@@ -400,7 +400,7 @@ class TemplateElement(object):
                 tmpInsertPos = parent.find(tagnameList[i])
                 if tmpInsertPos is None:
                     break
-                elif not cmp(parent.attrib, tmpattrib) == 0:
+                elif parent.attrib != tmpattrib:
                     break
                 parent = tmpInsertPos
                 insertIndex = i + 1
diff --git a/cinder/tests/unit/api/test_common.py b/cinder/tests/unit/api/test_common.py
index fb8cda4c5..915983776 100644
--- a/cinder/tests/unit/api/test_common.py
+++ b/cinder/tests/unit/api/test_common.py
@@ -44,10 +44,10 @@ class LimiterTest(test.TestCase):
     def setUp(self):
         """Run before each test."""
         super(LimiterTest, self).setUp()
-        self.tiny = range(1)
-        self.small = range(10)
-        self.medium = range(1000)
-        self.large = range(10000)
+        self.tiny = list(range(1))
+        self.small = list(range(10))
+        self.medium = list(range(1000))
+        self.large = list(range(10000))
 
     def test_limiter_offset_zero(self):
         """Test offset key works with 0."""
@@ -126,7 +126,7 @@ class LimiterTest(test.TestCase):
 
     def test_limiter_limit_and_offset(self):
         """Test request with both limit and offset."""
-        items = range(2000)
+        items = list(range(2000))
         req = webob.Request.blank('/?offset=1&limit=3')
         self.assertEqual(items[1:4], common.limited(items, req))
         req = webob.Request.blank('/?offset=3&limit=0')
@@ -138,7 +138,7 @@ class LimiterTest(test.TestCase):
 
     def test_limiter_custom_max_limit(self):
         """Test a max_limit other than 1000."""
-        items = range(2000)
+        items = list(range(2000))
         req = webob.Request.blank('/?offset=1&limit=3')
         self.assertEqual(
             items[1:4], common.limited(items, req, max_limit=2000))
diff --git a/cinder/tests/unit/api/test_extensions.py b/cinder/tests/unit/api/test_extensions.py
index 90f6c3435..c87a2fc12 100644
--- a/cinder/tests/unit/api/test_extensions.py
+++ b/cinder/tests/unit/api/test_extensions.py
@@ -200,12 +200,12 @@ class ExtensionControllerIdFormatTest(test.TestCase):
 
     def test_id_with_xml_format(self):
         result = self._bounce_id('foo.xml')
-        self.assertEqual('foo', result)
+        self.assertEqual(b'foo', result)
 
     def test_id_with_json_format(self):
         result = self._bounce_id('foo.json')
-        self.assertEqual('foo', result)
+        self.assertEqual(b'foo', result)
 
     def test_id_with_bad_format(self):
         result = self._bounce_id('foo.bad')
-        self.assertEqual('foo.bad', result)
+        self.assertEqual(b'foo.bad', result)
diff --git a/cinder/tests/unit/api/test_xmlutil.py b/cinder/tests/unit/api/test_xmlutil.py
index c2ce7bb46..14057cf0e 100644
--- a/cinder/tests/unit/api/test_xmlutil.py
+++ b/cinder/tests/unit/api/test_xmlutil.py
@@ -656,14 +656,12 @@ class TemplateTest(test.TestCase):
                                           selector='scope0:scope1:scope2:key3')
         key3.text = xmlutil.Selector()
         serializer = xmlutil.MasterTemplate(root, 1)
-        xml_list = []
-        xml_list.append("<?xmlversion='1.0'encoding='UTF-8'?><test>")
-        xml_list.append("<scope0><key1>Value1</key1><scope1>")
-        xml_list.append("<key2>Value2</key2><scope2><key3>Value3</key3>")
-        xml_list.append("</scope2></scope1></scope0></test>")
-        expected_xml = ''.join(xml_list)
+        expected_xml = (b"<?xmlversion='1.0'encoding='UTF-8'?><test>"
+                        b"<scope0><key1>Value1</key1><scope1>"
+                        b"<key2>Value2</key2><scope2><key3>Value3</key3>"
+                        b"</scope2></scope1></scope0></test>")
         result = serializer.serialize(obj)
-        result = result.replace('\n', '').replace(' ', '')
+        result = result.replace(b'\n', b'').replace(b' ', b'')
         self.assertEqual(expected_xml, result)
 
 
@@ -728,9 +726,9 @@ class TemplateBuilderTest(test.TestCase):
 
 class MiscellaneousXMLUtilTests(test.TestCase):
     def test_make_flat_dict(self):
-        expected_xml = ("<?xml version='1.0' encoding='UTF-8'?>\n"
-                        '<wrapper><a>foo</a><b>bar</b></wrapper>')
+        expected_xml = (b"<?xml version='1.0' encoding='UTF-8'?>\n"
+                        b'<wrapper><a>foo</a></wrapper>')
         root = xmlutil.make_flat_dict('wrapper')
         tmpl = xmlutil.MasterTemplate(root, 1)
-        result = tmpl.serialize(dict(wrapper=dict(a='foo', b='bar')))
+        result = tmpl.serialize(dict(wrapper=dict(a='foo')))
         self.assertEqual(expected_xml, result)
diff --git a/tests-py3.txt b/tests-py3.txt
index e58d84d07..22559d67b 100644
--- a/tests-py3.txt
+++ b/tests-py3.txt
@@ -1,4 +1,8 @@
 cinder.tests.unit.api.openstack.test_wsgi
+cinder.tests.unit.api.test_common
+cinder.tests.unit.api.test_extensions
+cinder.tests.unit.api.test_versions
+cinder.tests.unit.api.test_xmlutil
 cinder.tests.unit.image.test_cache
 cinder.tests.unit.image.test_glance
 cinder.tests.unit.keymgr.test_mock_key_mgr
-- 
2.45.2