diff --git a/ironic_lib/disk_utils.py b/ironic_lib/disk_utils.py index 365148a9..1b9b8bb4 100644 --- a/ironic_lib/disk_utils.py +++ b/ironic_lib/disk_utils.py @@ -14,6 +14,7 @@ # under the License. import gzip +import io import logging import math import os @@ -31,7 +32,6 @@ from oslo_utils import excutils from oslo_utils import imageutils from oslo_utils import units import requests -import six from ironic_lib.common.i18n import _ from ironic_lib import disk_partitioner @@ -519,7 +519,7 @@ def _get_configdrive(configdrive, node_uuid, tempdir=None): data = configdrive try: - data = six.BytesIO(base64.decode_as_bytes(data)) + data = io.BytesIO(base64.decode_as_bytes(data)) except TypeError: error_msg = (_('Config drive for node %s is not base64 encoded ' 'or the content is malformed.') % node_uuid) diff --git a/ironic_lib/exception.py b/ironic_lib/exception.py index 072a41d8..f9f30849 100644 --- a/ironic_lib/exception.py +++ b/ironic_lib/exception.py @@ -28,7 +28,6 @@ from oslo_config import cfg from oslo_log import log as logging from oslo_serialization import jsonutils from oslo_utils import excutils -import six from ironic_lib.common.i18n import _ @@ -68,7 +67,7 @@ def _ensure_exception_kwargs_serializable(exc_class_name, kwargs): :returns: a dictionary of serializable keyword arguments. """ serializers = [(jsonutils.dumps, _('when converting to JSON')), - (six.text_type, _('when converting to string'))] + (str, _('when converting to string'))] exceptions = collections.defaultdict(list) serializable_kwargs = {} for k, v in kwargs.items(): @@ -108,7 +107,7 @@ class IronicException(Exception): with the keyword arguments provided to the constructor. If you need to access the message from an exception you should use - six.text_type(exc) + str(exc) """ @@ -148,25 +147,6 @@ class IronicException(Exception): super(IronicException, self).__init__(message) - def __str__(self): - """Encode to utf-8 then wsme api can consume it as well.""" - value = self.__unicode__() - if six.PY3: - # On Python 3 unicode is the same as str - return value - else: - return value.encode('utf-8') - - def __unicode__(self): - """Return a unicode representation of the exception message.""" - return six.text_type(self.args[0]) - - def format_message(self): - if self.__class__.__name__.endswith('_Remote'): - return self.args[0] - else: - return six.text_type(self) - class InstanceDeployFailure(IronicException): _msg_fmt = _("Failed to deploy instance: %(reason)s") diff --git a/ironic_lib/mdns.py b/ironic_lib/mdns.py index a31283c8..1109c5d4 100644 --- a/ironic_lib/mdns.py +++ b/ironic_lib/mdns.py @@ -20,11 +20,11 @@ import collections import ipaddress import socket import time +from urllib import parse as urlparse from oslo_config import cfg from oslo_config import types as cfg_types from oslo_log import log as logging -from six.moves.urllib import parse import zeroconf from ironic_lib.common.i18n import _ @@ -261,7 +261,7 @@ def get_endpoint(service_type): def _parse_endpoint(endpoint, service_type=None): params = {} - url = parse.urlparse(endpoint) + url = urlparse.urlparse(endpoint) port = url.port if port is None: diff --git a/ironic_lib/metrics.py b/ironic_lib/metrics.py index fa79f9e3..afca1354 100644 --- a/ironic_lib/metrics.py +++ b/ironic_lib/metrics.py @@ -14,11 +14,10 @@ # under the License. import abc +import functools import random import time -import six - from ironic_lib.common.i18n import _ @@ -46,7 +45,7 @@ class Timer(object): :param metrics: The metric logger :param name: The metric name """ - if not isinstance(name, six.string_types): + if not isinstance(name, str): raise TypeError(_("The metric name is expected to be a string. " "Value is %s") % name) self.metrics = metrics @@ -54,7 +53,7 @@ class Timer(object): self._start = None def __call__(self, f): - @six.wraps(f) + @functools.wraps(f) def wrapped(*args, **kwargs): start = _time() result = f(*args, **kwargs) @@ -101,7 +100,7 @@ class Counter(object): :param name: The metric name :param sample_rate: Probabilistic rate at which the values will be sent """ - if not isinstance(name, six.string_types): + if not isinstance(name, str): raise TypeError(_("The metric name is expected to be a string. " "Value is %s") % name) @@ -116,7 +115,7 @@ class Counter(object): self.sample_rate = sample_rate def __call__(self, f): - @six.wraps(f) + @functools.wraps(f) def wrapped(*args, **kwargs): self.metrics.send_counter( self.metrics.get_metric_name(self.name), @@ -156,14 +155,14 @@ class Gauge(object): :param metrics: The metric logger :param name: The metric name """ - if not isinstance(name, six.string_types): + if not isinstance(name, str): raise TypeError(_("The metric name is expected to be a string. " "Value is %s") % name) self.metrics = metrics self.name = name def __call__(self, f): - @six.wraps(f) + @functools.wraps(f) def wrapped(*args, **kwargs): result = f(*args, **kwargs) self.metrics.send_gauge(self.metrics.get_metric_name(self.name), @@ -178,8 +177,7 @@ def _time(): return time.time() -@six.add_metaclass(abc.ABCMeta) -class MetricLogger(object): +class MetricLogger(object, metaclass=abc.ABCMeta): """Abstract class representing a metrics logger. A MetricLogger sends data to a backend (noop or statsd). diff --git a/ironic_lib/metrics_utils.py b/ironic_lib/metrics_utils.py index 0b479448..4ed8d0d4 100644 --- a/ironic_lib/metrics_utils.py +++ b/ironic_lib/metrics_utils.py @@ -14,7 +14,6 @@ # under the License. from oslo_config import cfg -import six from ironic_lib.common.i18n import _ from ironic_lib import exception @@ -62,7 +61,7 @@ def get_metrics_logger(prefix='', backend=None, host=None, delimiter='.'): :param delimiter: Delimiter to use for the metrics name. :return: The new MetricLogger. """ - if not isinstance(prefix, six.string_types): + if not isinstance(prefix, str): msg = (_("This metric prefix (%s) is of unsupported type. " "Value should be a string or None") % str(prefix)) diff --git a/ironic_lib/tests/test_exception.py b/ironic_lib/tests/test_exception.py index b37f81cc..e3fa4eaa 100644 --- a/ironic_lib/tests/test_exception.py +++ b/ironic_lib/tests/test_exception.py @@ -16,7 +16,6 @@ import re import mock from oslo_config import cfg -import six from ironic_lib import exception from ironic_lib.tests import base @@ -34,22 +33,9 @@ class TestException(exception.IronicException): class TestIronicException(base.IronicLibTestCase): - def test___str__encoding(self): - expected = b'\xc3\xa9\xe0\xaf\xb2\xe0\xbe\x84' - if six.PY3: - expected = expected.decode('utf-8') - message = six.unichr(233) + six.unichr(0x0bf2) + six.unichr(3972) - exc = exception.IronicException(message) - self.assertEqual(expected, exc.__str__()) - - def test___str__non_string(self): - exc = exception.IronicException(42) - self.assertEqual("42", exc.__str__()) - self.assertEqual(u"42", exc.__unicode__()) - def test___init___json_serializable(self): exc = TestException(spam=[1, 2, 3], ham='eggs') - self.assertIn('[1, 2, 3]', six.text_type(exc)) + self.assertIn('[1, 2, 3]', str(exc)) self.assertEqual('[1, 2, 3]', exc.kwargs['spam']) def test___init___string_serializable(self): @@ -57,7 +43,7 @@ class TestIronicException(base.IronicLibTestCase): spam=type('ni', (object,), dict(a=1, b=2))(), ham='eggs' ) check_str = 'ni object at' - self.assertIn(check_str, six.text_type(exc)) + self.assertIn(check_str, str(exc)) self.assertIn(check_str, exc.kwargs['spam']) @mock.patch.object(exception.LOG, 'error', autospec=True) diff --git a/ironic_lib/tests/test_metrics.py b/ironic_lib/tests/test_metrics.py index dc75bc41..ced08bba 100644 --- a/ironic_lib/tests/test_metrics.py +++ b/ironic_lib/tests/test_metrics.py @@ -49,24 +49,24 @@ class MockedMetricLogger(metricslib.MetricLogger): class TestMetricReflection(base.IronicLibTestCase): def test_timer_reflection(self): - # Ensure our decorator is done correctly (six.wraps) and we can get the - # arguments of our decorated function. + # Ensure our decorator is done correctly (functools.wraps) and we can + # get the arguments of our decorated function. expected = ['run', 'timer'] signature = reflection.get_signature(timer_check) parameters = list(signature.parameters) self.assertEqual(expected, parameters) def test_counter_reflection(self): - # Ensure our decorator is done correctly (six.wraps) and we can get the - # arguments of our decorated function. + # Ensure our decorator is done correctly (functools.wraps) and we can + # get the arguments of our decorated function. expected = ['run', 'counter'] signature = reflection.get_signature(counter_check) parameters = list(signature.parameters) self.assertEqual(expected, parameters) def test_gauge_reflection(self): - # Ensure our decorator is done correctly (six.wraps) and we can get the - # arguments of our decorated function. + # Ensure our decorator is done correctly (functools.wraps) and we can + # get the arguments of our decorated function. expected = ['run', 'gauge'] signature = reflection.get_signature(gauge_check) parameters = list(signature.parameters) diff --git a/ironic_lib/utils.py b/ironic_lib/utils.py index d6ff8e21..983781ad 100644 --- a/ironic_lib/utils.py +++ b/ironic_lib/utils.py @@ -24,6 +24,7 @@ import ipaddress import logging import os import re +from urllib import parse as urlparse from oslo_concurrency import processutils from oslo_config import cfg @@ -32,8 +33,6 @@ from oslo_utils import excutils from oslo_utils import specs_matcher from oslo_utils import strutils from oslo_utils import units -import six -from six.moves.urllib import parse from ironic_lib.common.i18n import _ from ironic_lib import exception @@ -195,7 +194,7 @@ def _extract_hint_operator_and_values(hint_expression, hint_name): :op: The operator. An empty string in case of None. :values: A list of values stripped and converted to lowercase. """ - expression = six.text_type(hint_expression).strip().lower() + expression = str(hint_expression).strip().lower() if not expression: raise ValueError( _('Root device hint "%s" expression is empty') % hint_name) @@ -228,7 +227,7 @@ def _normalize_hint_expression(hint_expression, hint_name): :returns: A normalized string. """ hdict = _extract_hint_operator_and_values(hint_expression, hint_name) - result = hdict['op'].join([' %s ' % parse.quote(t) + result = hdict['op'].join([' %s ' % urlparse.quote(t) for t in hdict['values']]) return (hdict['op'] + result).strip() @@ -249,7 +248,7 @@ def _append_operator_to_hints(root_device): if VALID_ROOT_DEVICE_HINTS[name] is bool: continue - expression = six.text_type(expression) + expression = str(expression) ast = ROOT_DEVICE_HINTS_GRAMMAR.parseString(expression) if len(ast) > 1: continue @@ -290,7 +289,7 @@ def parse_root_device_hints(root_device): for name, expression in root_device.items(): hint_type = VALID_ROOT_DEVICE_HINTS[name] if hint_type is str: - if not isinstance(expression, six.string_types): + if not isinstance(expression, str): raise ValueError( _('Root device hint "%(name)s" is not a string value. ' 'Hint expression: %(expression)s') % @@ -517,7 +516,7 @@ def get_route_source(dest, ignore_link_local=True): try: source = out.strip().split('\n')[0].split('src')[1].split()[0] - if (ipaddress.ip_address(six.u(source)).is_link_local + if (ipaddress.ip_address(source).is_link_local and ignore_link_local): LOG.debug('Ignoring link-local source to %(dest)s: %(rec)s', {'dest': dest, 'rec': out}) diff --git a/lower-constraints.txt b/lower-constraints.txt index c67f1377..6179aa6e 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -61,7 +61,6 @@ requestsexceptions==1.2.0 restructuredtext-lint==1.1.1 rfc3986==0.3.1 Routes==2.3.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 313d2e29..dc388a57 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,5 @@ oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 oslo.service!=1.28.1,>=1.24.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 requests>=2.14.2 # Apache-2.0 -six>=1.10.0 # MIT oslo.log>=3.36.0 # Apache-2.0 zeroconf>=0.24.0;python_version>='3.0' # LGPL