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: I4bf885bc7d1ccdf46dde3e0b10a8dbec304aaf9b
This commit is contained in:
Riccardo Pittau 2019-12-02 14:54:30 +01:00
parent a5b257cd86
commit 0e01f0735c
10 changed files with 29 additions and 69 deletions

View File

@ -14,6 +14,7 @@
# under the License. # under the License.
import gzip import gzip
import io
import logging import logging
import math import math
import os import os
@ -31,7 +32,6 @@ from oslo_utils import excutils
from oslo_utils import imageutils from oslo_utils import imageutils
from oslo_utils import units from oslo_utils import units
import requests import requests
import six
from ironic_lib.common.i18n import _ from ironic_lib.common.i18n import _
from ironic_lib import disk_partitioner from ironic_lib import disk_partitioner
@ -519,7 +519,7 @@ def _get_configdrive(configdrive, node_uuid, tempdir=None):
data = configdrive data = configdrive
try: try:
data = six.BytesIO(base64.decode_as_bytes(data)) data = io.BytesIO(base64.decode_as_bytes(data))
except TypeError: except TypeError:
error_msg = (_('Config drive for node %s is not base64 encoded ' error_msg = (_('Config drive for node %s is not base64 encoded '
'or the content is malformed.') % node_uuid) 'or the content is malformed.') % node_uuid)

View File

@ -28,7 +28,6 @@ from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from oslo_utils import excutils from oslo_utils import excutils
import six
from ironic_lib.common.i18n import _ 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. :returns: a dictionary of serializable keyword arguments.
""" """
serializers = [(jsonutils.dumps, _('when converting to JSON')), serializers = [(jsonutils.dumps, _('when converting to JSON')),
(six.text_type, _('when converting to string'))] (str, _('when converting to string'))]
exceptions = collections.defaultdict(list) exceptions = collections.defaultdict(list)
serializable_kwargs = {} serializable_kwargs = {}
for k, v in kwargs.items(): for k, v in kwargs.items():
@ -108,7 +107,7 @@ class IronicException(Exception):
with the keyword arguments provided to the constructor. with the keyword arguments provided to the constructor.
If you need to access the message from an exception you should use 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) 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): class InstanceDeployFailure(IronicException):
_msg_fmt = _("Failed to deploy instance: %(reason)s") _msg_fmt = _("Failed to deploy instance: %(reason)s")

View File

@ -20,11 +20,11 @@ import collections
import ipaddress import ipaddress
import socket import socket
import time import time
from urllib import parse as urlparse
from oslo_config import cfg from oslo_config import cfg
from oslo_config import types as cfg_types from oslo_config import types as cfg_types
from oslo_log import log as logging from oslo_log import log as logging
from six.moves.urllib import parse
import zeroconf import zeroconf
from ironic_lib.common.i18n import _ from ironic_lib.common.i18n import _
@ -261,7 +261,7 @@ def get_endpoint(service_type):
def _parse_endpoint(endpoint, service_type=None): def _parse_endpoint(endpoint, service_type=None):
params = {} params = {}
url = parse.urlparse(endpoint) url = urlparse.urlparse(endpoint)
port = url.port port = url.port
if port is None: if port is None:

View File

@ -14,11 +14,10 @@
# under the License. # under the License.
import abc import abc
import functools
import random import random
import time import time
import six
from ironic_lib.common.i18n import _ from ironic_lib.common.i18n import _
@ -46,7 +45,7 @@ class Timer(object):
:param metrics: The metric logger :param metrics: The metric logger
:param name: The metric name :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. " raise TypeError(_("The metric name is expected to be a string. "
"Value is %s") % name) "Value is %s") % name)
self.metrics = metrics self.metrics = metrics
@ -54,7 +53,7 @@ class Timer(object):
self._start = None self._start = None
def __call__(self, f): def __call__(self, f):
@six.wraps(f) @functools.wraps(f)
def wrapped(*args, **kwargs): def wrapped(*args, **kwargs):
start = _time() start = _time()
result = f(*args, **kwargs) result = f(*args, **kwargs)
@ -101,7 +100,7 @@ class Counter(object):
:param name: The metric name :param name: The metric name
:param sample_rate: Probabilistic rate at which the values will be sent :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. " raise TypeError(_("The metric name is expected to be a string. "
"Value is %s") % name) "Value is %s") % name)
@ -116,7 +115,7 @@ class Counter(object):
self.sample_rate = sample_rate self.sample_rate = sample_rate
def __call__(self, f): def __call__(self, f):
@six.wraps(f) @functools.wraps(f)
def wrapped(*args, **kwargs): def wrapped(*args, **kwargs):
self.metrics.send_counter( self.metrics.send_counter(
self.metrics.get_metric_name(self.name), self.metrics.get_metric_name(self.name),
@ -156,14 +155,14 @@ class Gauge(object):
:param metrics: The metric logger :param metrics: The metric logger
:param name: The metric name :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. " raise TypeError(_("The metric name is expected to be a string. "
"Value is %s") % name) "Value is %s") % name)
self.metrics = metrics self.metrics = metrics
self.name = name self.name = name
def __call__(self, f): def __call__(self, f):
@six.wraps(f) @functools.wraps(f)
def wrapped(*args, **kwargs): def wrapped(*args, **kwargs):
result = f(*args, **kwargs) result = f(*args, **kwargs)
self.metrics.send_gauge(self.metrics.get_metric_name(self.name), self.metrics.send_gauge(self.metrics.get_metric_name(self.name),
@ -178,8 +177,7 @@ def _time():
return time.time() return time.time()
@six.add_metaclass(abc.ABCMeta) class MetricLogger(object, metaclass=abc.ABCMeta):
class MetricLogger(object):
"""Abstract class representing a metrics logger. """Abstract class representing a metrics logger.
A MetricLogger sends data to a backend (noop or statsd). A MetricLogger sends data to a backend (noop or statsd).

View File

@ -14,7 +14,6 @@
# under the License. # under the License.
from oslo_config import cfg from oslo_config import cfg
import six
from ironic_lib.common.i18n import _ from ironic_lib.common.i18n import _
from ironic_lib import exception 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. :param delimiter: Delimiter to use for the metrics name.
:return: The new MetricLogger. :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. " msg = (_("This metric prefix (%s) is of unsupported type. "
"Value should be a string or None") "Value should be a string or None")
% str(prefix)) % str(prefix))

View File

@ -16,7 +16,6 @@ import re
import mock import mock
from oslo_config import cfg from oslo_config import cfg
import six
from ironic_lib import exception from ironic_lib import exception
from ironic_lib.tests import base from ironic_lib.tests import base
@ -34,22 +33,9 @@ class TestException(exception.IronicException):
class TestIronicException(base.IronicLibTestCase): 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): def test___init___json_serializable(self):
exc = TestException(spam=[1, 2, 3], ham='eggs') 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']) self.assertEqual('[1, 2, 3]', exc.kwargs['spam'])
def test___init___string_serializable(self): 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' spam=type('ni', (object,), dict(a=1, b=2))(), ham='eggs'
) )
check_str = 'ni object at' 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']) self.assertIn(check_str, exc.kwargs['spam'])
@mock.patch.object(exception.LOG, 'error', autospec=True) @mock.patch.object(exception.LOG, 'error', autospec=True)

View File

@ -49,24 +49,24 @@ class MockedMetricLogger(metricslib.MetricLogger):
class TestMetricReflection(base.IronicLibTestCase): class TestMetricReflection(base.IronicLibTestCase):
def test_timer_reflection(self): def test_timer_reflection(self):
# Ensure our decorator is done correctly (six.wraps) and we can get the # Ensure our decorator is done correctly (functools.wraps) and we can
# arguments of our decorated function. # get the arguments of our decorated function.
expected = ['run', 'timer'] expected = ['run', 'timer']
signature = reflection.get_signature(timer_check) signature = reflection.get_signature(timer_check)
parameters = list(signature.parameters) parameters = list(signature.parameters)
self.assertEqual(expected, parameters) self.assertEqual(expected, parameters)
def test_counter_reflection(self): def test_counter_reflection(self):
# Ensure our decorator is done correctly (six.wraps) and we can get the # Ensure our decorator is done correctly (functools.wraps) and we can
# arguments of our decorated function. # get the arguments of our decorated function.
expected = ['run', 'counter'] expected = ['run', 'counter']
signature = reflection.get_signature(counter_check) signature = reflection.get_signature(counter_check)
parameters = list(signature.parameters) parameters = list(signature.parameters)
self.assertEqual(expected, parameters) self.assertEqual(expected, parameters)
def test_gauge_reflection(self): def test_gauge_reflection(self):
# Ensure our decorator is done correctly (six.wraps) and we can get the # Ensure our decorator is done correctly (functools.wraps) and we can
# arguments of our decorated function. # get the arguments of our decorated function.
expected = ['run', 'gauge'] expected = ['run', 'gauge']
signature = reflection.get_signature(gauge_check) signature = reflection.get_signature(gauge_check)
parameters = list(signature.parameters) parameters = list(signature.parameters)

View File

@ -24,6 +24,7 @@ import ipaddress
import logging import logging
import os import os
import re import re
from urllib import parse as urlparse
from oslo_concurrency import processutils from oslo_concurrency import processutils
from oslo_config import cfg from oslo_config import cfg
@ -32,8 +33,6 @@ from oslo_utils import excutils
from oslo_utils import specs_matcher from oslo_utils import specs_matcher
from oslo_utils import strutils from oslo_utils import strutils
from oslo_utils import units from oslo_utils import units
import six
from six.moves.urllib import parse
from ironic_lib.common.i18n import _ from ironic_lib.common.i18n import _
from ironic_lib import exception 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. :op: The operator. An empty string in case of None.
:values: A list of values stripped and converted to lowercase. :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: if not expression:
raise ValueError( raise ValueError(
_('Root device hint "%s" expression is empty') % hint_name) _('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. :returns: A normalized string.
""" """
hdict = _extract_hint_operator_and_values(hint_expression, hint_name) 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']]) for t in hdict['values']])
return (hdict['op'] + result).strip() return (hdict['op'] + result).strip()
@ -249,7 +248,7 @@ def _append_operator_to_hints(root_device):
if VALID_ROOT_DEVICE_HINTS[name] is bool: if VALID_ROOT_DEVICE_HINTS[name] is bool:
continue continue
expression = six.text_type(expression) expression = str(expression)
ast = ROOT_DEVICE_HINTS_GRAMMAR.parseString(expression) ast = ROOT_DEVICE_HINTS_GRAMMAR.parseString(expression)
if len(ast) > 1: if len(ast) > 1:
continue continue
@ -290,7 +289,7 @@ def parse_root_device_hints(root_device):
for name, expression in root_device.items(): for name, expression in root_device.items():
hint_type = VALID_ROOT_DEVICE_HINTS[name] hint_type = VALID_ROOT_DEVICE_HINTS[name]
if hint_type is str: if hint_type is str:
if not isinstance(expression, six.string_types): if not isinstance(expression, str):
raise ValueError( raise ValueError(
_('Root device hint "%(name)s" is not a string value. ' _('Root device hint "%(name)s" is not a string value. '
'Hint expression: %(expression)s') % 'Hint expression: %(expression)s') %
@ -517,7 +516,7 @@ def get_route_source(dest, ignore_link_local=True):
try: try:
source = out.strip().split('\n')[0].split('src')[1].split()[0] 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): and ignore_link_local):
LOG.debug('Ignoring link-local source to %(dest)s: %(rec)s', LOG.debug('Ignoring link-local source to %(dest)s: %(rec)s',
{'dest': dest, 'rec': out}) {'dest': dest, 'rec': out})

View File

@ -61,7 +61,6 @@ requestsexceptions==1.2.0
restructuredtext-lint==1.1.1 restructuredtext-lint==1.1.1
rfc3986==0.3.1 rfc3986==0.3.1
Routes==2.3.1 Routes==2.3.1
six==1.10.0
snowballstemmer==1.2.1 snowballstemmer==1.2.1
Sphinx==1.6.2 Sphinx==1.6.2
sphinxcontrib-websupport==1.0.1 sphinxcontrib-websupport==1.0.1

View File

@ -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.service!=1.28.1,>=1.24.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0
requests>=2.14.2 # Apache-2.0 requests>=2.14.2 # Apache-2.0
six>=1.10.0 # MIT
oslo.log>=3.36.0 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0
zeroconf>=0.24.0;python_version>='3.0' # LGPL zeroconf>=0.24.0;python_version>='3.0' # LGPL