From 0a4f6d605e0380f280c815ac290d3790106dc084 Mon Sep 17 00:00:00 2001 From: Ramakrishnan G Date: Thu, 7 May 2015 16:52:26 +0000 Subject: [PATCH] Python 3 compatibility This commit introduces compatibility with python 3. Closes-Bug: 1449772 Change-Id: I9d65b527fd317046c79310bc79d191de3e2111d5 --- proliantutils/hpssa/constants.py | 2 +- proliantutils/hpssa/objects.py | 16 ++++++----- proliantutils/ilo/ribcl.py | 35 ++++++++++++++++------- proliantutils/ilo/ris.py | 23 +++++++++------ proliantutils/tests/hpssa/test_objects.py | 20 ++++++------- proliantutils/tests/ilo/test_ribcl.py | 2 +- proliantutils/tests/ilo/test_ris.py | 20 ++++++------- tox.ini | 2 +- 8 files changed, 70 insertions(+), 50 deletions(-) diff --git a/proliantutils/hpssa/constants.py b/proliantutils/hpssa/constants.py index c524366..28f390c 100644 --- a/proliantutils/hpssa/constants.py +++ b/proliantutils/hpssa/constants.py @@ -32,7 +32,7 @@ RAID_10_ADM = '10ADM' RAID_LEVEL_INPUT_TO_HPSSA_MAPPING = {RAID_50: '50', RAID_60: '60'} RAID_LEVEL_HPSSA_TO_INPUT_MAPPING = { - v: k for k, v in RAID_LEVEL_INPUT_TO_HPSSA_MAPPING.iteritems()} + v: k for k, v in RAID_LEVEL_INPUT_TO_HPSSA_MAPPING.items()} INTERFACE_TYPE_MAP = {'SCSI': INTERFACE_TYPE_SCSI, 'SAS': INTERFACE_TYPE_SAS, diff --git a/proliantutils/hpssa/objects.py b/proliantutils/hpssa/objects.py index 2dd911a..685485d 100644 --- a/proliantutils/hpssa/objects.py +++ b/proliantutils/hpssa/objects.py @@ -111,7 +111,7 @@ def _convert_to_dict(stdout): """ lines = stdout.split("\n") - lines = filter(None, lines) + lines = list(filter(None, lines)) info_dict, j = _get_dict(lines, 0, 0) return info_dict @@ -231,7 +231,7 @@ class Server(object): raid_info = _convert_to_dict(config) self.controllers = [] - for key, value in raid_info.iteritems(): + for key, value in raid_info.items(): self.controllers.append(Controller(key, value, self)) self.last_updated = time.time() @@ -313,7 +313,7 @@ class Controller(object): self.raid_arrays = [] unassigned_drives = properties.get('unassigned', dict()) - for key, value in unassigned_drives.iteritems(): + for key, value in unassigned_drives.items(): self.unassigned_physical_drives.append(PhysicalDrive(key, value, self)) @@ -485,8 +485,9 @@ class LogicalDrive(object): # It requires space to be stripped. size = self.properties['Size'].replace(' ', '') try: - self.size_gb = (strutils.string_to_bytes(size, return_int=True) / - (1024*1024*1024)) + self.size_gb = int(strutils.string_to_bytes(size, + return_int=True) / + (1024*1024*1024)) except ValueError: msg = ("hpssacli returned unknown size '%(size)s' for logical " "disk '%(logical_disk)s' of RAID array '%(array)s' in " @@ -545,8 +546,9 @@ class PhysicalDrive: # (like 500MB, 25GB) unit of storage space to bytes (Integer value). # It requires space to be stripped. try: - self.size_gb = (strutils.string_to_bytes(size, return_int=True) / - (1024*1024*1024)) + self.size_gb = int(strutils.string_to_bytes(size, + return_int=True) / + (1024*1024*1024)) except ValueError: msg = ("hpssacli returned unknown size '%(size)s' for physical " "disk '%(physical_disk)s' of controller " diff --git a/proliantutils/ilo/ribcl.py b/proliantutils/ilo/ribcl.py index 6ee661b..111830f 100644 --- a/proliantutils/ilo/ribcl.py +++ b/proliantutils/ilo/ribcl.py @@ -18,11 +18,12 @@ over RIBCL scripting language """ import re -import urllib2 import xml.etree.ElementTree as etree from oslo_utils import strutils import six +from six.moves.urllib import error as urllib_error +from six.moves.urllib import request from proliantutils import exception from proliantutils.ilo import common @@ -69,10 +70,11 @@ class RIBCLOperations(operations.IloOperations): urlstr = 'https://%s/ribcl' % (self.host) xml = self._serialize_xml(root) try: - req = urllib2.Request(url=urlstr, data=xml) + req = request.Request(url=urlstr, data=xml.encode('ascii')) req.add_header("Content-length", len(xml)) - data = urllib2.urlopen(req).read() - except (ValueError, urllib2.URLError, urllib2.HTTPError) as e: + data = request.urlopen(req).read() + except (ValueError, urllib_error.URLError, + urllib_error.HTTPError) as e: raise exception.IloConnectionError(e) return data @@ -119,9 +121,19 @@ class RIBCLOperations(operations.IloOperations): :param root: root of the dynamic xml. """ if hasattr(etree, 'tostringlist'): - xml = '\r\n'.join(etree.tostringlist(root)) + '\r\n' + if six.PY3: + xml_content_list = [ + x.decode("utf-8") for x in etree.tostringlist(root)] + else: + xml_content_list = etree.tostringlist(root) + + xml = '\r\n'.join(xml_content_list) + '\r\n' else: - xml = etree.tostring(root) + '\r\n' + if six.PY3: + xml_content = etree.tostring(root).decode("utf-8") + else: + xml_content = etree.tostring(root) + xml = xml_content + '\r\n' return xml def _parse_output(self, xml_response): @@ -518,9 +530,10 @@ class RIBCLOperations(operations.IloOperations): """Request host info from the server.""" urlstr = 'http://%s/xmldata?item=all' % (self.host) try: - req = urllib2.Request(url=urlstr) - xml = urllib2.urlopen(req).read() - except (ValueError, urllib2.URLError, urllib2.HTTPError) as e: + req = request.Request(url=urlstr) + xml = request.urlopen(req).read() + except (ValueError, urllib_error.URLError, + urllib_error.HTTPError) as e: raise IloConnectionError(e) return xml @@ -751,7 +764,7 @@ class RIBCLOperations(operations.IloOperations): memory_bytes = ( strutils.string_to_bytes( memsize.replace(' ', ''), return_int=True)) - memory_mb = memory_bytes / (1024 * 1024) + memory_mb = int(memory_bytes / (1024 * 1024)) total_memory_size = total_memory_size + memory_mb return total_memory_size @@ -812,7 +825,7 @@ class RIBCLOperations(operations.IloOperations): capacity = val['VALUE'] local_bytes = (strutils.string_to_bytes( capacity.replace(' ', ''), return_int=True)) - local_gb = local_bytes / (1024 * 1024 * 1024) + local_gb = int(local_bytes / (1024 * 1024 * 1024)) if minimum >= local_gb or minimum == 0: minimum = local_gb return minimum diff --git a/proliantutils/ilo/ris.py b/proliantutils/ilo/ris.py index 412fc3b..bff6eb0 100644 --- a/proliantutils/ilo/ris.py +++ b/proliantutils/ilo/ris.py @@ -17,10 +17,11 @@ __author__ = 'HP' import base64 import gzip import hashlib -import httplib import json -import StringIO -import urlparse + +import six +from six.moves import http_client +from six.moves.urllib import parse as urlparse from proliantutils import exception from proliantutils.ilo import common @@ -54,16 +55,20 @@ class RISOperations(operations.IloOperations): # Use self.login/self.password and Basic Auth if self.login is not None and self.password is not None: - hr = "BASIC " + base64.b64encode(self.login + ":" + self.password) + auth_data = self.login + ":" + self.password + hr = "BASIC " + base64.b64encode( + auth_data.encode('ascii')).decode("utf-8") request_headers['Authorization'] = hr redir_count = 5 while redir_count: conn = None if url.scheme == 'https': - conn = httplib.HTTPSConnection(host=url.netloc, strict=True) + conn = http_client.HTTPSConnection(host=url.netloc, + strict=True) elif url.scheme == 'http': - conn = httplib.HTTPConnection(host=url.netloc, strict=True) + conn = http_client.HTTPConnection(host=url.netloc, + strict=True) try: conn.request(operation, url.path, headers=request_headers, @@ -98,14 +103,14 @@ class RISOperations(operations.IloOperations): response = dict() try: if body: - response = json.loads(body.decode('utf-8')) - except ValueError: + response = json.loads(body) + except (ValueError, TypeError): # if it doesn't decode as json # NOTE: resources may return gzipped content # try to decode as gzip (we should check the headers for # Content-Encoding=gzip) try: - gzipper = gzip.GzipFile(fileobj=StringIO.StringIO(body)) + gzipper = gzip.GzipFile(fileobj=six.BytesIO(body)) uncompressed_string = gzipper.read().decode('UTF-8') response = json.loads(uncompressed_string) except Exception as e: diff --git a/proliantutils/tests/hpssa/test_objects.py b/proliantutils/tests/hpssa/test_objects.py index f498b34..0c0c974 100644 --- a/proliantutils/tests/hpssa/test_objects.py +++ b/proliantutils/tests/hpssa/test_objects.py @@ -50,8 +50,8 @@ class ServerTest(testtools.TestCase): self.assertEqual(sorted(physical_drives_expected), sorted(physical_drives_found)) - physical_drive = filter(lambda x: x.id == '5I:1:1', - controller.unassigned_physical_drives)[0] + physical_drive = list(filter(lambda x: x.id == '5I:1:1', + controller.unassigned_physical_drives))[0] self.assertEqual(controller, physical_drive.parent) self.assertEqual(500, physical_drive.size_gb) self.assertEqual(constants.INTERFACE_TYPE_SAS, @@ -86,14 +86,14 @@ class ServerTest(testtools.TestCase): self.assertIsInstance(logical_drive.properties, dict) # Assertion on physical drives of array - physical_drive = filter(lambda x: x.id == '5I:1:1', - array.physical_drives)[0] + physical_drive = list(filter(lambda x: x.id == '5I:1:1', + array.physical_drives))[0] self.assertEqual(array, physical_drive.parent) self.assertEqual(500, physical_drive.size_gb) # Assertion on physical drives of controller - physical_drive = filter(lambda x: x.id == '5I:1:3', - controller.unassigned_physical_drives)[0] + physical_drive = list(filter(lambda x: x.id == '5I:1:3', + controller.unassigned_physical_drives))[0] self.assertEqual(controller, physical_drive.parent) self.assertEqual(400, physical_drive.size_gb) @@ -303,13 +303,13 @@ class ControllerTest(testtools.TestCase): controller = server.controllers[0] array = controller.raid_arrays[0] - physical_drive = filter(lambda x: x.id == '5I:1:1', - array.physical_drives)[0] + physical_drive = list(filter(lambda x: x.id == '5I:1:1', + array.physical_drives))[0] self.assertEqual(physical_drive, controller.get_physical_drive_by_id('5I:1:1')) - physical_drive = filter(lambda x: x.id == '5I:1:3', - controller.unassigned_physical_drives)[0] + physical_drive = list(filter(lambda x: x.id == '5I:1:3', + controller.unassigned_physical_drives))[0] self.assertEqual(physical_drive, controller.get_physical_drive_by_id('5I:1:3')) diff --git a/proliantutils/tests/ilo/test_ribcl.py b/proliantutils/tests/ilo/test_ribcl.py index 31b0f25..1959d34 100644 --- a/proliantutils/tests/ilo/test_ribcl.py +++ b/proliantutils/tests/ilo/test_ribcl.py @@ -19,11 +19,11 @@ import json import unittest import mock -import ribcl_sample_outputs as constants from proliantutils import exception from proliantutils.ilo import common from proliantutils.ilo import ribcl +from proliantutils.tests.ilo import ribcl_sample_outputs as constants class IloRibclTestCase(unittest.TestCase): diff --git a/proliantutils/tests/ilo/test_ris.py b/proliantutils/tests/ilo/test_ris.py index 933f971..7cd1ce1 100644 --- a/proliantutils/tests/ilo/test_ris.py +++ b/proliantutils/tests/ilo/test_ris.py @@ -16,10 +16,10 @@ """Test class for RIS Module.""" import base64 -import httplib import json import mock +from six.moves import http_client import testtools from proliantutils import exception @@ -326,7 +326,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): result = self.client._validate_uefi_boot_mode() self.assertFalse(result) - @mock.patch.object(httplib, 'HTTPSConnection') + @mock.patch.object(http_client, 'HTTPSConnection') def test__rest_op_okay(self, https_con_mock): connection_mock_obj = mock.MagicMock() response_mock_obj = mock.MagicMock(status=200) @@ -354,7 +354,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): headers={'Authorization': 'BASIC YWRtaW46QWRtaW4='}, body="null") - @mock.patch.object(httplib, 'HTTPSConnection') + @mock.patch.object(http_client, 'HTTPSConnection') def test__rest_op_request_error(self, https_con_mock): connection_mock_obj = mock.MagicMock() https_con_mock.return_value = connection_mock_obj @@ -365,7 +365,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): https_con_mock.assert_called_once_with(host='1.2.3.4', strict=True) self.assertIn("boom", str(exc)) - @mock.patch.object(httplib, 'HTTPSConnection') + @mock.patch.object(http_client, 'HTTPSConnection') def test__rest_op_get_response_error(self, https_con_mock): connection_mock_obj = mock.MagicMock() https_con_mock.return_value = connection_mock_obj @@ -380,7 +380,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): body="null") self.assertIn("boom", str(exc)) - @mock.patch.object(httplib, 'HTTPSConnection') + @mock.patch.object(http_client, 'HTTPSConnection') def test__rest_op_response_read_error(self, https_con_mock): connection_mock_obj = mock.MagicMock() response_mock_obj = mock.MagicMock(status=200) @@ -392,7 +392,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): 'GET', '/v1/foo', None, None) self.assertIn("boom", str(exc)) - @mock.patch.object(httplib, 'HTTPSConnection') + @mock.patch.object(http_client, 'HTTPSConnection') def test__rest_op_continous_redirection(self, https_con_mock): connection_mock_obj = mock.MagicMock() response_mock_obj = mock.MagicMock(status=301) @@ -418,8 +418,8 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): self.assertEqual(5, connection_mock_obj.request.call_count) self.assertIn('https://1.2.3.4/v1/foo', str(exc)) - @mock.patch.object(httplib, 'HTTPConnection') - @mock.patch.object(httplib, 'HTTPSConnection') + @mock.patch.object(http_client, 'HTTPConnection') + @mock.patch.object(http_client, 'HTTPSConnection') def test__rest_op_one_redirection(self, https_con_mock, http_con_mock): connection_mock_obj = mock.MagicMock() @@ -454,7 +454,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): self.assertTrue(response_mock_obj1.read.called) self.assertTrue(response_mock_obj2.read.called) - @mock.patch.object(httplib, 'HTTPSConnection') + @mock.patch.object(http_client, 'HTTPSConnection') def test__rest_op_response_decode_error(self, https_con_mock): connection_mock_obj = mock.MagicMock() response_mock_obj = mock.MagicMock(status=200) @@ -477,7 +477,7 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): headers={'Authorization': 'BASIC YWRtaW46QWRtaW4='}, body="null") - @mock.patch.object(httplib, 'HTTPSConnection') + @mock.patch.object(http_client, 'HTTPSConnection') def test__rest_op_response_gzipped_response(self, https_con_mock): connection_mock_obj = mock.MagicMock() response_mock_obj = mock.MagicMock(status=200) diff --git a/tox.ini b/tox.ini index 5934343..1a61776 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27,pep8 +envlist = py27,pep8,py34 [testenv] usedevelop = True