From 8c0d58075b73aaffeeba335d70562c84cb467ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Beraud?= Date: Wed, 20 Nov 2019 19:37:26 +0100 Subject: [PATCH] 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 6 of a serie of 28 patches Change-Id: Ic56cf6da5ff9ab8f4bd218e6516b87f47165206d --- heat/engine/dependencies.py | 29 +++++------- heat/engine/environment.py | 37 +++++++-------- heat/engine/function.py | 34 ++++++-------- heat/engine/hot/functions.py | 87 +++++++++++++++++------------------ heat/engine/hot/template.py | 26 +++++------ heat/engine/node_data.py | 10 ++-- heat/engine/output.py | 6 +-- heat/engine/parameters.py | 36 +++++++-------- heat/engine/plugin_manager.py | 10 ++-- heat/engine/properties.py | 22 ++++----- 10 files changed, 134 insertions(+), 163 deletions(-) diff --git a/heat/engine/dependencies.py b/heat/engine/dependencies.py index 3c84b9e6d0..b61dd578c1 100644 --- a/heat/engine/dependencies.py +++ b/heat/engine/dependencies.py @@ -14,8 +14,6 @@ import collections import itertools -import six - from heat.common import exception from heat.common.i18n import _ @@ -24,7 +22,6 @@ class CircularDependencyException(exception.HeatException): msg_fmt = _("Circular Dependency Found: %(cycle)s") -@six.python_2_unicode_compatible class Node(object): """A node in a dependency graph.""" @@ -92,15 +89,14 @@ class Node(object): def __str__(self): """Return a human-readable string representation of the node.""" - text = '{%s}' % ', '.join(six.text_type(n) for n in self) - return six.text_type(text) + text = '{%s}' % ', '.join(str(n) for n in self) + return str(text) def __repr__(self): """Return a string representation of the node.""" return repr(self.require) -@six.python_2_unicode_compatible class Graph(collections.defaultdict): """A mutable mapping of objects to nodes in a dependency graph.""" @@ -132,7 +128,7 @@ class Graph(collections.defaultdict): for rqd in node: yield (rqr, rqd) return itertools.chain.from_iterable(outgoing_edges(*i) - for i in six.iteritems(self)) + for i in self.items()) def __delitem__(self, key): """Delete the node given by the specified key from the graph.""" @@ -147,10 +143,10 @@ class Graph(collections.defaultdict): def __str__(self): """Convert the graph to a human-readable string.""" - pairs = ('%s: %s' % (six.text_type(k), six.text_type(v)) - for k, v in six.iteritems(self)) + pairs = ('%s: %s' % (str(k), str(v)) + for k, v in self.items()) text = '{%s}' % ', '.join(pairs) - return six.text_type(text) + return str(text) @staticmethod def toposort(graph): @@ -158,8 +154,8 @@ class Graph(collections.defaultdict): This is a destructive operation for the graph. """ - for iteration in six.moves.xrange(len(graph)): - for key, node in six.iteritems(graph): + for iteration in range(len(graph)): + for key, node in graph.items(): if not node: yield key del graph[key] @@ -167,10 +163,9 @@ class Graph(collections.defaultdict): else: # There are nodes remaining, but none without # dependencies: a cycle - raise CircularDependencyException(cycle=six.text_type(graph)) + raise CircularDependencyException(cycle=str(graph)) -@six.python_2_unicode_compatible class Dependencies(object): """Helper class for calculating a dependency graph.""" @@ -227,8 +222,8 @@ class Dependencies(object): return itertools.chain([(rqr, key)], get_edges(rqr)) # Get the edge list for each node that requires the current node - edge_lists = six.moves.map(requirer_edges, - self._graph[key].required_by()) + edge_lists = map(requirer_edges, + self._graph[key].required_by()) # Combine the lists into one long list return itertools.chain.from_iterable(edge_lists) @@ -263,7 +258,7 @@ class Dependencies(object): def __str__(self): """Return a human-readable string repr of the dependency graph.""" - return six.text_type(self._graph) + return str(self._graph) def __repr__(self): """Return a consistent string representation of the object.""" diff --git a/heat/engine/environment.py b/heat/engine/environment.py index 1efb9f3743..8defdf31ff 100644 --- a/heat/engine/environment.py +++ b/heat/engine/environment.py @@ -21,7 +21,6 @@ import weakref from oslo_config import cfg from oslo_log import log from oslo_utils import fnmatch -import six from heat.common import environment_format as env_fmt from heat.common import exception @@ -54,7 +53,7 @@ def valid_restricted_actions(action): def is_hook_definition(key, value): is_valid_hook = False if key == 'hooks': - if isinstance(value, six.string_types): + if isinstance(value, str): is_valid_hook = valid_hook_type(value) elif isinstance(value, collections.Sequence): is_valid_hook = all(valid_hook_type(hook) for hook in value) @@ -71,7 +70,7 @@ def is_hook_definition(key, value): def is_valid_restricted_action(key, value): valid_action = False if key == 'restricted_actions': - if isinstance(value, six.string_types): + if isinstance(value, str): valid_action = valid_restricted_actions(value) elif isinstance(value, collections.Sequence): valid_action = all(valid_restricted_actions( @@ -101,7 +100,7 @@ class ResourceInfo(object): if name.endswith(('.yaml', '.template')): # a template url for the resource "Type" klass = TemplateResourceInfo - elif not isinstance(value, six.string_types): + elif not isinstance(value, str): klass = ClassResourceInfo elif value.endswith(('.yaml', '.template')): # a registered template @@ -344,10 +343,8 @@ class ResourceRegistry(object): if info.value.support_status.message is not None: details = { 'name': info.name, - 'status': six.text_type( - info.value.support_status.status), - 'message': six.text_type( - info.value.support_status.message) + 'status': str(info.value.support_status.status), + 'message': str(info.value.support_status.message) } LOG.warning('%(name)s is %(status)s. %(message)s', details) @@ -364,7 +361,7 @@ class ResourceRegistry(object): if show_all or isinstance(registry[name], TemplateResourceInfo): msg = ('%(p)sRegistered: %(t)s' % {'p': prefix, - 't': six.text_type(registry[name])}) + 't': str(registry[name])}) LOG.info(msg) def remove_item(self, info): @@ -394,11 +391,11 @@ class ResourceRegistry(object): """ ress = self._registry['resources'] restricted_actions = set() - for name_pattern, resource in six.iteritems(ress): + for name_pattern, resource in ress.items(): if fnmatch.fnmatchcase(resource_name, name_pattern): if 'restricted_actions' in resource: actions = resource['restricted_actions'] - if isinstance(actions, six.string_types): + if isinstance(actions, str): restricted_actions.add(actions) elif isinstance(actions, collections.Sequence): restricted_actions |= set(actions) @@ -429,11 +426,11 @@ class ResourceRegistry(object): everything. """ ress = self._registry['resources'] - for name_pattern, resource in six.iteritems(ress): + for name_pattern, resource in ress.items(): if fnmatch.fnmatchcase(resource_name, name_pattern): if 'hooks' in resource: hooks = resource['hooks'] - if isinstance(hooks, six.string_types): + if isinstance(hooks, str): if hook == hooks: return True elif isinstance(hooks, collections.Sequence): @@ -444,7 +441,7 @@ class ResourceRegistry(object): def remove_resources_except(self, resource_name): ress = self._registry['resources'] new_resources = {} - for name, res in six.iteritems(ress): + for name, res in ress.items(): if fnmatch.fnmatchcase(resource_name, name): new_resources.update(res) if resource_name in ress: @@ -477,7 +474,7 @@ class ResourceRegistry(object): # handle: "OS::*" -> "Dreamhost::*" def is_a_glob(resource_type): return resource_type.endswith('*') - globs = six.moves.filter(is_a_glob, iter(self._registry)) + globs = filter(is_a_glob, iter(self._registry)) for pattern in globs: if self._registry[pattern].matches(resource_type): yield self._registry[pattern] @@ -550,7 +547,7 @@ class ResourceRegistry(object): msg = _('Non-empty resource type is required ' 'for resource "%s"') % resource_name raise exception.StackValidationFailed(message=msg) - elif not isinstance(resource_type, six.string_types): + elif not isinstance(resource_type, str): msg = _('Resource "%s" type is not a string') % resource_name raise exception.StackValidationFailed(message=msg) @@ -558,7 +555,7 @@ class ResourceRegistry(object): info = self.get_resource_info(resource_type, resource_name=resource_name) except exception.EntityNotFound as exc: - raise exception.StackValidationFailed(message=six.text_type(exc)) + raise exception.StackValidationFailed(message=str(exc)) return info.get_class_to_instantiate() @@ -590,7 +587,7 @@ class ResourceRegistry(object): if support_status is not None and not support.is_valid_status( support_status): msg = (_('Invalid support status and should be one of %s') % - six.text_type(support.SUPPORT_STATUSES)) + str(support.SUPPORT_STATUSES)) raise exception.Invalid(reason=msg) def is_resource(key): @@ -650,7 +647,7 @@ class ResourceRegistry(object): } return [resource_description(name, cls, with_description) - for name, cls in six.iteritems(self._registry) + for name, cls in self._registry.items() if (is_resource(name) and name_matches(name) and status_matches(cls) and @@ -693,7 +690,7 @@ class Environment(object): if env_fmt.PARAMETERS in env: self.params = env[env_fmt.PARAMETERS] else: - self.params = dict((k, v) for (k, v) in six.iteritems(env) + self.params = dict((k, v) for (k, v) in env.items() if k not in (env_fmt.PARAMETER_DEFAULTS, env_fmt.ENCRYPTED_PARAM_NAMES, env_fmt.EVENT_SINKS, diff --git a/heat/engine/function.py b/heat/engine/function.py index 9dfc8d3d5c..c3a276d196 100644 --- a/heat/engine/function.py +++ b/heat/engine/function.py @@ -16,14 +16,11 @@ import collections import itertools import weakref -import six - from heat.common import exception from heat.common.i18n import _ -@six.add_metaclass(abc.ABCMeta) -class Function(object): +class Function(metaclass=abc.ABCMeta): """Abstract base class for template functions.""" def __init__(self, stack, fn_name, args): @@ -98,13 +95,13 @@ class Function(object): return all_dep_attrs(self.args) def res_dep_attrs(resource_name): - return six.moves.zip(itertools.repeat(resource_name), - self.dep_attrs(resource_name)) + return zip(itertools.repeat(resource_name), + self.dep_attrs(resource_name)) resource_names = self.stack.enabled_rsrc_names() - return itertools.chain.from_iterable(six.moves.map(res_dep_attrs, - resource_names)) + return itertools.chain.from_iterable(map(res_dep_attrs, + resource_names)) def __reduce__(self): """Return a representation of the function suitable for pickling. @@ -160,8 +157,7 @@ class Function(object): __hash__ = None -@six.add_metaclass(abc.ABCMeta) -class Macro(Function): +class Macro(Function, metaclass=abc.ABCMeta): """Abstract base class for template macros. A macro differs from a function in that it controls how the template is @@ -260,7 +256,7 @@ def resolve(snippet): if isinstance(snippet, collections.Mapping): return dict((k, resolve(v)) for k, v in snippet.items()) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): return [resolve(v) for v in snippet] @@ -270,7 +266,7 @@ def resolve(snippet): def validate(snippet, path=None): if path is None: path = [] - elif isinstance(path, six.string_types): + elif isinstance(path, str): path = [path] if isinstance(snippet, Function): @@ -281,11 +277,11 @@ def validate(snippet, path=None): except Exception as e: raise exception.StackValidationFailed( path=path + [snippet.fn_name], - message=six.text_type(e)) + message=str(e)) elif isinstance(snippet, collections.Mapping): - for k, v in six.iteritems(snippet): + for k, v in snippet.items(): validate(v, path + [k]) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): basepath = list(path) parent = basepath.pop() if basepath else '' @@ -305,13 +301,13 @@ def dependencies(snippet, path=''): elif isinstance(snippet, collections.Mapping): def mkpath(key): - return '.'.join([path, six.text_type(key)]) + return '.'.join([path, str(key)]) deps = (dependencies(value, mkpath(key)) for key, value in snippet.items()) return itertools.chain.from_iterable(deps) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): def mkpath(idx): return ''.join([path, '[%d]' % idx]) @@ -340,7 +336,7 @@ def dep_attrs(snippet, resource_name): elif isinstance(snippet, collections.Mapping): attrs = (dep_attrs(val, resource_name) for val in snippet.values()) return itertools.chain.from_iterable(attrs) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): attrs = (dep_attrs(value, resource_name) for value in snippet) return itertools.chain.from_iterable(attrs) @@ -363,7 +359,7 @@ def all_dep_attrs(snippet): elif isinstance(snippet, collections.Mapping): res_attrs = (all_dep_attrs(value) for value in snippet.values()) return itertools.chain.from_iterable(res_attrs) - elif (not isinstance(snippet, six.string_types) and + elif (not isinstance(snippet, str) and isinstance(snippet, collections.Iterable)): res_attrs = (all_dep_attrs(value) for value in snippet) return itertools.chain.from_iterable(res_attrs) diff --git a/heat/engine/hot/functions.py b/heat/engine/hot/functions.py index 713815e899..cf4eaa0f52 100644 --- a/heat/engine/hot/functions.py +++ b/heat/engine/hot/functions.py @@ -12,14 +12,14 @@ # under the License. import collections +import functools import hashlib import itertools from oslo_config import cfg from oslo_log import log as logging from oslo_serialization import jsonutils -import six -from six.moves.urllib import parse as urlparse +from urllib import parse as urlparse import yaql from yaql.language import exceptions @@ -76,7 +76,7 @@ class GetParam(function.Function): raise ValueError(_('Function "%s" must have arguments') % self.fn_name) - if isinstance(args, six.string_types): + if isinstance(args, str): param_name = args path_components = [] elif isinstance(args, collections.Sequence): @@ -86,7 +86,7 @@ class GetParam(function.Function): raise TypeError(_('Argument to "%s" must be string or list') % self.fn_name) - if not isinstance(param_name, six.string_types): + if not isinstance(param_name, str): raise TypeError(_('Parameter name in "%s" must be string') % self.fn_name) @@ -100,12 +100,12 @@ class GetParam(function.Function): collections.Sequence)): raise TypeError(_('"%s" can\'t traverse path') % self.fn_name) - if not isinstance(key, (six.string_types, int)): + if not isinstance(key, (str, int)): raise TypeError(_('Path components in "%s" ' 'must be strings') % self.fn_name) if isinstance(collection, collections.Sequence - ) and isinstance(key, six.string_types): + ) and isinstance(key, str): try: key = int(key) except ValueError: @@ -116,7 +116,7 @@ class GetParam(function.Function): return collection[key] try: - return six.moves.reduce(get_path_component, path_components, + return functools.reduce(get_path_component, path_components, parameter) except (KeyError, IndexError, TypeError): return '' @@ -168,7 +168,7 @@ class GetAttThenSelect(function.Function): def _parse_args(self): if (not isinstance(self.args, collections.Sequence) or - isinstance(self.args, six.string_types)): + isinstance(self.args, str)): raise TypeError(_('Argument to "%s" must be a list') % self.fn_name) @@ -200,7 +200,7 @@ class GetAttThenSelect(function.Function): attrs = [self._attr_path()] except Exception as exc: LOG.debug("Ignoring exception calculating required attributes" - ": %s %s", type(exc).__name__, six.text_type(exc)) + ": %s %s", type(exc).__name__, str(exc)) attrs = [] else: attrs = [] @@ -400,13 +400,13 @@ class Replace(function.Function): return '' if not isinstance(value, - (six.string_types, six.integer_types, + (str, int, float, bool)): raise TypeError(_('"%(name)s" params must be strings or numbers, ' 'param %(param)s is not valid') % {'name': self.fn_name, 'param': param}) - return six.text_type(value) + return str(value) def result(self): template = function.resolve(self._string) @@ -415,7 +415,7 @@ class Replace(function.Function): if self._strict: unreplaced_keys = set(mapping) - if not isinstance(template, six.string_types): + if not isinstance(template, str): raise TypeError(_('"%s" template must be a string') % self.fn_name) if not isinstance(mapping, collections.Mapping): @@ -426,7 +426,7 @@ class Replace(function.Function): return strings placeholder = keys[0] - if not isinstance(placeholder, six.string_types): + if not isinstance(placeholder, str): raise TypeError(_('"%s" param placeholders must be strings') % self.fn_name) @@ -490,7 +490,7 @@ class ReplaceJson(Replace): else: _raise_empty_param_value_error() - if not isinstance(value, (six.string_types, six.integer_types, + if not isinstance(value, (str, int, float, bool)): if isinstance(value, (collections.Mapping, collections.Sequence)): if not self._allow_empty_value and len(value) == 0: @@ -507,7 +507,7 @@ class ReplaceJson(Replace): raise TypeError(_('"%s" params must be strings, numbers, ' 'list or map.') % self.fn_name) - ret_value = six.text_type(value) + ret_value = str(value) if not self._allow_empty_value and not ret_value: _raise_empty_param_value_error() return ret_value @@ -553,7 +553,7 @@ class GetFile(function.Function): assert self.files is not None, "No stack definition in Function" args = function.resolve(self.args) - if not (isinstance(args, six.string_types)): + if not (isinstance(args, str)): raise TypeError(_('Argument to "%s" must be a string') % self.fn_name) @@ -603,19 +603,19 @@ class Join(function.Function): strings = function.resolve(self._strings) if strings is None: strings = [] - if (isinstance(strings, six.string_types) or + if (isinstance(strings, str) or not isinstance(strings, collections.Sequence)): raise TypeError(_('"%s" must operate on a list') % self.fn_name) delim = function.resolve(self._delim) - if not isinstance(delim, six.string_types): + if not isinstance(delim, str): raise TypeError(_('"%s" delimiter must be a string') % self.fn_name) def ensure_string(s): if s is None: return '' - if not isinstance(s, six.string_types): + if not isinstance(s, str): raise TypeError( _('Items to join must be strings not %s' ) % (repr(s)[:200])) @@ -668,7 +668,7 @@ class JoinMultiple(function.Function): strings = [] for jl in r_joinlists: if jl: - if (isinstance(jl, six.string_types) or + if (isinstance(jl, str) or not isinstance(jl, collections.Sequence)): raise TypeError(_('"%s" must operate on ' 'a list') % self.fn_name) @@ -676,7 +676,7 @@ class JoinMultiple(function.Function): strings += jl delim = function.resolve(self._delim) - if not isinstance(delim, six.string_types): + if not isinstance(delim, str): raise TypeError(_('"%s" delimiter must be a string') % self.fn_name) @@ -685,7 +685,7 @@ class JoinMultiple(function.Function): ) % (repr(s)[:200]) if s is None: return '' - elif isinstance(s, six.string_types): + elif isinstance(s, str): return s elif isinstance(s, (collections.Mapping, collections.Sequence)): try: @@ -801,7 +801,7 @@ class MapReplace(function.Function): repl_keys = ensure_map(repl_map.get('keys', {})) repl_values = ensure_map(repl_map.get('values', {})) ret_map = {} - for k, v in six.iteritems(in_map): + for k, v in in_map.items(): key = repl_keys.get(k) if key is None: key = k @@ -930,12 +930,12 @@ class Repeat(function.Function): def _valid_arg(self, arg): if not (isinstance(arg, (collections.Sequence, function.Function)) and - not isinstance(arg, six.string_types)): + not isinstance(arg, str)): raise TypeError(_('The values of the "for_each" argument to ' '"%s" must be lists') % self.fn_name) def _do_replacement(self, keys, values, template): - if isinstance(template, six.string_types): + if isinstance(template, str): for (key, value) in zip(keys, values): template = template.replace(key, value) return template @@ -951,7 +951,7 @@ class Repeat(function.Function): def result(self): for_each = function.resolve(self._for_each) - keys, lists = six.moves.zip(*for_each.items()) + keys, lists = zip(*for_each.items()) # use empty list for references(None) else validation will fail value_lens = [] @@ -970,7 +970,7 @@ class Repeat(function.Function): 'loop.') % self.fn_name) template = function.resolve(self._template) - iter_func = itertools.product if self._nested_loop else six.moves.zip + iter_func = itertools.product if self._nested_loop else zip return [self._do_replacement(keys, replacements, template) for replacements in iter_func(*values)] @@ -996,7 +996,7 @@ class RepeatWithMap(Repeat): if not (isinstance(arg, (collections.Sequence, collections.Mapping, function.Function)) and - not isinstance(arg, six.string_types)): + not isinstance(arg, str)): raise TypeError(_('The values of the "for_each" argument to ' '"%s" must be lists or maps') % self.fn_name) @@ -1067,7 +1067,7 @@ class Digest(function.Function): def validate_usage(self, args): if not (isinstance(args, list) and - all([isinstance(a, six.string_types) for a in args])): + all([isinstance(a, str) for a in args])): msg = _('Argument to function "%s" must be a list of strings') raise TypeError(msg % self.fn_name) @@ -1075,18 +1075,15 @@ class Digest(function.Function): msg = _('Function "%s" usage: ["", ""]') raise ValueError(msg % self.fn_name) - if six.PY3: - algorithms = hashlib.algorithms_available - else: - algorithms = hashlib.algorithms + algorithms = hashlib.algorithms_available if args[0].lower() not in algorithms: msg = _('Algorithm must be one of %s') - raise ValueError(msg % six.text_type(algorithms)) + raise ValueError(msg % str(algorithms)) def digest(self, algorithm, value): _hash = hashlib.new(algorithm) - _hash.update(six.b(value)) + _hash.update(value.encode('latin-1')) return _hash.hexdigest() @@ -1121,7 +1118,7 @@ class StrSplit(function.Function): 'example': example} self.fn_name = fn_name - if isinstance(args, (six.string_types, collections.Mapping)): + if isinstance(args, (str, collections.Mapping)): raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' 'should be: %(example)s') % self.fmt_data) @@ -1214,7 +1211,7 @@ class Yaql(function.Function): self._parse(self._expression) def _parse(self, expression): - if not isinstance(expression, six.string_types): + if not isinstance(expression, str): raise TypeError(_('The "expression" argument to %s must ' 'contain a string.') % self.fn_name) @@ -1282,7 +1279,7 @@ class If(function.Macro): try: if (not self.args or not isinstance(self.args, collections.Sequence) or - isinstance(self.args, six.string_types)): + isinstance(self.args, str)): raise ValueError() condition, value_if_true, value_if_false = self.args except ValueError: @@ -1311,7 +1308,7 @@ class ConditionBoolean(function.Function): def _check_args(self): if not (isinstance(self.args, collections.Sequence) and - not isinstance(self.args, six.string_types)): + not isinstance(self.args, str)): msg = _('Arguments to "%s" must be a list of conditions') raise ValueError(msg % self.fn_name) if not self.args or len(self.args) < 2: @@ -1406,7 +1403,7 @@ class Filter(function.Function): def _parse_args(self): if (not isinstance(self.args, collections.Sequence) or - isinstance(self.args, six.string_types)): + isinstance(self.args, str)): raise TypeError(_('Argument to "%s" must be a list') % self.fn_name) @@ -1476,7 +1473,7 @@ class MakeURL(function.Function): elif arg == self.PORT: port = args[arg] if not isinstance(port, function.Function): - if not isinstance(port, six.integer_types): + if not isinstance(port, int): try: port = int(port) except ValueError: @@ -1493,7 +1490,7 @@ class MakeURL(function.Function): 'must be in range 1-65535') % port) else: if not isinstance(args[arg], (function.Function, - six.string_types)): + str)): raise TypeError(_('The "%(arg)s" argument to ' '"%(fn_name)s" must be a string') % {'arg': arg, @@ -1544,7 +1541,7 @@ class MakeURL(function.Function): port = args.get(self.PORT, '') if port: yield ':' - yield six.text_type(port) + yield str(port) path = urlparse.quote(args.get(self.PATH, '')) @@ -1584,7 +1581,7 @@ class ListConcat(function.Function): def result(self): args = function.resolve(self.args) - if (isinstance(args, six.string_types) or + if (isinstance(args, str) or not isinstance(args, collections.Sequence)): raise TypeError(_('Incorrect arguments to "%(fn_name)s" ' 'should be: %(example)s') % self.fmt_data) @@ -1593,7 +1590,7 @@ class ListConcat(function.Function): if m is None: return [] elif (isinstance(m, collections.Sequence) and - not isinstance(m, six.string_types)): + not isinstance(m, str)): return m else: msg = _('Incorrect arguments: Items to concat must be lists. ' diff --git a/heat/engine/hot/template.py b/heat/engine/hot/template.py index f0f46a4ea6..f6edb51c7d 100644 --- a/heat/engine/hot/template.py +++ b/heat/engine/hot/template.py @@ -12,8 +12,6 @@ import functools -import six - from heat.common import exception from heat.common.i18n import _ from heat.engine.cfn import functions as cfn_funcs @@ -159,7 +157,7 @@ class HOTemplate20130523(template_common.CommonTemplate): if not attrs: raise exception.StackValidationFailed(message=message) try: - for attr, attr_value in six.iteritems(attrs): + for attr, attr_value in attrs.items(): if attr not in allowed_keys: raise KeyError(err_msg % attr) if sub_section not in attrs: @@ -183,7 +181,7 @@ class HOTemplate20130523(template_common.CommonTemplate): for name, attrs in sorted(data.items()): cfn_object = {} - for attr, attr_value in six.iteritems(attrs): + for attr, attr_value in attrs.items(): cfn_attr = mapping[attr] if cfn_attr is not None: cfn_object[cfn_attr] = attr_value @@ -201,18 +199,18 @@ class HOTemplate20130523(template_common.CommonTemplate): def get_section_name(self, section): cfn_to_hot_attrs = dict( - zip(six.itervalues(self._HOT_TO_CFN_ATTRS), - six.iterkeys(self._HOT_TO_CFN_ATTRS))) + zip(self._HOT_TO_CFN_ATTRS.values(), + self._HOT_TO_CFN_ATTRS.keys())) return cfn_to_hot_attrs.get(section, section) def param_schemata(self, param_defaults=None): parameter_section = self.t.get(self.PARAMETERS) or {} pdefaults = param_defaults or {} - for name, schema in six.iteritems(parameter_section): + for name, schema in parameter_section.items(): if name in pdefaults: parameter_section[name]['default'] = pdefaults[name] - params = six.iteritems(parameter_section) + params = parameter_section.items() return dict((name, self.param_schema_class.from_dict(name, schema)) for name, schema in params) @@ -228,7 +226,7 @@ class HOTemplate20130523(template_common.CommonTemplate): valid_keys = frozenset(self._RESOURCE_KEYS) def defns(): - for name, snippet in six.iteritems(resources): + for name, snippet in resources.items(): try: invalid_keys = set(snippet) - valid_keys if invalid_keys: @@ -239,7 +237,7 @@ class HOTemplate20130523(template_common.CommonTemplate): defn_data = dict(self._rsrc_defn_args(stack, name, snippet)) except (TypeError, ValueError, KeyError) as ex: - msg = six.text_type(ex) + msg = str(ex) raise exception.StackValidationFailed(message=msg) defn = rsrc_defn.ResourceDefinition(name, **defn_data) @@ -250,7 +248,7 @@ class HOTemplate20130523(template_common.CommonTemplate): enabled = conditions.is_enabled(cond_name) except ValueError as exc: path = [self.RESOURCES, name, self.RES_CONDITION] - message = six.text_type(exc) + message = str(exc) raise exception.StackValidationFailed(path=path, message=message) if not enabled: @@ -490,7 +488,7 @@ class HOTemplate20161014(HOTemplate20160408): tmpl, template_id, files, env) self._parser_condition_functions = {} - for n, f in six.iteritems(self.functions): + for n, f in self.functions.items(): if not f == hot_funcs.Removed: self._parser_condition_functions[n] = function.Invalid else: @@ -512,14 +510,14 @@ class HOTemplate20161014(HOTemplate20160408): yield ('external_id', self._parse_resource_field(self.RES_EXTERNAL_ID, - (six.string_types, + (str, function.Function), 'string', name, data, parse)) yield ('condition', self._parse_resource_field(self.RES_CONDITION, - (six.string_types, bool, + (str, bool, function.Function), 'string_or_boolean', name, data, parse_cond)) diff --git a/heat/engine/node_data.py b/heat/engine/node_data.py index 06580cb86f..da1c6e636e 100644 --- a/heat/engine/node_data.py +++ b/heat/engine/node_data.py @@ -11,8 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - class NodeData(object): """Data about a node in the graph, to be passed along to other nodes.""" @@ -53,8 +51,8 @@ class NodeData(object): """Return a dict of all available top-level attribute values.""" attrs = {k: v for k, v in self._attributes.items() - if isinstance(k, six.string_types)} - for v in six.itervalues(attrs): + if isinstance(k, str)} + for v in attrs.values(): if isinstance(v, Exception): raise v return attrs @@ -69,7 +67,7 @@ class NodeData(object): def attribute_names(self): """Iterate over valid top-level attribute names.""" for key in self._attributes: - if isinstance(key, six.string_types): + if isinstance(key, str): yield key else: yield key[0] @@ -80,7 +78,7 @@ class NodeData(object): This is the format that is serialised and stored in the database's SyncPoints. """ - for v in six.itervalues(self._attributes): + for v in self._attributes.values(): if isinstance(v, Exception): raise v diff --git a/heat/engine/output.py b/heat/engine/output.py index 1c12232cea..80a180db1b 100644 --- a/heat/engine/output.py +++ b/heat/engine/output.py @@ -13,7 +13,6 @@ import collections import copy -import six from heat.common import exception from heat.engine import function @@ -47,8 +46,7 @@ class OutputDefinition(object): if self._deps is None: try: required_resources = function.dependencies(self._value) - self._deps = set(six.moves.map(lambda rp: rp.name, - required_resources)) + self._deps = set(map(lambda rp: rp.name, required_resources)) except (exception.InvalidTemplateAttribute, exception.InvalidTemplateReference): # This output ain't gonna work anyway @@ -83,7 +81,7 @@ class OutputDefinition(object): if self._description is None: return 'No description given' - return six.text_type(self._description) + return str(self._description) def render_hot(self): def items(): diff --git a/heat/engine/parameters.py b/heat/engine/parameters.py index 168ac3e59c..0447738157 100644 --- a/heat/engine/parameters.py +++ b/heat/engine/parameters.py @@ -18,7 +18,6 @@ import itertools from oslo_serialization import jsonutils from oslo_utils import encodeutils from oslo_utils import strutils -import six from heat.common import exception from heat.common.i18n import _ @@ -87,8 +86,7 @@ class Schema(constr.Schema): message=_('Default must be a comma-delimited list ' 'string: %s') % err) elif self.type == self.LIST and isinstance(self.default, list): - default_value = [(six.text_type(x)) - for x in self.default] + default_value = [(str(x)) for x in self.default] try: self.validate_constraints(default_value, context, [constr.CustomConstraint]) @@ -184,7 +182,6 @@ class Schema(constr.Schema): return super(Schema, self).__getitem__(key) -@six.python_2_unicode_compatible class Parameter(object): """A template parameter.""" @@ -247,10 +244,10 @@ class Parameter(object): else: raise exception.UserParameterMissing(key=self.name) except exception.StackValidationFailed as ex: - msg = err_msg % dict(name=self.name, exp=six.text_type(ex)) + msg = err_msg % dict(name=self.name, exp=str(ex)) raise exception.StackValidationFailed(message=msg) except exception.InvalidSchemaError as ex: - msg = err_msg % dict(name=self.name, exp=six.text_type(ex)) + msg = err_msg % dict(name=self.name, exp=str(ex)) raise exception.InvalidSchemaError(message=msg) def value(self): @@ -302,13 +299,13 @@ class Parameter(object): @classmethod def _value_as_text(cls, value): - return six.text_type(value) + return str(value) def __str__(self): """Return a string representation of the parameter.""" value = self.value() if self.hidden(): - return six.text_type('******') + return str('******') else: return self._value_as_text(value) @@ -330,7 +327,7 @@ class NumberParam(Parameter): try: Schema.str_to_num(val) except (ValueError, TypeError) as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) self.schema.validate_value(val, context) def value(self): @@ -346,7 +343,7 @@ class BooleanParam(Parameter): try: strutils.bool_from_string(val, strict=True) except ValueError as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) self.schema.validate_value(val, context) def value(self): @@ -402,12 +399,12 @@ class CommaDelimitedListParam(ParsedParameter, collections.Sequence): def parse(self, value): # only parse when value is not already a list if isinstance(value, list): - return [(six.text_type(x)) for x in value] + return [(str(x)) for x in value] try: return param_utils.delim_string_to_list(value) except (KeyError, AttributeError) as err: message = _('Value must be a comma-delimited list string: %s') - raise ValueError(message % six.text_type(err)) + raise ValueError(message % str(err)) return value def value(self): @@ -432,7 +429,7 @@ class CommaDelimitedListParam(ParsedParameter, collections.Sequence): try: parsed = self.parse(val) except ValueError as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) self.schema.validate_value(parsed, context) @@ -448,7 +445,7 @@ class JsonParam(ParsedParameter): def parse(self, value): try: val = value - if not isinstance(val, six.string_types): + if not isinstance(val, str): # turn off oslo_serialization's clever to_primitive() val = jsonutils.dumps(val, default=None) if val: @@ -481,12 +478,11 @@ class JsonParam(ParsedParameter): try: parsed = self.parse(val) except ValueError as ex: - raise exception.StackValidationFailed(message=six.text_type(ex)) + raise exception.StackValidationFailed(message=str(ex)) self.schema.validate_value(parsed, context) -@six.add_metaclass(abc.ABCMeta) -class Parameters(collections.Mapping): +class Parameters(collections.Mapping, metaclass=abc.ABCMeta): """Parameters of a stack. The parameters of a stack, with type checking, defaults, etc. specified by @@ -513,7 +509,7 @@ class Parameters(collections.Mapping): schemata = self.tmpl.param_schemata() user_parameters = (user_parameter(si) for si in - six.iteritems(schemata)) + schemata.items()) pseudo_parameters = self._pseudo_parameters(stack_identifier) self.params = dict((p.name, @@ -534,7 +530,7 @@ class Parameters(collections.Mapping): """ self._validate_user_parameters() - for param in six.itervalues(self.params): + for param in self.params.values(): param.validate(validate_value, context) def __contains__(self, key): @@ -560,7 +556,7 @@ class Parameters(collections.Mapping): function) and return the resulting dictionary. """ return dict((n, func(p)) - for n, p in six.iteritems(self.params) if filter_func(p)) + for n, p in self.params.items() if filter_func(p)) def set_stack_id(self, stack_identifier): """Set the StackId pseudo parameter value.""" diff --git a/heat/engine/plugin_manager.py b/heat/engine/plugin_manager.py index 8dad27818f..e929c141c9 100644 --- a/heat/engine/plugin_manager.py +++ b/heat/engine/plugin_manager.py @@ -17,7 +17,6 @@ import sys from oslo_config import cfg from oslo_log import log -import six from heat.common import plugin_loader @@ -49,15 +48,14 @@ class PluginManager(object): 'heat.engine') def modules(): - pkg_modules = six.moves.map(plugin_loader.load_modules, - packages()) + pkg_modules = map(plugin_loader.load_modules, packages()) return itertools.chain.from_iterable(pkg_modules) self.modules = list(modules()) def map_to_modules(self, function): """Iterate over the results of calling a function on every module.""" - return six.moves.map(function, self.modules) + return map(function, self.modules) class PluginMapping(object): @@ -72,7 +70,7 @@ class PluginMapping(object): mappings provided by that module. Any other arguments passed will be passed to the mapping functions. """ - if isinstance(names, six.string_types): + if isinstance(names, str): names = [names] self.names = ['%s_mapping' % name for name in names] @@ -109,5 +107,5 @@ class PluginMapping(object): Mappings are returned as a list of (key, value) tuples. """ mod_dicts = plugin_manager.map_to_modules(self.load_from_module) - return itertools.chain.from_iterable(six.iteritems(d) for d + return itertools.chain.from_iterable(d.items() for d in mod_dicts) diff --git a/heat/engine/properties.py b/heat/engine/properties.py index e58516c9ef..d7e16efcd1 100644 --- a/heat/engine/properties.py +++ b/heat/engine/properties.py @@ -14,7 +14,6 @@ import collections from oslo_serialization import jsonutils -import six from heat.common import exception from heat.common.i18n import _ @@ -274,9 +273,9 @@ class Property(object): def _get_string(self, value): if value is None: value = self.has_default() and self.default() or '' - if not isinstance(value, six.string_types): + if not isinstance(value, str): if isinstance(value, (bool, int)): - value = six.text_type(value) + value = str(value) else: raise ValueError(_('Value must be a string; got %r') % value) return value @@ -306,24 +305,23 @@ class Property(object): # via a provider resource, in particular lists-of-dicts which # cannot be handled correctly via comma_delimited_list if self.schema.allow_conversion: - if isinstance(value, six.string_types): + if isinstance(value, str): return value elif isinstance(value, collections.Sequence): return jsonutils.dumps(value) raise TypeError(_('"%s" is not a map') % value) - return dict(self._get_children(six.iteritems(value), + return dict(self._get_children(value.items(), validate=validate, translation=translation)) def _get_list(self, value, validate=False, translation=None): if value is None: value = self.has_default() and self.default() or [] - if self.schema.allow_conversion and isinstance(value, - six.string_types): + if self.schema.allow_conversion and isinstance(value, str): value = param_utils.delim_string_to_list(value) if (not isinstance(value, collections.Sequence) or - isinstance(value, six.string_types)): + isinstance(value, str)): raise TypeError(_('"%s" is not a list') % repr(value)) return [v[1] for v in self._get_children(enumerate(value), @@ -341,7 +339,7 @@ class Property(object): value = self.has_default() and self.default() or False if isinstance(value, bool): return value - if isinstance(value, six.string_types): + if isinstance(value, str): normalised = value.lower() if normalised not in ['true', 'false']: raise ValueError(_('"%s" is not a valid boolean') % normalised) @@ -432,7 +430,7 @@ class Properties(collections.Mapping): else: path = [key] raise exception.StackValidationFailed( - path=path, message=six.text_type(e)) + path=path, message=str(e)) # are there unimplemented Properties if not prop.implemented() and key in self.data: @@ -488,7 +486,7 @@ class Properties(collections.Mapping): # the resolver function could raise any number of exceptions, # so handle this generically except Exception as e: - raise ValueError(six.text_type(e)) + raise ValueError(str(e)) def _get_property_value(self, key, validate=False): if key not in self: @@ -658,7 +656,7 @@ class Properties(collections.Mapping): return {}, {} param_prop_defs = [param_prop_def_items(n, s, template_type) - for n, s in six.iteritems(schemata(schema)) + for n, s in schemata(schema).items() if s.implemented] param_items, prop_items = zip(*param_prop_defs) return dict(param_items), dict(prop_items)