summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Finucane <stephenfin@redhat.com>2021-02-01 09:57:55 +0000
committerStephen Finucane <stephenfin@redhat.com>2021-02-01 11:15:59 +0000
commit57e9754093eec986b60d86e527e41c74b001b30a (patch)
treec78226619aa8c6564fc2c9435143e8fc4a1aec5c
parent32f9014207d3a3fa1e248d372f9f1d59c876ee1c (diff)
downloadheat-57e9754093eec986b60d86e527e41c74b001b30a.tar.gz
Switch to collections.abc.*
The abstract base classes previously defined in 'collections' were moved to 'collections.abc' in 3.3. The aliases will be removed in 3.10. Preempt this change now with a simple find-replace: $ ag -l 'collections.($TYPES)' | \ xargs sed -i 's/\(collections\)\.\($TYPES\)/\1.abc.\2/g' Where $TYPES is the list of moved ABCs from [1]. [1] https://docs.python.org/3/library/collections.abc.html Change-Id: Ia282479bb1d466bd2189ebb21b51d91e89b9581e Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
-rw-r--r--doc/source/contributor/pluginguide.rst8
-rw-r--r--heat/common/environment_util.py6
-rw-r--r--heat/common/identifier.py2
-rw-r--r--heat/engine/api.py2
-rw-r--r--heat/engine/attributes.py10
-rw-r--r--heat/engine/cfn/functions.py12
-rw-r--r--heat/engine/clients/os/nova.py4
-rw-r--r--heat/engine/conditions.py2
-rw-r--r--heat/engine/constraints.py8
-rw-r--r--heat/engine/environment.py8
-rw-r--r--heat/engine/function.py20
-rw-r--r--heat/engine/hot/functions.py73
-rw-r--r--heat/engine/parameters.py4
-rw-r--r--heat/engine/plugin_manager.py2
-rw-r--r--heat/engine/properties.py8
-rw-r--r--heat/engine/resource.py2
-rw-r--r--heat/engine/resources/openstack/heat/resource_group.py8
-rw-r--r--heat/engine/resources/openstack/heat/structured_config.py4
-rw-r--r--heat/engine/resources/openstack/neutron/l2_gateway.py4
-rw-r--r--heat/engine/resources/wait_condition.py2
-rw-r--r--heat/engine/rsrc_defn.py12
-rw-r--r--heat/engine/software_config_io.py12
-rw-r--r--heat/engine/stack.py2
-rw-r--r--heat/engine/template.py6
-rw-r--r--heat/engine/template_common.py12
-rw-r--r--heat/engine/template_files.py2
-rw-r--r--heat/tests/openstack/nova/test_server.py2
-rw-r--r--heat/tests/test_resource.py2
28 files changed, 123 insertions, 116 deletions
diff --git a/doc/source/contributor/pluginguide.rst b/doc/source/contributor/pluginguide.rst
index d8d43345a..7177c4b38 100644
--- a/doc/source/contributor/pluginguide.rst
+++ b/doc/source/contributor/pluginguide.rst
@@ -248,7 +248,7 @@ the end user.
*AllowedValues(allowed, description)*:
Lists the allowed values. ``allowed`` must be a
- ``collections.Sequence`` or ``basestring``. Applicable to all types
+ ``collections.abc.Sequence`` or ``basestring``. Applicable to all types
of value except MAP.
*Length(min, max, description)*:
@@ -480,16 +480,16 @@ that updates require the engine to delete and re-create the resource
Update the physical resources using updated information.
:param json_snippet: the resource definition from the updated template
- :type json_snippet: collections.Mapping
+ :type json_snippet: collections.abc.Mapping
:param tmpl_diff: values in the updated definition that have changed
with respect to the original template definition.
- :type tmpl_diff: collections.Mapping
+ :type tmpl_diff: collections.abc.Mapping
:param prop_diff: property values that are different between the original
definition and the updated definition; keys are
property names and values are the new values. Deleted or
properties that were originally present but now absent
have values of ``None``
- :type prop_diff: collections.Mapping
+ :type prop_diff: collections.abc.Mapping
*Note* Before calling ``handle_update`` we check whether need to replace
the resource, especially for resource in ``*_FAILED`` state, there is a
diff --git a/heat/common/environment_util.py b/heat/common/environment_util.py
index abf081bd0..8a6ed4393 100644
--- a/heat/common/environment_util.py
+++ b/heat/common/environment_util.py
@@ -57,10 +57,10 @@ def merge_map(old, new, deep_merge=False):
if v is not None:
if not deep_merge:
old[k] = v
- elif isinstance(v, collections.Mapping):
+ elif isinstance(v, collections.abc.Mapping):
old_v = old.get(k)
old[k] = merge_map(old_v, v, deep_merge) if old_v else v
- elif (isinstance(v, collections.Sequence) and
+ elif (isinstance(v, collections.abc.Sequence) and
not isinstance(v, str)):
old_v = old.get(k)
old[k] = merge_list(old_v, v) if old_v else v
@@ -79,7 +79,7 @@ def parse_param(p_val, p_schema):
p_val = jsonutils.dumps(p_val)
if p_val:
return jsonutils.loads(p_val)
- elif not isinstance(p_val, collections.Sequence):
+ elif not isinstance(p_val, collections.abc.Sequence):
raise ValueError()
except (ValueError, TypeError) as err:
msg = _("Invalid parameter in environment %s.") % str(err)
diff --git a/heat/common/identifier.py b/heat/common/identifier.py
index 46323b25d..02628b478 100644
--- a/heat/common/identifier.py
+++ b/heat/common/identifier.py
@@ -20,7 +20,7 @@ from urllib import parse as urlparse
from heat.common.i18n import _
-class HeatIdentifier(collections.Mapping):
+class HeatIdentifier(collections.abc.Mapping):
FIELDS = (
TENANT, STACK_NAME, STACK_ID, PATH
diff --git a/heat/engine/api.py b/heat/engine/api.py
index ceb881470..35edaff6e 100644
--- a/heat/engine/api.py
+++ b/heat/engine/api.py
@@ -292,7 +292,7 @@ def format_resource_attributes(resource, with_attr=None):
if 'show' in resolver:
show_attr = resolve('show', resolver)
# check if 'show' resolved to dictionary. so it's not None
- if isinstance(show_attr, collections.Mapping):
+ if isinstance(show_attr, collections.abc.Mapping):
for a in with_attr:
if a not in show_attr:
show_attr[a] = resolve(a, resolver)
diff --git a/heat/engine/attributes.py b/heat/engine/attributes.py
index 26c7a9676..eb2c5667f 100644
--- a/heat/engine/attributes.py
+++ b/heat/engine/attributes.py
@@ -138,7 +138,7 @@ BASE_ATTRIBUTES = (SHOW_ATTR, ) = ('show', )
ALL_ATTRIBUTES = '*'
-class Attributes(collections.Mapping):
+class Attributes(collections.abc.Mapping):
"""Models a collection of Resource Attributes."""
def __init__(self, res_name, schema, resolver):
@@ -212,14 +212,14 @@ class Attributes(collections.Mapping):
{'name': attrib.name,
'att_type': attrib.schema.STRING})
elif attrib.schema.type == attrib.schema.LIST:
- if (not isinstance(value, collections.Sequence)
+ if (not isinstance(value, collections.abc.Sequence)
or isinstance(value, str)):
LOG.warning("Attribute %(name)s is not of type "
"%(att_type)s",
{'name': attrib.name,
'att_type': attrib.schema.LIST})
elif attrib.schema.type == attrib.schema.MAP:
- if not isinstance(value, collections.Mapping):
+ if not isinstance(value, collections.abc.Mapping):
LOG.warning("Attribute %(name)s is not of type "
"%(att_type)s",
{'name': attrib.name,
@@ -307,8 +307,8 @@ def select_from_attribute(attribute_value, path):
:returns: the selected attribute component value.
"""
def get_path_component(collection, key):
- if not isinstance(collection, (collections.Mapping,
- collections.Sequence)):
+ if not isinstance(collection, (collections.abc.Mapping,
+ collections.abc.Sequence)):
raise TypeError(_("Can't traverse attribute path"))
if not isinstance(key, (str, int)):
diff --git a/heat/engine/cfn/functions.py b/heat/engine/cfn/functions.py
index ccd9c4d47..f037eec0c 100644
--- a/heat/engine/cfn/functions.py
+++ b/heat/engine/cfn/functions.py
@@ -168,7 +168,7 @@ class Select(function.Function):
'err': json_ex}
raise ValueError(_('"%(fn_name)s": %(err)s') % fmt_data)
- if isinstance(strings, collections.Mapping):
+ if isinstance(strings, collections.abc.Mapping):
if not isinstance(index, str):
raise TypeError(_('Index to "%s" must be a string') %
self.fn_name)
@@ -179,7 +179,7 @@ class Select(function.Function):
except (ValueError, TypeError):
pass
- if (isinstance(strings, collections.Sequence) and
+ if (isinstance(strings, collections.abc.Sequence) and
not isinstance(strings, str)):
if not isinstance(index, int):
raise TypeError(_('Index to "%s" must be an integer') %
@@ -229,7 +229,7 @@ class Split(function.Function):
fmt_data = {'fn_name': self.fn_name,
'example': example}
- if isinstance(self.args, (str, collections.Mapping)):
+ if isinstance(self.args, (str, collections.abc.Mapping)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
@@ -278,7 +278,7 @@ class Replace(hot_funcs.Replace):
fmt_data = {'fn_name': self.fn_name,
'example': example}
- if isinstance(self.args, (str, collections.Mapping)):
+ if isinstance(self.args, (str, collections.abc.Mapping)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % fmt_data)
@@ -350,7 +350,7 @@ class MemberListToMap(function.Function):
def result(self):
member_list = function.resolve(self._list)
- if not isinstance(member_list, collections.Iterable):
+ if not isinstance(member_list, collections.abc.Iterable):
raise TypeError(_('Member list must be a list'))
def item(s):
@@ -428,7 +428,7 @@ class Not(hot_funcs.Not):
msg = _('Arguments to "%s" must be of the form: '
'[condition]') % self.fn_name
if (not self.args or
- not isinstance(self.args, collections.Sequence) or
+ not isinstance(self.args, collections.abc.Sequence) or
isinstance(self.args, str)):
raise ValueError(msg)
if len(self.args) != 1:
diff --git a/heat/engine/clients/os/nova.py b/heat/engine/clients/os/nova.py
index c634388ad..bb3a8adde 100644
--- a/heat/engine/clients/os/nova.py
+++ b/heat/engine/clients/os/nova.py
@@ -596,7 +596,7 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
def meta_serialize(self, metadata):
"""Serialize non-string metadata values before sending them to Nova."""
- if not isinstance(metadata, collections.Mapping):
+ if not isinstance(metadata, collections.abc.Mapping):
raise exception.StackValidationFailed(message=_(
"nova server metadata needs to be a Map."))
@@ -647,7 +647,7 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
"""
nc = self.client
- class ConsoleUrls(collections.Mapping):
+ class ConsoleUrls(collections.abc.Mapping):
def __init__(self, server):
self.console_method = server.get_console_url
self.support_console_types = ['novnc', 'xvpvnc',
diff --git a/heat/engine/conditions.py b/heat/engine/conditions.py
index 1e3d7e6a4..73e51f485 100644
--- a/heat/engine/conditions.py
+++ b/heat/engine/conditions.py
@@ -24,7 +24,7 @@ _in_progress = object()
class Conditions(object):
def __init__(self, conditions_dict):
- assert isinstance(conditions_dict, collections.Mapping)
+ assert isinstance(conditions_dict, collections.abc.Mapping)
self._conditions = conditions_dict
self._resolved = {}
diff --git a/heat/engine/constraints.py b/heat/engine/constraints.py
index f6ca11e3e..dfed2c969 100644
--- a/heat/engine/constraints.py
+++ b/heat/engine/constraints.py
@@ -36,7 +36,7 @@ MEMOIZE = core.get_memoization_decorator(conf=cfg.CONF,
LOG = log.getLogger(__name__)
-class Schema(collections.Mapping):
+class Schema(collections.abc.Mapping):
"""Schema base class for validating properties or parameters.
Schema objects are serializable to dictionaries following a superset of
@@ -251,7 +251,7 @@ class Schema(collections.Mapping):
return self._len
-class AnyIndexDict(collections.Mapping):
+class AnyIndexDict(collections.abc.Mapping):
"""A Mapping that returns the same value for any integer index.
Used for storing the schema for a list. When converted to a dictionary,
@@ -276,7 +276,7 @@ class AnyIndexDict(collections.Mapping):
return 1
-class Constraint(collections.Mapping):
+class Constraint(collections.abc.Mapping):
"""Parent class for constraints on allowable values for a Property.
Constraints are serializable to dictionaries following the HOT input
@@ -540,7 +540,7 @@ class AllowedValues(Constraint):
def __init__(self, allowed, description=None):
super(AllowedValues, self).__init__(description)
- if (not isinstance(allowed, collections.Sequence) or
+ if (not isinstance(allowed, collections.abc.Sequence) or
isinstance(allowed, str)):
raise exception.InvalidSchemaError(
message=_('AllowedValues must be a list'))
diff --git a/heat/engine/environment.py b/heat/engine/environment.py
index 8defdf31f..f425e3c2c 100644
--- a/heat/engine/environment.py
+++ b/heat/engine/environment.py
@@ -55,7 +55,7 @@ def is_hook_definition(key, value):
if key == 'hooks':
if isinstance(value, str):
is_valid_hook = valid_hook_type(value)
- elif isinstance(value, collections.Sequence):
+ elif isinstance(value, collections.abc.Sequence):
is_valid_hook = all(valid_hook_type(hook) for hook in value)
if not is_valid_hook:
@@ -72,7 +72,7 @@ def is_valid_restricted_action(key, value):
if key == 'restricted_actions':
if isinstance(value, str):
valid_action = valid_restricted_actions(value)
- elif isinstance(value, collections.Sequence):
+ elif isinstance(value, collections.abc.Sequence):
valid_action = all(valid_restricted_actions(
action) for action in value)
@@ -397,7 +397,7 @@ class ResourceRegistry(object):
actions = resource['restricted_actions']
if isinstance(actions, str):
restricted_actions.add(actions)
- elif isinstance(actions, collections.Sequence):
+ elif isinstance(actions, collections.abc.Sequence):
restricted_actions |= set(actions)
return restricted_actions
@@ -433,7 +433,7 @@ class ResourceRegistry(object):
if isinstance(hooks, str):
if hook == hooks:
return True
- elif isinstance(hooks, collections.Sequence):
+ elif isinstance(hooks, collections.abc.Sequence):
if hook in hooks:
return True
return False
diff --git a/heat/engine/function.py b/heat/engine/function.py
index f2e68e1cb..2169e2194 100644
--- a/heat/engine/function.py
+++ b/heat/engine/function.py
@@ -266,12 +266,12 @@ def resolve(snippet, nullable=False):
result = None
return result
- if isinstance(snippet, collections.Mapping):
+ if isinstance(snippet, collections.abc.Mapping):
return dict(filter(_non_null_item,
((k, resolve(v, nullable=True))
for k, v in snippet.items())))
elif (not isinstance(snippet, str) and
- isinstance(snippet, collections.Iterable)):
+ isinstance(snippet, collections.abc.Iterable)):
return list(filter(_non_null_value,
(resolve(v, nullable=True) for v in snippet)))
@@ -293,11 +293,11 @@ def validate(snippet, path=None):
raise exception.StackValidationFailed(
path=path + [snippet.fn_name],
message=str(e))
- elif isinstance(snippet, collections.Mapping):
+ elif isinstance(snippet, collections.abc.Mapping):
for k, v in snippet.items():
validate(v, path + [k])
elif (not isinstance(snippet, str) and
- isinstance(snippet, collections.Iterable)):
+ isinstance(snippet, collections.abc.Iterable)):
basepath = list(path)
parent = basepath.pop() if basepath else ''
for i, v in enumerate(snippet):
@@ -314,7 +314,7 @@ def dependencies(snippet, path=''):
if isinstance(snippet, Function):
return snippet.dependencies(path)
- elif isinstance(snippet, collections.Mapping):
+ elif isinstance(snippet, collections.abc.Mapping):
def mkpath(key):
return '.'.join([path, str(key)])
@@ -323,7 +323,7 @@ def dependencies(snippet, path=''):
return itertools.chain.from_iterable(deps)
elif (not isinstance(snippet, str) and
- isinstance(snippet, collections.Iterable)):
+ isinstance(snippet, collections.abc.Iterable)):
def mkpath(idx):
return ''.join([path, '[%d]' % idx])
@@ -348,11 +348,11 @@ def dep_attrs(snippet, resource_name):
if isinstance(snippet, Function):
return snippet.dep_attrs(resource_name)
- elif isinstance(snippet, collections.Mapping):
+ elif isinstance(snippet, collections.abc.Mapping):
attrs = (dep_attrs(val, resource_name) for val in snippet.values())
return itertools.chain.from_iterable(attrs)
elif (not isinstance(snippet, str) and
- isinstance(snippet, collections.Iterable)):
+ isinstance(snippet, collections.abc.Iterable)):
attrs = (dep_attrs(value, resource_name) for value in snippet)
return itertools.chain.from_iterable(attrs)
return []
@@ -371,11 +371,11 @@ def all_dep_attrs(snippet):
if isinstance(snippet, Function):
return snippet.all_dep_attrs()
- elif isinstance(snippet, collections.Mapping):
+ elif isinstance(snippet, collections.abc.Mapping):
res_attrs = (all_dep_attrs(value) for value in snippet.values())
return itertools.chain.from_iterable(res_attrs)
elif (not isinstance(snippet, str) and
- isinstance(snippet, collections.Iterable)):
+ isinstance(snippet, collections.abc.Iterable)):
res_attrs = (all_dep_attrs(value) for value in snippet)
return itertools.chain.from_iterable(res_attrs)
return []
diff --git a/heat/engine/hot/functions.py b/heat/engine/hot/functions.py
index a700ff5fe..33b75f4e4 100644
--- a/heat/engine/hot/functions.py
+++ b/heat/engine/hot/functions.py
@@ -79,7 +79,7 @@ class GetParam(function.Function):
if isinstance(args, str):
param_name = args
path_components = []
- elif isinstance(args, collections.Sequence):
+ elif isinstance(args, collections.abc.Sequence):
param_name = args[0]
path_components = args[1:]
else:
@@ -96,15 +96,15 @@ class GetParam(function.Function):
raise exception.UserParameterMissing(key=param_name)
def get_path_component(collection, key):
- if not isinstance(collection, (collections.Mapping,
- collections.Sequence)):
+ if not isinstance(collection, (collections.abc.Mapping,
+ collections.abc.Sequence)):
raise TypeError(_('"%s" can\'t traverse path') % self.fn_name)
if not isinstance(key, (str, int)):
raise TypeError(_('Path components in "%s" '
'must be strings') % self.fn_name)
- if isinstance(collection, collections.Sequence
+ if isinstance(collection, collections.abc.Sequence
) and isinstance(key, str):
try:
key = int(key)
@@ -167,7 +167,7 @@ class GetAttThenSelect(function.Function):
self._path_components) = self._parse_args()
def _parse_args(self):
- if (not isinstance(self.args, collections.Sequence) or
+ if (not isinstance(self.args, collections.abc.Sequence) or
isinstance(self.args, str)):
raise TypeError(_('Argument to "%s" must be a list') %
self.fn_name)
@@ -314,7 +314,7 @@ class GetAttAllAttributes(GetAtt):
'forms: [resource_name] or '
'[resource_name, attribute, (path), ...]'
) % self.fn_name)
- elif isinstance(self.args, collections.Sequence):
+ elif isinstance(self.args, collections.abc.Sequence):
if len(self.args) > 1:
return super(GetAttAllAttributes, self)._parse_args()
else:
@@ -372,12 +372,12 @@ class Replace(function.Function):
self._mapping, self._string = self._parse_args()
if not isinstance(self._mapping,
- (collections.Mapping, function.Function)):
+ (collections.abc.Mapping, function.Function)):
raise TypeError(_('"%s" parameters must be a mapping') %
self.fn_name)
def _parse_args(self):
- if not isinstance(self.args, collections.Mapping):
+ if not isinstance(self.args, collections.abc.Mapping):
raise TypeError(_('Arguments to "%s" must be a map') %
self.fn_name)
@@ -418,7 +418,7 @@ class Replace(function.Function):
if not isinstance(template, str):
raise TypeError(_('"%s" template must be a string') % self.fn_name)
- if not isinstance(mapping, collections.Mapping):
+ if not isinstance(mapping, collections.abc.Mapping):
raise TypeError(_('"%s" params must be a map') % self.fn_name)
def replace(strings, keys):
@@ -490,9 +490,10 @@ class ReplaceJson(Replace):
else:
_raise_empty_param_value_error()
- if not isinstance(value, (str, int,
- float, bool)):
- if isinstance(value, (collections.Mapping, collections.Sequence)):
+ if not isinstance(value, (str, int, float, bool)):
+ if isinstance(
+ value, (collections.abc.Mapping, collections.abc.Sequence)
+ ):
if not self._allow_empty_value and len(value) == 0:
_raise_empty_param_value_error()
try:
@@ -604,7 +605,7 @@ class Join(function.Function):
if strings is None:
strings = []
if (isinstance(strings, str) or
- not isinstance(strings, collections.Sequence)):
+ not isinstance(strings, collections.abc.Sequence)):
raise TypeError(_('"%s" must operate on a list') % self.fn_name)
delim = function.resolve(self._delim)
@@ -669,7 +670,7 @@ class JoinMultiple(function.Function):
for jl in r_joinlists:
if jl:
if (isinstance(jl, str) or
- not isinstance(jl, collections.Sequence)):
+ not isinstance(jl, collections.abc.Sequence)):
raise TypeError(_('"%s" must operate on '
'a list') % self.fn_name)
@@ -687,7 +688,9 @@ class JoinMultiple(function.Function):
return ''
elif isinstance(s, str):
return s
- elif isinstance(s, (collections.Mapping, collections.Sequence)):
+ elif isinstance(
+ s, (collections.abc.Mapping, collections.abc.Sequence)
+ ):
try:
return jsonutils.dumps(s, default=None, sort_keys=True)
except TypeError:
@@ -725,14 +728,14 @@ class MapMerge(function.Function):
def result(self):
args = function.resolve(self.args)
- if not isinstance(args, collections.Sequence):
+ if not isinstance(args, collections.abc.Sequence):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % self.fmt_data)
def ensure_map(m):
if m is None:
return {}
- elif isinstance(m, collections.Mapping):
+ elif isinstance(m, collections.abc.Mapping):
return m
else:
msg = _('Incorrect arguments: Items to merge must be maps.')
@@ -776,7 +779,7 @@ class MapReplace(function.Function):
def ensure_map(m):
if m is None:
return {}
- elif isinstance(m, collections.Mapping):
+ elif isinstance(m, collections.abc.Mapping):
return m
else:
msg = (_('Incorrect arguments: to "%(fn_name)s", arguments '
@@ -901,7 +904,7 @@ class Repeat(function.Function):
self._parse_args()
def _parse_args(self):
- if not isinstance(self.args, collections.Mapping):
+ if not isinstance(self.args, collections.abc.Mapping):
raise TypeError(_('Arguments to "%s" must be a map') %
self.fn_name)
@@ -923,12 +926,12 @@ class Repeat(function.Function):
super(Repeat, self).validate()
if not isinstance(self._for_each, function.Function):
- if not isinstance(self._for_each, collections.Mapping):
+ if not isinstance(self._for_each, collections.abc.Mapping):
raise TypeError(_('The "for_each" argument to "%s" must '
'contain a map') % self.fn_name)
def _valid_arg(self, arg):
- if not (isinstance(arg, (collections.Sequence,
+ if not (isinstance(arg, (collections.abc.Sequence,
function.Function)) and
not isinstance(arg, str)):
raise TypeError(_('The values of the "for_each" argument to '
@@ -939,10 +942,10 @@ class Repeat(function.Function):
for (key, value) in zip(keys, values):
template = template.replace(key, value)
return template
- elif isinstance(template, collections.Sequence):
+ elif isinstance(template, collections.abc.Sequence):
return [self._do_replacement(keys, values, elem)
for elem in template]
- elif isinstance(template, collections.Mapping):
+ elif isinstance(template, collections.abc.Mapping):
return dict((self._do_replacement(keys, values, k),
self._do_replacement(keys, values, v))
for (k, v) in template.items())
@@ -993,8 +996,8 @@ class RepeatWithMap(Repeat):
"""
def _valid_arg(self, arg):
- if not (isinstance(arg, (collections.Sequence,
- collections.Mapping,
+ if not (isinstance(arg, (collections.abc.Sequence,
+ collections.abc.Mapping,
function.Function)) and
not isinstance(arg, str)):
raise TypeError(_('The values of the "for_each" argument to '
@@ -1118,7 +1121,7 @@ class StrSplit(function.Function):
'example': example}
self.fn_name = fn_name
- if isinstance(args, (str, collections.Mapping)):
+ if isinstance(args, (str, collections.abc.Mapping)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % self.fmt_data)
@@ -1188,7 +1191,7 @@ class Yaql(function.Function):
def __init__(self, stack, fn_name, args):
super(Yaql, self).__init__(stack, fn_name, args)
- if not isinstance(self.args, collections.Mapping):
+ if not isinstance(self.args, collections.abc.Mapping):
raise TypeError(_('Arguments to "%s" must be a map.') %
self.fn_name)
@@ -1281,7 +1284,7 @@ class If(function.Macro):
def parse_args(self, parse_func):
try:
if (not self.args or
- not isinstance(self.args, collections.Sequence) or
+ not isinstance(self.args, collections.abc.Sequence) or
isinstance(self.args, str)):
raise ValueError()
condition, value_if_true, value_if_false = self._read_args()
@@ -1344,7 +1347,7 @@ class ConditionBoolean(function.Function):
self._check_args()
def _check_args(self):
- if not (isinstance(self.args, collections.Sequence) and
+ if not (isinstance(self.args, collections.abc.Sequence) and
not isinstance(self.args, str)):
msg = _('Arguments to "%s" must be a list of conditions')
raise ValueError(msg % self.fn_name)
@@ -1439,7 +1442,7 @@ class Filter(function.Function):
self._values, self._sequence = self._parse_args()
def _parse_args(self):
- if (not isinstance(self.args, collections.Sequence) or
+ if (not isinstance(self.args, collections.abc.Sequence) or
isinstance(self.args, str)):
raise TypeError(_('Argument to "%s" must be a list') %
self.fn_name)
@@ -1501,7 +1504,7 @@ class MakeURL(function.Function):
if arg in args:
if arg == self.QUERY:
if not isinstance(args[arg], (function.Function,
- collections.Mapping)):
+ collections.abc.Mapping)):
raise TypeError(_('The "%(arg)s" argument to '
'"%(fn_name)s" must be a map') %
{'arg': arg,
@@ -1536,7 +1539,7 @@ class MakeURL(function.Function):
def validate(self):
super(MakeURL, self).validate()
- if not isinstance(self.args, collections.Mapping):
+ if not isinstance(self.args, collections.abc.Mapping):
raise TypeError(_('The arguments to "%s" must '
'be a map') % self.fn_name)
@@ -1619,14 +1622,14 @@ class ListConcat(function.Function):
args = function.resolve(self.args)
if (isinstance(args, str) or
- not isinstance(args, collections.Sequence)):
+ not isinstance(args, collections.abc.Sequence)):
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
'should be: %(example)s') % self.fmt_data)
def ensure_list(m):
if m is None:
return []
- elif (isinstance(m, collections.Sequence) and
+ elif (isinstance(m, collections.abc.Sequence) and
not isinstance(m, str)):
return m
else:
@@ -1691,7 +1694,7 @@ class Contains(function.Function):
resolved_value = function.resolve(self.value)
resolved_sequence = function.resolve(self.sequence)
- if not isinstance(resolved_sequence, collections.Sequence):
+ if not isinstance(resolved_sequence, collections.abc.Sequence):
raise TypeError(_('Second argument to "%s" should be '
'a sequence.') % self.fn_name)
diff --git a/heat/engine/parameters.py b/heat/engine/parameters.py
index 4aced043b..cb05c6ed7 100644
--- a/heat/engine/parameters.py
+++ b/heat/engine/parameters.py
@@ -388,7 +388,7 @@ class ParsedParameter(Parameter):
return self._parsed
-class CommaDelimitedListParam(ParsedParameter, collections.Sequence):
+class CommaDelimitedListParam(ParsedParameter, collections.abc.Sequence):
"""A template parameter of type "CommaDelimitedList"."""
__slots__ = tuple()
@@ -481,7 +481,7 @@ class JsonParam(ParsedParameter):
self.schema.validate_value(parsed, context)
-class Parameters(collections.Mapping, metaclass=abc.ABCMeta):
+class Parameters(collections.abc.Mapping, metaclass=abc.ABCMeta):
"""Parameters of a stack.
The parameters of a stack, with type checking, defaults, etc. specified by
diff --git a/heat/engine/plugin_manager.py b/heat/engine/plugin_manager.py
index e929c141c..cde1591aa 100644
--- a/heat/engine/plugin_manager.py
+++ b/heat/engine/plugin_manager.py
@@ -93,7 +93,7 @@ class PluginMapping(object):
'from %(module)s', fmt_data)
raise
else:
- if isinstance(mapping_dict, collections.Mapping):
+ if isinstance(mapping_dict, collections.abc.Mapping):
return mapping_dict
elif mapping_dict is not None:
LOG.error('Invalid type for %(mapping_name)s '
diff --git a/heat/engine/properties.py b/heat/engine/properties.py
index a3f955d86..2d9623baa 100644
--- a/heat/engine/properties.py
+++ b/heat/engine/properties.py
@@ -300,14 +300,14 @@ class Property(object):
def _get_map(self, value, validate=False, translation=None):
if value is None:
value = self.default() if self.has_default() else {}
- if not isinstance(value, collections.Mapping):
+ if not isinstance(value, collections.abc.Mapping):
# This is to handle passing Lists via Json parameters exposed
# 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, str):
return value
- elif isinstance(value, collections.Sequence):
+ elif isinstance(value, collections.abc.Sequence):
return jsonutils.dumps(value)
raise TypeError(_('"%s" is not a map') % value)
@@ -320,7 +320,7 @@ class Property(object):
value = self.has_default() and self.default() or []
if self.schema.allow_conversion and isinstance(value, str):
value = param_utils.delim_string_to_list(value)
- if (not isinstance(value, collections.Sequence) or
+ if (not isinstance(value, collections.abc.Sequence) or
isinstance(value, str)):
raise TypeError(_('"%s" is not a list') % repr(value))
@@ -376,7 +376,7 @@ def _default_resolver(d, nullable=False):
return d
-class Properties(collections.Mapping):
+class Properties(collections.abc.Mapping):
def __init__(self, schema, data, resolver=_default_resolver,
parent_name=None,
diff --git a/heat/engine/resource.py b/heat/engine/resource.py
index e2f51e5c5..de9a708a8 100644
--- a/heat/engine/resource.py
+++ b/heat/engine/resource.py
@@ -1066,7 +1066,7 @@ class Resource(status.ResourceStatus):
refd_attrs |= get_dep_attrs(stk_defn.resource_definition(r_name)
for r_name in enabled_resources)
- subset_outputs = isinstance(in_outputs, collections.Iterable)
+ subset_outputs = isinstance(in_outputs, collections.abc.Iterable)
if subset_outputs or in_outputs:
if not subset_outputs:
in_outputs = stk_defn.enabled_output_names()
diff --git a/heat/engine/resources/openstack/heat/resource_group.py b/heat/engine/resources/openstack/heat/resource_group.py
index 85545bf84..48ef05ae9 100644
--- a/heat/engine/resources/openstack/heat/resource_group.py
+++ b/heat/engine/resources/openstack/heat/resource_group.py
@@ -610,12 +610,12 @@ class ResourceGroup(stack_resource.StackResource):
result = None
return result
- if isinstance(snippet, collections.Mapping):
+ if isinstance(snippet, collections.abc.Mapping):
return dict(filter(function._non_null_item,
((k, ignore_param_resolve(v, nullable=True))
for k, v in snippet.items())))
elif (not isinstance(snippet, str) and
- isinstance(snippet, collections.Iterable)):
+ isinstance(snippet, collections.abc.Iterable)):
return list(filter(function._non_null_value,
(ignore_param_resolve(v, nullable=True)
for v in snippet)))
@@ -646,9 +646,9 @@ class ResourceGroup(stack_resource.StackResource):
if isinstance(val, str):
return val.replace(repl_var, res_name)
- elif isinstance(val, collections.Mapping):
+ elif isinstance(val, collections.abc.Mapping):
return {k: recurse(v) for k, v in val.items()}
- elif isinstance(val, collections.Sequence):
+ elif isinstance(val, collections.abc.Sequence):
return [recurse(v) for v in val]
return val
diff --git a/heat/engine/resources/openstack/heat/structured_config.py b/heat/engine/resources/openstack/heat/structured_config.py
index a23bfceda..abcb676d6 100644
--- a/heat/engine/resources/openstack/heat/structured_config.py
+++ b/heat/engine/resources/openstack/heat/structured_config.py
@@ -166,7 +166,7 @@ class StructuredDeployment(sd.SoftwareDeployment):
input_key,
check_input_val=check_input_val)
- if isinstance(snippet, collections.Mapping):
+ if isinstance(snippet, collections.abc.Mapping):
fn_arg = StructuredDeployment.get_input_key_arg(snippet, input_key)
if fn_arg is not None:
return StructuredDeployment.get_input_key_value(fn_arg, inputs,
@@ -175,7 +175,7 @@ class StructuredDeployment(sd.SoftwareDeployment):
return dict((k, parse(v)) for k, v in snippet.items())
elif (not isinstance(snippet, str) and
- isinstance(snippet, collections.Iterable)):
+ isinstance(snippet, collections.abc.Iterable)):
return [parse(v) for v in snippet]
else:
return snippet
diff --git a/heat/engine/resources/openstack/neutron/l2_gateway.py b/heat/engine/resources/openstack/neutron/l2_gateway.py
index 08f877256..634ee81fc 100644
--- a/heat/engine/resources/openstack/neutron/l2_gateway.py
+++ b/heat/engine/resources/openstack/neutron/l2_gateway.py
@@ -106,10 +106,10 @@ class L2Gateway(neutron.NeutronResource):
@staticmethod
def _remove_none_value_props(props):
- if isinstance(props, collections.Mapping):
+ if isinstance(props, collections.abc.Mapping):
return dict((k, L2Gateway._remove_none_value_props(v)) for k, v
in props.items() if v is not None)
- elif (isinstance(props, collections.Sequence) and
+ elif (isinstance(props, collections.abc.Sequence) and
not isinstance(props, str)):
return list(L2Gateway._remove_none_value_props(p) for p in props
if p is not None)
diff --git a/heat/engine/resources/wait_condition.py b/heat/engine/resources/wait_condition.py
index 65caeab91..74de91819 100644
--- a/heat/engine/resources/wait_condition.py
+++ b/heat/engine/resources/wait_condition.py
@@ -57,7 +57,7 @@ class BaseWaitConditionHandle(signal_responder.SignalResponder):
return status in self.WAIT_STATUSES
def _metadata_format_ok(self, metadata):
- if not isinstance(metadata, collections.Mapping):
+ if not isinstance(metadata, collections.abc.Mapping):
return False
if set(metadata) != set(self.METADATA_KEYS):
return False
diff --git a/heat/engine/rsrc_defn.py b/heat/engine/rsrc_defn.py
index 24422376a..04e12eed3 100644
--- a/heat/engine/rsrc_defn.py
+++ b/heat/engine/rsrc_defn.py
@@ -113,17 +113,17 @@ class ResourceDefinition(object):
assert isinstance(self.description, str)
if properties is not None:
- assert isinstance(properties, (collections.Mapping,
+ assert isinstance(properties, (collections.abc.Mapping,
function.Function))
self._hash ^= _hash_data(properties)
if metadata is not None:
- assert isinstance(metadata, (collections.Mapping,
+ assert isinstance(metadata, (collections.abc.Mapping,
function.Function))
self._hash ^= _hash_data(metadata)
if depends is not None:
- assert isinstance(depends, (collections.Sequence,
+ assert isinstance(depends, (collections.abc.Sequence,
function.Function))
assert not isinstance(depends, str)
self._hash ^= _hash_data(depends)
@@ -133,7 +133,7 @@ class ResourceDefinition(object):
self._hash ^= _hash_data(deletion_policy)
if update_policy is not None:
- assert isinstance(update_policy, (collections.Mapping,
+ assert isinstance(update_policy, (collections.abc.Mapping,
function.Function))
self._hash ^= _hash_data(update_policy)
@@ -432,10 +432,10 @@ def _hash_data(data):
data = copy.deepcopy(data)
if not isinstance(data, str):
- if isinstance(data, collections.Sequence):
+ if isinstance(data, collections.abc.Sequence):
return hash(tuple(_hash_data(d) for d in data))
- if isinstance(data, collections.Mapping):
+ if isinstance(data, collections.abc.Mapping):
item_hashes = (hash(k) ^ _hash_data(v) for k, v in data.items())
return functools.reduce(operator.xor, item_hashes, 0)
diff --git a/heat/engine/software_config_io.py b/heat/engine/software_config_io.py
index 6f788554d..3e2906302 100644
--- a/heat/engine/software_config_io.py
+++ b/heat/engine/software_config_io.py
@@ -178,10 +178,14 @@ def check_io_schema_list(io_configs):
Raises TypeError if the list itself is not a list, or if any of the
members are not dicts.
"""
- if (not isinstance(io_configs, collections.Sequence) or
- isinstance(io_configs, collections.Mapping) or
- isinstance(io_configs, str)):
+ if (
+ not isinstance(io_configs, collections.abc.Sequence) or
+ isinstance(io_configs, collections.abc.Mapping) or
+ isinstance(io_configs, str)
+ ):
raise TypeError('Software Config I/O Schema must be in a list')
- if not all(isinstance(conf, collections.Mapping) for conf in io_configs):
+ if not all(
+ isinstance(conf, collections.abc.Mapping) for conf in io_configs
+ ):
raise TypeError('Software Config I/O Schema must be a dict')
diff --git a/heat/engine/stack.py b/heat/engine/stack.py
index be3323b8b..02291d087 100644
--- a/heat/engine/stack.py
+++ b/heat/engine/stack.py
@@ -100,7 +100,7 @@ def reset_state_on_error(func):
return handle_exceptions
-class Stack(collections.Mapping):
+class Stack(collections.abc.Mapping):
ACTIONS = (
CREATE, DELETE, UPDATE, ROLLBACK, SUSPEND, RESUME, ADOPT,
diff --git a/heat/engine/template.py b/heat/engine/template.py
index 1e52c8c92..eece1d004 100644
--- a/heat/engine/template.py
+++ b/heat/engine/template.py
@@ -89,7 +89,7 @@ def get_template_class(template_data):
raise exception.InvalidTemplateVersion(explanation=explanation)
-class Template(collections.Mapping):
+class Template(collections.abc.Mapping):
"""Abstract base class for template format plugins.
All template formats (both internal and third-party) should derive from
@@ -355,7 +355,7 @@ class Template(collections.Mapping):
def parse(functions, stack, snippet, path='', template=None):
recurse = functools.partial(parse, functions, stack, template=template)
- if isinstance(snippet, collections.Mapping):
+ if isinstance(snippet, collections.abc.Mapping):
def mkpath(key):
return '.'.join([path, str(key)])
@@ -380,7 +380,7 @@ def parse(functions, stack, snippet, path='', template=None):
return dict((k, recurse(v, mkpath(k)))
for k, v in snippet.items())
elif (not isinstance(snippet, str) and
- isinstance(snippet, collections.Iterable)):
+ isinstance(snippet, collections.abc.Iterable)):
def mkpath(idx):
return ''.join([path, '[%d]' % idx])
diff --git a/heat/engine/template_common.py b/heat/engine/template_common.py
index f13898dc6..f5d80a509 100644
--- a/heat/engine/template_common.py
+++ b/heat/engine/template_common.py
@@ -80,18 +80,18 @@ class CommonTemplate(template.Template):
yield ('properties',
self._parse_resource_field(self.RES_PROPERTIES,
- (collections.Mapping,
+ (collections.abc.Mapping,
function.Function), 'object',
name, data, parse))
yield ('metadata',
self._parse_resource_field(self.RES_METADATA,
- (collections.Mapping,
+ (collections.abc.Mapping,
function.Function), 'object',
name, data, parse))
depends = self._parse_resource_field(self.RES_DEPENDS_ON,
- collections.Sequence,
+ collections.abc.Sequence,
'list or string',
name, data, no_parse)
if isinstance(depends, str):
@@ -122,7 +122,7 @@ class CommonTemplate(template.Template):
yield ('update_policy',
self._parse_resource_field(self.RES_UPDATE_POLICY,
- (collections.Mapping,
+ (collections.abc.Mapping,
function.Function), 'object',
name, data, parse))
@@ -143,7 +143,7 @@ class CommonTemplate(template.Template):
return cached_conds
raw_defs = self._get_condition_definitions()
- if not isinstance(raw_defs, collections.Mapping):
+ if not isinstance(raw_defs, collections.abc.Mapping):
message = _('Condition definitions must be a map. Found a '
'%s instead') % type(raw_defs).__name__
raise exception.StackValidationFailed(
@@ -166,7 +166,7 @@ class CommonTemplate(template.Template):
def get_outputs():
for key, val in outputs.items():
- if not isinstance(val, collections.Mapping):
+ if not isinstance(val, collections.abc.Mapping):
message = _('Output definitions must be a map. Found a '
'%s instead') % type(val).__name__
raise exception.StackValidationFailed(
diff --git a/heat/engine/template_files.py b/heat/engine/template_files.py
index 93e68b5e6..55a54e0d6 100644
--- a/heat/engine/template_files.py
+++ b/heat/engine/template_files.py
@@ -28,7 +28,7 @@ class ReadOnlyDict(dict):
raise ValueError("Attempted to write to internal TemplateFiles cache")
-class TemplateFiles(collections.Mapping):
+class TemplateFiles(collections.abc.Mapping):
def __init__(self, files):
self.files = None
diff --git a/heat/tests/openstack/nova/test_server.py b/heat/tests/openstack/nova/test_server.py
index f4aec2a81..9b36a533c 100644
--- a/heat/tests/openstack/nova/test_server.py
+++ b/heat/tests/openstack/nova/test_server.py
@@ -3305,7 +3305,7 @@ class ServersTest(common.HeatTestCase):
ws.resource_id = server.id
self.patchobject(self.fc.servers, 'get', return_value=server)
console_urls = ws._resolve_any_attribute('console_urls')
- self.assertIsInstance(console_urls, collections.Mapping)
+ self.assertIsInstance(console_urls, collections.abc.Mapping)
supported_consoles = ('novnc', 'xvpvnc', 'spice-html5', 'rdp-html5',
'serial', 'webmks')
self.assertEqual(set(supported_consoles),
diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py
index 5bad17671..92e06857c 100644
--- a/heat/tests/test_resource.py
+++ b/heat/tests/test_resource.py
@@ -4433,7 +4433,7 @@ class TestResourceMapping(common.HeatTestCase):
def _check_mapping_func(self, func, module):
self.assertTrue(callable(func))
res = func()
- self.assertIsInstance(res, collections.Mapping)
+ self.assertIsInstance(res, collections.abc.Mapping)
for r_type, r_class in res.items():
self.assertIsInstance(r_type, str)
type_elements = r_type.split('::')