From a572ae21e72c8197fb25f05d39a5caef99d7e575 Mon Sep 17 00:00:00 2001 From: Riccardo Pittau Date: Wed, 18 Dec 2019 10:21:29 +0100 Subject: [PATCH] Stop using six library Since we've dropped support for Python 2.7, it's time to look at the bright future that Python 3.x will bring and stop forcing compatibility with older versions. This patch removes the six library from requirements, not looking back. Change-Id: I4b60638bb0268e5d1cf54fdf7d61964082536f4f --- ironicclient/common/apiclient/base.py | 12 +++---- ironicclient/common/apiclient/exceptions.py | 7 ++-- ironicclient/common/base.py | 19 +++++----- ironicclient/common/http.py | 22 ++++++------ ironicclient/common/utils.py | 3 +- ironicclient/tests/functional/base.py | 13 +++---- .../test_baremetal_deploy_template_basic.py | 5 +-- .../v1/test_baremetal_node_create_negative.py | 5 ++- .../osc/v1/test_baremetal_node_fields.py | 24 ++++++------- .../osc/v1/test_baremetal_node_negative.py | 35 ++++++++----------- ironicclient/tests/functional/utils.py | 4 +-- .../unit/common/apiclient/test_exceptions.py | 12 +++---- ironicclient/tests/unit/common/test_http.py | 2 +- ironicclient/tests/unit/common/test_utils.py | 4 +-- ironicclient/tests/unit/test_exc.py | 3 +- ironicclient/tests/unit/utils.py | 4 +-- .../tests/unit/v1/test_create_resources.py | 17 +++++---- ironicclient/tests/unit/v1/test_node.py | 4 --- ironicclient/v1/create_resources.py | 8 ++--- lower-constraints.txt | 1 - requirements.txt | 1 - 21 files changed, 86 insertions(+), 119 deletions(-) diff --git a/ironicclient/common/apiclient/base.py b/ironicclient/common/apiclient/base.py index fcf536d0c..a1a13999a 100644 --- a/ironicclient/common/apiclient/base.py +++ b/ironicclient/common/apiclient/base.py @@ -26,11 +26,10 @@ Base utilities to build API operation managers and objects on top of. import abc import copy +from http import client as http_client +from urllib import parse as urlparse from oslo_utils import strutils -import six -from six.moves import http_client -from six.moves.urllib import parse from ironicclient.common.apiclient import exceptions from ironicclient.common.i18n import _ @@ -212,8 +211,7 @@ class BaseManager(HookableMixin): return self.client.delete(url) -@six.add_metaclass(abc.ABCMeta) -class ManagerWithFind(BaseManager): +class ManagerWithFind(BaseManager, metaclass=abc.ABCMeta): """Manager with additional `find()`/`findall()` methods.""" @abc.abstractmethod @@ -341,7 +339,7 @@ class CrudManager(BaseManager): return self._list( '%(base_url)s%(query)s' % { 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', + 'query': '?%s' % urlparse.urlencode(kwargs) if kwargs else '', }, self.collection_key) @@ -380,7 +378,7 @@ class CrudManager(BaseManager): rl = self._list( '%(base_url)s%(query)s' % { 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', + 'query': '?%s' % urlparse.urlencode(kwargs) if kwargs else '', }, self.collection_key) num = len(rl) diff --git a/ironicclient/common/apiclient/exceptions.py b/ironicclient/common/apiclient/exceptions.py index 81a3340a2..2ae9bf67e 100644 --- a/ironicclient/common/apiclient/exceptions.py +++ b/ironicclient/common/apiclient/exceptions.py @@ -20,13 +20,10 @@ Exception definitions. """ - +from http import client as http_client import inspect import sys -import six -from six.moves import http_client - from ironicclient.common.i18n import _ @@ -450,7 +447,7 @@ def from_response(response, method, url): kwargs["message"] = (error.get("message") or error.get("faultstring")) kwargs["details"] = (error.get("details") or - six.text_type(body)) + str(body)) elif content_type.startswith("text/"): kwargs["details"] = getattr(response, 'text', '') diff --git a/ironicclient/common/base.py b/ironicclient/common/base.py index 0bd4a35d3..2244c6555 100644 --- a/ironicclient/common/base.py +++ b/ironicclient/common/base.py @@ -19,9 +19,7 @@ Base utilities to build API operation managers and objects on top of. import abc import copy -import six - -import six.moves.urllib.parse as urlparse +from urllib import parse as urlparse from ironicclient.common.apiclient import base from ironicclient import exc @@ -39,8 +37,7 @@ def getid(obj): return obj -@six.add_metaclass(abc.ABCMeta) -class Manager(object): +class Manager(object, metaclass=abc.ABCMeta): """Provides CRUD operations with a particular API.""" def __init__(self, api): @@ -55,13 +52,15 @@ class Manager(object): return ('/v1/%s/%s' % (self._resource_name, resource_id) if resource_id else '/v1/%s' % self._resource_name) - @abc.abstractproperty + @property + @abc.abstractmethod def resource_class(self): """The resource class """ - @abc.abstractproperty + @property + @abc.abstractmethod def _resource_name(self): """The resource name. @@ -259,11 +258,11 @@ class Manager(object): self.api.raw_request('DELETE', self._path(resource_id)) -@six.add_metaclass(abc.ABCMeta) -class CreateManager(Manager): +class CreateManager(Manager, metaclass=abc.ABCMeta): """Provides creation operations with a particular API.""" - @abc.abstractproperty + @property + @abc.abstractmethod def _creation_attributes(self): """A list of required creation attributes for a resource type. diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py index fd916a2c3..bf41d2f4d 100644 --- a/ironicclient/common/http.py +++ b/ironicclient/common/http.py @@ -14,6 +14,8 @@ # under the License. from distutils.version import StrictVersion +import functools +from http import client as http_client import logging import os import re @@ -21,13 +23,11 @@ import socket import ssl import textwrap import time +from urllib import parse as urlparse from keystoneauth1 import adapter from keystoneauth1 import exceptions as kexc from oslo_serialization import jsonutils -import six -from six.moves import http_client -import six.moves.urllib.parse as urlparse from ironicclient.common import filecache from ironicclient.common.i18n import _ @@ -196,7 +196,7 @@ class VersionNegotiationMixin(object): % {'req': requested_version, 'min': min_ver, 'max': max_ver})) - if isinstance(requested_version, six.string_types): + if isinstance(requested_version, str): if requested_version == 'latest': negotiated_ver = max_ver else: @@ -276,7 +276,7 @@ _RETRY_EXCEPTIONS = (exc.Conflict, exc.ServiceUnavailable, def with_retries(func): """Wrapper for _http_request adding support for retries.""" - @six.wraps(func) + @functools.wraps(func) def wrapper(self, url, method, **kwargs): if self.conflict_max_retries is None: self.conflict_max_retries = DEFAULT_MAX_RETRIES @@ -303,7 +303,7 @@ def with_retries(func): return wrapper -class VerifiedHTTPSConnection(six.moves.http_client.HTTPSConnection): +class VerifiedHTTPSConnection(http_client.HTTPSConnection): """httplib-compatible connection using client-side SSL authentication :see http://code.activestate.com/recipes/ @@ -312,9 +312,9 @@ class VerifiedHTTPSConnection(six.moves.http_client.HTTPSConnection): def __init__(self, host, port, key_file=None, cert_file=None, ca_file=None, timeout=None, insecure=False): - six.moves.http_client.HTTPSConnection.__init__(self, host, port, - key_file=key_file, - cert_file=cert_file) + http_client.HTTPSConnection.__init__(self, host, port, + key_file=key_file, + cert_file=cert_file) self.key_file = key_file self.cert_file = cert_file if ca_file is not None: @@ -380,7 +380,7 @@ class SessionClient(VersionNegotiationMixin, adapter.LegacyJsonAdapter): self.api_version_select_state = api_version_select_state self.conflict_max_retries = max_retries self.conflict_retry_interval = retry_interval - if isinstance(kwargs.get('endpoint_override'), six.string_types): + if isinstance(kwargs.get('endpoint_override'), str): kwargs['endpoint_override'] = _trim_endpoint_api_version( kwargs['endpoint_override']) @@ -421,7 +421,7 @@ class SessionClient(VersionNegotiationMixin, adapter.LegacyJsonAdapter): kwargs.setdefault('user_agent', USER_AGENT) kwargs.setdefault('auth', self.auth) - if isinstance(self.endpoint_override, six.string_types): + if isinstance(self.endpoint_override, str): kwargs.setdefault('endpoint_override', self.endpoint_override) if getattr(self, 'os_ironic_api_version', None): diff --git a/ironicclient/common/utils.py b/ironicclient/common/utils.py index fac527857..cf3b1bad9 100644 --- a/ironicclient/common/utils.py +++ b/ironicclient/common/utils.py @@ -28,7 +28,6 @@ import time from oslo_serialization import base64 from oslo_utils import strutils -import six from ironicclient.common.i18n import _ from ironicclient import exc @@ -163,7 +162,7 @@ def convert_list_props_to_comma_separated(data, props=None): for prop in props: val = data.get(prop, None) if isinstance(val, list): - result[prop] = ', '.join(map(six.text_type, val)) + result[prop] = ', '.join(map(str, val)) return result diff --git a/ironicclient/tests/functional/base.py b/ironicclient/tests/functional/base.py index cb87f4831..c62fcd101 100644 --- a/ironicclient/tests/functional/base.py +++ b/ironicclient/tests/functional/base.py @@ -12,10 +12,9 @@ # License for the specific language governing permissions and limitations # under the License. +import configparser import os -import six -import six.moves.configparser as config_parser from tempest.lib.cli import base from tempest.lib.common.utils import data_utils from tempest.lib import exceptions @@ -60,16 +59,12 @@ class FunctionalTestBase(base.ClientTestBase): def _get_config(self): config_file = os.environ.get('IRONICCLIENT_TEST_CONFIG', DEFAULT_CONFIG_FILE) - # SafeConfigParser was deprecated in Python 3.2 - if six.PY3: - config = config_parser.ConfigParser() - else: - config = config_parser.SafeConfigParser() + config = configparser.ConfigParser() if not config.read(config_file): self.skipTest('Skipping, no test config found @ %s' % config_file) try: auth_strategy = config.get('functional', 'auth_strategy') - except config_parser.NoOptionError: + except configparser.NoOptionError: auth_strategy = 'keystone' if auth_strategy not in ['keystone', 'noauth']: raise self.fail( @@ -92,7 +87,7 @@ class FunctionalTestBase(base.ClientTestBase): for c in conf_settings + keystone_v3_conf_settings: try: cli_flags[c] = config.get('functional', c) - except config_parser.NoOptionError: + except configparser.NoOptionError: # NOTE(vdrok): Here we ignore the absence of KS v3 options as # v2 may be used. Keystone client will do the actual check of # the parameters' correctness. diff --git a/ironicclient/tests/functional/osc/v1/test_baremetal_deploy_template_basic.py b/ironicclient/tests/functional/osc/v1/test_baremetal_deploy_template_basic.py index 5a717509c..d3bfdbe9b 100644 --- a/ironicclient/tests/functional/osc/v1/test_baremetal_deploy_template_basic.py +++ b/ironicclient/tests/functional/osc/v1/test_baremetal_deploy_template_basic.py @@ -13,7 +13,6 @@ import json import ddt -import six from tempest.lib.common.utils import data_utils from tempest.lib import exceptions @@ -160,9 +159,7 @@ class BaremetalDeployTemplateTests(base.TestCase): @ddt.data( ('--uuid', '', 'expected one argument'), ('--uuid', '!@#$^*&%^', 'Expected a UUID'), - ('', '', - 'too few arguments' if six.PY2 - else 'the following arguments are required'), + ('', '', 'the following arguments are required'), ('', 'not/a/name', 'Deploy template name must be a valid trait'), ('', 'foo', 'Deploy template name must be a valid trait'), ('--steps', '', 'expected one argument'), diff --git a/ironicclient/tests/functional/osc/v1/test_baremetal_node_create_negative.py b/ironicclient/tests/functional/osc/v1/test_baremetal_node_create_negative.py index eec76db78..82c4201dd 100644 --- a/ironicclient/tests/functional/osc/v1/test_baremetal_node_create_negative.py +++ b/ironicclient/tests/functional/osc/v1/test_baremetal_node_create_negative.py @@ -13,7 +13,6 @@ # under the License. import ddt -import six from tempest.lib import exceptions from ironicclient.tests.functional.osc.v1 import base @@ -44,5 +43,5 @@ class BaremetalNodeCreateNegativeTests(base.TestCase): def test_baremetal_node_create(self, argument, value, ex_text): base_cmd = 'baremetal node create --driver %s' % self.driver_name command = self.construct_cmd(base_cmd, argument, value) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) diff --git a/ironicclient/tests/functional/osc/v1/test_baremetal_node_fields.py b/ironicclient/tests/functional/osc/v1/test_baremetal_node_fields.py index dd19958ff..681b8fc3e 100644 --- a/ironicclient/tests/functional/osc/v1/test_baremetal_node_fields.py +++ b/ironicclient/tests/functional/osc/v1/test_baremetal_node_fields.py @@ -12,7 +12,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six from tempest.lib import exceptions from ironicclient.tests.functional.osc.v1 import base @@ -44,8 +43,7 @@ class TestNodeListFields(base.TestCase): fields = ['instance_uuid', 'name', 'uuid'] node_list = self.openstack( - 'baremetal node list --fields {}' - .format(' '.join(fields))) + 'baremetal node list --fields {}'.format(' '.join(fields))) nodes_list_headers = self._get_table_headers(node_list) self.assertEqual(headers, nodes_list_headers) @@ -53,14 +51,14 @@ class TestNodeListFields(base.TestCase): def test_list_no_fields(self): command = 'baremetal node list --fields' ex_text = 'expected at least one argument' - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) def test_list_wrong_field(self): command = 'baremetal node list --fields ABC' ex_text = 'invalid choice' - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) class TestNodeShowFields(base.TestCase): @@ -117,8 +115,8 @@ class TestNodeShowFields(base.TestCase): 'uuid'] node_show = self.openstack( - 'baremetal node show {} --fields {} {}' - .format(self.node['uuid'], ' '.join(rows), self.api_version)) + 'baremetal node show {} --fields {} {}'.format( + self.node['uuid'], ' '.join(rows), self.api_version)) nodes_show_rows = self._get_table_rows(node_show) self.assertEqual(set(rows), set(nodes_show_rows)) @@ -127,12 +125,12 @@ class TestNodeShowFields(base.TestCase): command = 'baremetal node show {} --fields {}'.format( self.node['uuid'], self.api_version) ex_text = 'expected at least one argument' - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) def test_show_wrong_field(self): command = 'baremetal node show {} --fields ABC {}'.format( self.node['uuid'], self.api_version) ex_text = 'invalid choice' - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) diff --git a/ironicclient/tests/functional/osc/v1/test_baremetal_node_negative.py b/ironicclient/tests/functional/osc/v1/test_baremetal_node_negative.py index 22013aa3b..7970a1223 100644 --- a/ironicclient/tests/functional/osc/v1/test_baremetal_node_negative.py +++ b/ironicclient/tests/functional/osc/v1/test_baremetal_node_negative.py @@ -13,7 +13,6 @@ # under the License. import ddt -import six from tempest.lib import exceptions from ironicclient.tests.functional.osc.v1 import base @@ -28,9 +27,7 @@ class BaremetalNodeNegativeTests(base.TestCase): self.node = self.node_create() @ddt.data( - ('', '', - 'error: argument --driver is required' if six.PY2 - else 'error: the following arguments are required: --driver'), + ('', '', 'error: the following arguments are required: --driver'), ('--driver', 'wrongdriver', 'No valid host was found. Reason: No conductor service ' 'registered which supports driver wrongdriver.') @@ -40,29 +37,26 @@ class BaremetalNodeNegativeTests(base.TestCase): """Negative test for baremetal node driver options.""" base_cmd = 'baremetal node create' command = self.construct_cmd(base_cmd, argument, value) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) def test_delete_no_node(self): """Test for baremetal node delete without node specified.""" command = 'baremetal node delete' - ex_text = 'error: too few arguments' - if six.PY3: - ex_text = '' - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + ex_text = '' + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) def test_list_wrong_argument(self): """Test for baremetal node list with wrong argument.""" command = 'baremetal node list --wrong_arg' ex_text = 'error: unrecognized arguments: --wrong_arg' - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) @ddt.data( ('--property', '', - 'error: too few arguments' if six.PY2 - else 'error: the following arguments are required: '), + 'error: the following arguments are required: '), ('--property', 'prop', 'Attributes must be a list of PATH=VALUE') ) @ddt.unpack @@ -71,13 +65,12 @@ class BaremetalNodeNegativeTests(base.TestCase): base_cmd = 'baremetal node set' command = self.construct_cmd(base_cmd, argument, value, self.node['uuid']) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) @ddt.data( ('--property', '', - 'error: too few arguments' if six.PY2 - else 'error: the following arguments are required: '), + 'error: the following arguments are required: '), ('--property', 'prop', "Reason: can't remove non-existent object") ) @ddt.unpack @@ -86,5 +79,5 @@ class BaremetalNodeNegativeTests(base.TestCase): base_cmd = 'baremetal node unset' command = self.construct_cmd(base_cmd, argument, value, self.node['uuid']) - six.assertRaisesRegex(self, exceptions.CommandFailed, ex_text, - self.openstack, command) + self.assertRaisesRegex(exceptions.CommandFailed, ex_text, + self.openstack, command) diff --git a/ironicclient/tests/functional/utils.py b/ironicclient/tests/functional/utils.py index 49d208915..ba11c40af 100644 --- a/ironicclient/tests/functional/utils.py +++ b/ironicclient/tests/functional/utils.py @@ -12,8 +12,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - def get_dict_from_output(output): """Parse list of dictionaries, return a dictionary. @@ -22,7 +20,7 @@ def get_dict_from_output(output): """ obj = {} for item in output: - obj[item['Property']] = six.text_type(item['Value']) + obj[item['Property']] = str(item['Value']) return obj diff --git a/ironicclient/tests/unit/common/apiclient/test_exceptions.py b/ironicclient/tests/unit/common/apiclient/test_exceptions.py index 2ac5b398c..d466c41d7 100644 --- a/ironicclient/tests/unit/common/apiclient/test_exceptions.py +++ b/ironicclient/tests/unit/common/apiclient/test_exceptions.py @@ -13,9 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from http import client as http_client + from oslotest import base as test_base -import six -from six.moves import http_client from ironicclient.common.apiclient import exceptions @@ -89,17 +89,17 @@ class ExceptionsArgsTest(test_base.BaseTestCase): json_data1 = {"error_message": {"debuginfo": None, "faultcode": "Client", "faultstring": "fake message"}} - message = six.text_type( + message = str( json_data1["error_message"]["faultstring"]) - details = six.text_type(json_data1) + details = str(json_data1) self.assert_exception( exceptions.BadRequest, method, url, status_code, json_data1, message, details) json_data2 = {"badRequest": {"message": "fake message", "code": http_client.BAD_REQUEST}} - message = six.text_type(json_data2["badRequest"]["message"]) - details = six.text_type(json_data2) + message = str(json_data2["badRequest"]["message"]) + details = str(json_data2) self.assert_exception( exceptions.BadRequest, method, url, status_code, json_data2, message, details) diff --git a/ironicclient/tests/unit/common/test_http.py b/ironicclient/tests/unit/common/test_http.py index 441e4eeb5..9f603365b 100644 --- a/ironicclient/tests/unit/common/test_http.py +++ b/ironicclient/tests/unit/common/test_http.py @@ -13,11 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +from http import client as http_client import time import mock from oslo_serialization import jsonutils -from six.moves import http_client from keystoneauth1 import exceptions as kexc diff --git a/ironicclient/tests/unit/common/test_utils.py b/ironicclient/tests/unit/common/test_utils.py index ffc31bbe8..c60ec3178 100644 --- a/ironicclient/tests/unit/common/test_utils.py +++ b/ironicclient/tests/unit/common/test_utils.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import builtins import json import os import subprocess @@ -20,7 +21,6 @@ import sys import tempfile import mock -import six.moves.builtins as __builtin__ from ironicclient.common import utils from ironicclient import exc @@ -355,7 +355,7 @@ class HandleJsonFileTest(test_utils.BaseTestCase): self.assertEqual(json.loads(contents), steps) - @mock.patch.object(__builtin__, 'open', autospec=True) + @mock.patch.object(builtins, 'open', autospec=True) def test_handle_json_or_file_arg_file_fail(self, mock_open): mock_file_object = mock.MagicMock() mock_file_handle = mock.MagicMock() diff --git a/ironicclient/tests/unit/test_exc.py b/ironicclient/tests/unit/test_exc.py index d7c838263..ea57098d3 100644 --- a/ironicclient/tests/unit/test_exc.py +++ b/ironicclient/tests/unit/test_exc.py @@ -13,8 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from http import client as http_client + import mock -from six.moves import http_client from ironicclient.common.apiclient import exceptions from ironicclient import exc diff --git a/ironicclient/tests/unit/utils.py b/ironicclient/tests/unit/utils.py index ea3308e63..02a8767d8 100644 --- a/ironicclient/tests/unit/utils.py +++ b/ironicclient/tests/unit/utils.py @@ -14,13 +14,13 @@ # under the License. import copy +import io import os import fixtures import mock from oslo_utils import strutils import requests -import six import testtools @@ -58,7 +58,7 @@ class FakeAPI(object): def raw_request(self, *args, **kwargs): response = self._request(*args, **kwargs) - body_iter = iter(six.StringIO(response[1])) + body_iter = iter(io.StringIO(response[1])) return FakeResponse(response[0]), body_iter def json_request(self, *args, **kwargs): diff --git a/ironicclient/tests/unit/v1/test_create_resources.py b/ironicclient/tests/unit/v1/test_create_resources.py index 4b37934f5..455877f82 100644 --- a/ironicclient/tests/unit/v1/test_create_resources.py +++ b/ironicclient/tests/unit/v1/test_create_resources.py @@ -10,10 +10,9 @@ # License for the specific language governing permissions and limitations # under the License. +import builtins import jsonschema import mock -import six -import six.moves.builtins as __builtin__ from ironicclient import exc from ironicclient.tests.unit import utils @@ -193,14 +192,14 @@ class CreateResourcesTest(utils.BaseTestCase): class LoadFromFileTest(utils.BaseTestCase): - @mock.patch.object(__builtin__, 'open', + @mock.patch.object(builtins, 'open', mock.mock_open(read_data='{"a": "b"}')) def test_load_json(self): fname = 'abc.json' res = create_resources.load_from_file(fname) self.assertEqual({'a': 'b'}, res) - @mock.patch.object(__builtin__, 'open', + @mock.patch.object(builtins, 'open', mock.mock_open(read_data='{"a": "b"}')) def test_load_unknown_extension(self): fname = 'abc' @@ -208,7 +207,7 @@ class LoadFromFileTest(utils.BaseTestCase): 'must have .json or .yaml extension', create_resources.load_from_file, fname) - @mock.patch.object(__builtin__, 'open', autospec=True) + @mock.patch.object(builtins, 'open', autospec=True) def test_load_ioerror(self, mock_open): mock_open.side_effect = IOError('file does not exist') fname = 'abc.json' @@ -216,7 +215,7 @@ class LoadFromFileTest(utils.BaseTestCase): 'Cannot read file', create_resources.load_from_file, fname) - @mock.patch.object(__builtin__, 'open', + @mock.patch.object(builtins, 'open', mock.mock_open(read_data='{{bbb')) def test_load_incorrect_json(self): fname = 'abc.json' @@ -224,14 +223,14 @@ class LoadFromFileTest(utils.BaseTestCase): exc.ClientException, 'File "%s" is invalid' % fname, create_resources.load_from_file, fname) - @mock.patch.object(__builtin__, 'open', + @mock.patch.object(builtins, 'open', mock.mock_open(read_data='---\na: b')) def test_load_yaml(self): fname = 'abc.yaml' res = create_resources.load_from_file(fname) self.assertEqual({'a': 'b'}, res) - @mock.patch.object(__builtin__, 'open', + @mock.patch.object(builtins, 'open', mock.mock_open(read_data='---\na-: - b')) def test_load_incorrect_yaml(self): fname = 'abc.yaml' @@ -365,7 +364,7 @@ class CreateMethodsTest(utils.BaseTestCase): 'node-uuid-1', 'pg-uuid-2') self.assertEqual(1, len(errs)) self.assertIsInstance(errs[0], exc.ClientException) - self.assertIn('port group', six.text_type(errs[0])) + self.assertIn('port group', str(errs[0])) self.assertFalse(self.client.port.create.called) @mock.patch.object(create_resources, 'create_portgroups', autospec=True) diff --git a/ironicclient/tests/unit/v1/test_node.py b/ironicclient/tests/unit/v1/test_node.py index 8eae43115..de558780b 100644 --- a/ironicclient/tests/unit/v1/test_node.py +++ b/ironicclient/tests/unit/v1/test_node.py @@ -17,7 +17,6 @@ import tempfile import time import mock -import six import testtools from testtools.matchers import HasLength @@ -28,9 +27,6 @@ from ironicclient.v1 import node from ironicclient.v1 import volume_connector from ironicclient.v1 import volume_target -if six.PY3: - import io - file = io.BytesIO NODE1 = {'uuid': '66666666-7777-8888-9999-000000000000', 'chassis_uuid': 'aaaaaaaa-1111-bbbb-2222-cccccccccccc', diff --git a/ironicclient/v1/create_resources.py b/ironicclient/v1/create_resources.py index 3ca56a95d..75f6f0554 100644 --- a/ironicclient/v1/create_resources.py +++ b/ironicclient/v1/create_resources.py @@ -10,10 +10,10 @@ # License for the specific language governing permissions and limitations # under the License. +import functools import json import jsonschema -import six import yaml from ironicclient import exc @@ -61,14 +61,14 @@ def create_resources(client, filenames): if errors: raise exc.ClientException('While validating the resources file(s), the' ' following error(s) were encountered:\n%s' % - '\n'.join(six.text_type(e) for e in errors)) + '\n'.join(str(e) for e in errors)) for r in resources: errors.extend(create_chassis(client, r.get('chassis', []))) errors.extend(create_nodes(client, r.get('nodes', []))) if errors: raise exc.ClientException('During resources creation, the following ' 'error(s) were encountered:\n%s' % - '\n'.join(six.text_type(e) for e in errors)) + '\n'.join(str(e) for e in errors)) def load_from_file(filename): @@ -113,7 +113,7 @@ def create_single_handler(resource_type): """ def outer_wrapper(create_method): - @six.wraps(create_method) + @functools.wraps(create_method) def wrapper(client, **params): uuid = None error = None diff --git a/lower-constraints.txt b/lower-constraints.txt index 388f62a29..5f9da80eb 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -85,7 +85,6 @@ requestsexceptions==1.2.0 restructuredtext-lint==1.1.1 rfc3986==0.3.1 simplejson==3.5.1 -six==1.10.0 snowballstemmer==1.2.1 Sphinx==1.6.2 sphinxcontrib-websupport==1.0.1 diff --git a/requirements.txt b/requirements.txt index 4adff2f02..412c047c8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,3 @@ oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 PyYAML>=3.12 # MIT requests>=2.14.2 # Apache-2.0 -six>=1.10.0 # MIT