Remove six and python 2.7 full support

Six is in use to help us to keep support for python 2.7.
Since the ussuri cycle we decide to remove the python 2.7
support so we can go ahead and also remove six usage from
the python code.

Review process and help
-----------------------
Removing six introduce a lot of changes and an huge amount of modified files
To simplify reviews we decided to split changes into several patches to avoid
painful reviews and avoid mistakes.

To review this patch you can use the six documentation [1] to obtain help and
understand choices.

Additional informations
-----------------------
Changes related to 'six.b(data)' [2]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

six.b [2] encode the given datas in latin-1 in python3 so I did the same
things in this patch.

Latin-1 is equal to iso-8859-1 [3].

This encoding is the default encoding [4] of certain descriptive HTTP
headers.

I suggest to keep latin-1 for the moment and to move to another encoding
in a follow-up patch if needed to move to most powerful encoding (utf8).

HTML4 support utf8 charset and utf8 is the default charset for HTML5 [5].

Note that this commit message is autogenerated and not necesserly contains
changes related to 'six.b'

[1] https://six.readthedocs.io/
[2] https://six.readthedocs.io/#six.b
[3] https://docs.python.org/3/library/codecs.html#standard-encodings
[4] https://www.w3schools.com/charsets/ref_html_8859.asp
[5] https://www.w3schools.com/html/html_charset.asp

Patch 3 of a serie of 28 patches

Change-Id: If6e66839c128dde5fb80d90155dedb598da8d53b
This commit is contained in:
Hervé Beraud 2019-11-20 19:37:26 +01:00
parent bb02b2b5f1
commit fccd312871
16 changed files with 27 additions and 70 deletions

View File

@ -21,8 +21,6 @@ import sys
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import excutils from oslo_utils import excutils
import six
from heat.common.i18n import _ from heat.common.i18n import _
_FATAL_EXCEPTION_FORMAT_ERRORS = False _FATAL_EXCEPTION_FORMAT_ERRORS = False
@ -38,7 +36,6 @@ ERROR_CODE_MAP = {
} }
@six.python_2_unicode_compatible
class HeatException(Exception): class HeatException(Exception):
"""Base Heat Exception. """Base Heat Exception.
@ -71,7 +68,7 @@ class HeatException(Exception):
# kwargs doesn't match a variable in the message # kwargs doesn't match a variable in the message
# log the issue and the kwargs # log the issue and the kwargs
LOG.exception('Exception in string format operation') LOG.exception('Exception in string format operation')
for name, value in six.iteritems(kwargs): for name, value in kwargs.items():
LOG.error("%(name)s: %(value)s", LOG.error("%(name)s: %(value)s",
{'name': name, 'value': value}) # noqa {'name': name, 'value': value}) # noqa
@ -222,7 +219,7 @@ class HeatExceptionWithPath(HeatException):
if path is not None: if path is not None:
if isinstance(path, list): if isinstance(path, list):
self.path = path self.path = path
elif isinstance(path, six.string_types): elif isinstance(path, str):
self.path = [path] self.path = [path]
result_path = '' result_path = ''
@ -247,7 +244,7 @@ class StackValidationFailed(HeatExceptionWithPath):
resource=None): resource=None):
if path is None: if path is None:
path = [] path = []
elif isinstance(path, six.string_types): elif isinstance(path, str):
path = [path] path = [path]
if resource is not None and not path: if resource is not None and not path:
@ -263,8 +260,8 @@ class StackValidationFailed(HeatExceptionWithPath):
# oslo.messaging. # oslo.messaging.
self.args = error.args self.args = error.args
else: else:
str_error = six.text_type(type(error).__name__) str_error = str(type(error).__name__)
message = six.text_type(error) message = str(error)
else: else:
str_error = error str_error = error
@ -331,8 +328,8 @@ class ResourceFailure(HeatExceptionWithPath):
path = exception_or_error.path path = exception_or_error.path
else: else:
self.exc = exception_or_error self.exc = exception_or_error
error = six.text_type(type(self.exc).__name__) error = str(type(self.exc).__name__)
message = six.text_type(self.exc) message = str(self.exc)
path = res_path path = res_path
else: else:
self.exc = None self.exc = None
@ -418,7 +415,7 @@ class UpdateReplace(Exception):
"""Raised when resource update requires replacement.""" """Raised when resource update requires replacement."""
def __init__(self, resource_name='Unknown'): def __init__(self, resource_name='Unknown'):
msg = _("The Resource %s requires replacement.") % resource_name msg = _("The Resource %s requires replacement.") % resource_name
super(Exception, self).__init__(six.text_type(msg)) super(Exception, self).__init__(str(msg))
class ResourceUnknownStatus(HeatException): class ResourceUnknownStatus(HeatException):
@ -443,7 +440,7 @@ class ResourceInError(HeatException):
class UpdateInProgress(Exception): class UpdateInProgress(Exception):
def __init__(self, resource_name='Unknown'): def __init__(self, resource_name='Unknown'):
msg = _("The resource %s is already being updated.") % resource_name msg = _("The resource %s is already being updated.") % resource_name
super(Exception, self).__init__(six.text_type(msg)) super(Exception, self).__init__(str(msg))
class HTTPExceptionDisguise(Exception): class HTTPExceptionDisguise(Exception):

View File

@ -11,8 +11,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import six
from heat.common import exception from heat.common import exception
from heat.common.i18n import _ from heat.common.i18n import _
from heat.engine import status from heat.engine import status
@ -122,7 +120,7 @@ def get_members(group, include_failed=False):
""" """
resources = [] resources = []
if group.nested(): if group.nested():
resources = [r for r in six.itervalues(group.nested()) resources = [r for r in group.nested().values()
if include_failed or r.status != r.FAILED] if include_failed or r.status != r.FAILED]
return sorted(resources, return sorted(resources,

View File

@ -17,29 +17,10 @@
# recommendations from # recommendations from
# https://docs.openstack.org/oslo.i18n/latest/user/usage.html # https://docs.openstack.org/oslo.i18n/latest/user/usage.html
import six
import oslo_i18n as i18n import oslo_i18n as i18n
from oslo_utils import encodeutils
_translators = i18n.TranslatorFactory(domain='heat') _translators = i18n.TranslatorFactory(domain='heat')
# The primary translation function using the well-known name "_" # The primary translation function using the well-known name "_"
_ = _translators.primary _ = _translators.primary
def repr_wrapper(klass):
"""A decorator that defines __repr__ method under Python 2.
Under Python 2 it will encode repr return value to str type.
Under Python 3 it does nothing.
"""
if six.PY2:
if '__repr__' not in klass.__dict__:
raise ValueError("@repr_wrapper cannot be applied "
"to %s because it doesn't define __repr__()." %
klass.__name__)
klass._repr = klass.__repr__
klass.__repr__ = lambda self: encodeutils.safe_encode(self._repr())
return klass

View File

@ -15,7 +15,7 @@ import collections
import re import re
from oslo_utils import encodeutils from oslo_utils import encodeutils
from six.moves.urllib import parse as urlparse from urllib import parse as urlparse
from heat.common.i18n import _ from heat.common.i18n import _

View File

@ -12,11 +12,10 @@
# under the License. # under the License.
import collections import collections
import io
import random as random_module import random as random_module
import string import string
import six
# NOTE(pas-ha) Heat officially supports only POSIX::Linux platform # NOTE(pas-ha) Heat officially supports only POSIX::Linux platform
# where os.urandom() and random.SystemRandom() are available # where os.urandom() and random.SystemRandom() are available
@ -88,19 +87,19 @@ def generate_password(length, char_classes):
:param char_classes: Iterable over classes of characters from which to :param char_classes: Iterable over classes of characters from which to
generate a password generate a password
""" """
char_buffer = six.StringIO() char_buffer = io.StringIO()
all_allowed_chars = set() all_allowed_chars = set()
# Add the minimum number of chars from each char class # Add the minimum number of chars from each char class
for char_class in char_classes: for char_class in char_classes:
all_allowed_chars |= char_class.allowed_chars all_allowed_chars |= char_class.allowed_chars
allowed_chars = tuple(char_class.allowed_chars) allowed_chars = tuple(char_class.allowed_chars)
for i in six.moves.xrange(char_class.min_count): for i in range(char_class.min_count):
char_buffer.write(random.choice(allowed_chars)) char_buffer.write(random.choice(allowed_chars))
# Fill up rest with random chars from provided classes # Fill up rest with random chars from provided classes
combined_chars = tuple(all_allowed_chars) combined_chars = tuple(all_allowed_chars)
for i in six.moves.xrange(max(0, length - char_buffer.tell())): for i in range(max(0, length - char_buffer.tell())):
char_buffer.write(random.choice(combined_chars)) char_buffer.write(random.choice(combined_chars))
# Shuffle string # Shuffle string

View File

@ -19,12 +19,12 @@ existing package tree, use create_subpackage() to dynamically create a package
for them before loading them. for them before loading them.
""" """
import functools
import pkgutil import pkgutil
import sys import sys
import types import types
from oslo_log import log as logging from oslo_log import log as logging
import six
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -46,7 +46,7 @@ def create_subpackage(path, parent_package_name, subpackage_name="plugins"):
package_name = _module_name(parent_package_name, subpackage_name) package_name = _module_name(parent_package_name, subpackage_name)
package = types.ModuleType(package_name) package = types.ModuleType(package_name)
package.__path__ = ([path] if isinstance(path, six.string_types) package.__path__ = ([path] if isinstance(path, str)
else list(path)) else list(path))
sys.modules[package_name] = package sys.modules[package_name] = package
@ -75,7 +75,7 @@ def _import_module(importer, module_name, package):
# Make this accessible through the parent package for static imports # Make this accessible through the parent package for static imports
local_name = module_name.partition(package.__name__ + '.')[2] local_name = module_name.partition(package.__name__ + '.')[2]
module_components = local_name.split('.') module_components = local_name.split('.')
parent = six.moves.reduce(getattr, module_components[:-1], package) parent = functools.reduce(getattr, module_components[:-1], package)
setattr(parent, module_components[-1], module) setattr(parent, module_components[-1], module)
return module return module

View File

@ -12,7 +12,6 @@
# under the License. # under the License.
from oslo_log import log as logging from oslo_log import log as logging
import six
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -23,5 +22,5 @@ def log_fail_msg(manager, entrypoint, exception):
'"%(message)s". Not using %(name)s.', '"%(message)s". Not using %(name)s.',
{'module_name': entrypoint.module_name, {'module_name': entrypoint.module_name,
'message': getattr(exception, 'message', 'message': getattr(exception, 'message',
six.text_type(exception)), str(exception)),
'name': entrypoint.name}) 'name': entrypoint.name})

View File

@ -21,7 +21,6 @@ from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from oslo_policy import policy from oslo_policy import policy
from oslo_utils import excutils from oslo_utils import excutils
import six
from heat.common import exception from heat.common import exception
from heat.common.i18n import _ from heat.common.i18n import _
@ -151,7 +150,7 @@ class ResourceEnforcer(Enforcer):
except policy.PolicyNotRegistered: except policy.PolicyNotRegistered:
result = True result = True
except self.exc as ex: except self.exc as ex:
LOG.info(six.text_type(ex)) LOG.info(str(ex))
raise raise
if not result: if not result:
if self.exc: if self.exc:

View File

@ -23,7 +23,6 @@ import datetime
from lxml import etree from lxml import etree
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
import six
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -34,7 +33,7 @@ class JSONResponseSerializer(object):
def sanitizer(obj): def sanitizer(obj):
if isinstance(obj, datetime.datetime): if isinstance(obj, datetime.datetime):
return obj.isoformat() return obj.isoformat()
return six.text_type(obj) return str(obj)
response = jsonutils.dumps(data, default=sanitizer) response = jsonutils.dumps(data, default=sanitizer)
@ -46,7 +45,7 @@ class JSONResponseSerializer(object):
def default(self, response, result): def default(self, response, result):
response.content_type = 'application/json' response.content_type = 'application/json'
response.body = six.b(self.to_json(result)) response.body = self.to_json(result).encode('latin-1')
# Escape XML serialization for these keys, as the AWS API defines them as # Escape XML serialization for these keys, as the AWS API defines them as
@ -75,11 +74,11 @@ class XMLResponseSerializer(object):
else: else:
self.object_to_element(value, subelement) self.object_to_element(value, subelement)
else: else:
element.text = six.text_type(obj) element.text = str(obj)
def to_xml(self, data): def to_xml(self, data):
# Assumption : root node is dict with single key # Assumption : root node is dict with single key
root = next(six.iterkeys(data)) root = next(iter(data.keys()))
eltree = etree.Element(root) eltree = etree.Element(root)
self.object_to_element(data.get(root), eltree) self.object_to_element(data.get(root), eltree)
response = etree.tostring(eltree) response = etree.tostring(eltree)

View File

@ -19,8 +19,6 @@ The IDs each comprise 12 (lower-case) alphanumeric characters.
import base64 import base64
import uuid import uuid
import six
from heat.common.i18n import _ from heat.common.i18n import _
@ -30,12 +28,12 @@ def _to_byte_string(value, num_bits):
Padding is added at the end (i.e. after the least-significant bit) if Padding is added at the end (i.e. after the least-significant bit) if
required. required.
""" """
shifts = six.moves.xrange(num_bits - 8, -8, -8) shifts = range(num_bits - 8, -8, -8)
def byte_at(off): def byte_at(off):
return (value >> off if off >= 0 else value << -off) & 0xff return (value >> off if off >= 0 else value << -off) & 0xff
return b''.join(six.int2byte(byte_at(offset)) for offset in shifts) return b''.join(bytes((byte_at(offset),)) for offset in shifts)
def get_id(source_uuid): def get_id(source_uuid):
@ -43,7 +41,7 @@ def get_id(source_uuid):
The supplied UUID must be a version 4 UUID object. The supplied UUID must be a version 4 UUID object.
""" """
if isinstance(source_uuid, six.string_types): if isinstance(source_uuid, str):
source_uuid = uuid.UUID(source_uuid) source_uuid = uuid.UUID(source_uuid)
if source_uuid.version != 4: if source_uuid.version != 4:
raise ValueError(_('Invalid UUID version (%d)') % source_uuid.version) raise ValueError(_('Invalid UUID version (%d)') % source_uuid.version)

View File

@ -17,7 +17,6 @@ from oslo_utils import strutils
import six import six
from heat.common.i18n import _ from heat.common.i18n import _
from heat.common.i18n import repr_wrapper
from heat.engine import constraints as constr from heat.engine import constraints as constr
from heat.engine import support from heat.engine import support
@ -139,7 +138,6 @@ BASE_ATTRIBUTES = (SHOW_ATTR, ) = ('show', )
ALL_ATTRIBUTES = '*' ALL_ATTRIBUTES = '*'
@repr_wrapper
class Attributes(collections.Mapping): class Attributes(collections.Mapping):
"""Models a collection of Resource Attributes.""" """Models a collection of Resource Attributes."""

View File

@ -18,14 +18,12 @@ import six
from heat.common import exception from heat.common import exception
from heat.common.i18n import _ from heat.common.i18n import _
from heat.common.i18n import repr_wrapper
class CircularDependencyException(exception.HeatException): class CircularDependencyException(exception.HeatException):
msg_fmt = _("Circular Dependency Found: %(cycle)s") msg_fmt = _("Circular Dependency Found: %(cycle)s")
@repr_wrapper
@six.python_2_unicode_compatible @six.python_2_unicode_compatible
class Node(object): class Node(object):
"""A node in a dependency graph.""" """A node in a dependency graph."""
@ -172,7 +170,6 @@ class Graph(collections.defaultdict):
raise CircularDependencyException(cycle=six.text_type(graph)) raise CircularDependencyException(cycle=six.text_type(graph))
@repr_wrapper
@six.python_2_unicode_compatible @six.python_2_unicode_compatible
class Dependencies(object): class Dependencies(object):
"""Helper class for calculating a dependency graph.""" """Helper class for calculating a dependency graph."""

View File

@ -18,7 +18,6 @@ import operator
import six import six
from heat.common import exception from heat.common import exception
from heat.common.i18n import repr_wrapper
from heat.engine import function from heat.engine import function
from heat.engine import properties from heat.engine import properties
@ -37,7 +36,6 @@ FIELDS = (
) )
@repr_wrapper
class ResourceDefinition(object): class ResourceDefinition(object):
"""A definition of a resource, independent of any template format.""" """A definition of a resource, independent of any template format."""

View File

@ -21,7 +21,6 @@ from oslo_utils import excutils
import six import six
from heat.common.i18n import _ from heat.common.i18n import _
from heat.common.i18n import repr_wrapper
from heat.common import timeutils from heat.common import timeutils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -365,7 +364,6 @@ def wrappertask(task): # noqa: C901
return wrapper return wrapper
@repr_wrapper
class DependencyTaskGroup(object): class DependencyTaskGroup(object):
"""Task which manages group of subtasks that have ordering dependencies.""" """Task which manages group of subtasks that have ordering dependencies."""

View File

@ -15,7 +15,6 @@ from oslo_log import log as logging
import six import six
from heat.common import exception from heat.common import exception
from heat.common.i18n import repr_wrapper
from heat.engine import dependencies from heat.engine import dependencies
from heat.engine import resource from heat.engine import resource
from heat.engine import scheduler from heat.engine import scheduler
@ -25,7 +24,6 @@ from heat.objects import resource as resource_objects
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@repr_wrapper
class StackUpdate(object): class StackUpdate(object):
"""A Task to perform the update of an existing stack to a new template.""" """A Task to perform the update of an existing stack to a new template."""

View File

@ -18,7 +18,6 @@ import eventlet
import mock import mock
import six import six
from heat.common.i18n import repr_wrapper
from heat.common import timeutils from heat.common import timeutils
from heat.engine import dependencies from heat.engine import dependencies
from heat.engine import scheduler from heat.engine import scheduler
@ -1273,7 +1272,6 @@ class DescriptionTest(common.HeatTestCase):
self.assertEqual('o', scheduler.task_description(C())) self.assertEqual('o', scheduler.task_description(C()))
def test_unicode(self): def test_unicode(self):
@repr_wrapper
@six.python_2_unicode_compatible @six.python_2_unicode_compatible
class C(object): class C(object):
def __str__(self): def __str__(self):